Merge "Return SDK_UNAVAILABLE when HealthConnectManager is null" into androidx-main
diff --git a/annotation/annotation/build.gradle b/annotation/annotation/build.gradle
index 3170c7b..0abb57e 100644
--- a/annotation/annotation/build.gradle
+++ b/annotation/annotation/build.gradle
@@ -22,6 +22,8 @@
     linux()
     linuxArm64()
     ios()
+    watchos()
+    tvos()
 
     defaultPlatform(PlatformIdentifier.JVM)
 
@@ -44,7 +46,6 @@
             }
         }
 
-
         // Workaround for https://youtrack.jetbrains.com/issue/KT-51763
         // Make sure commonization runs before any compilation task.
         tasks.withType(KotlinNativeCompile).configureEach {
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/AppCompatDialogTest.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/AppCompatDialogTest.kt
index f8e8717..8ac9df3 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/AppCompatDialogTest.kt
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/AppCompatDialogTest.kt
@@ -17,6 +17,7 @@
 package androidx.appcompat.app
 
 import android.view.View
+import android.view.ViewGroup
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.findViewTreeLifecycleOwner
 import androidx.test.core.app.ActivityScenario
@@ -34,7 +35,7 @@
 class AppCompatDialogTest {
 
     @Test
-    fun testViewTreeLifecycleOwner() {
+    fun testViewTreeLifecycleOwnerWhenSetContentView() {
         withUse(ActivityScenario.launch(AppCompatActivity::class.java)) {
             lateinit var view: View
             val dialog = withActivity {
@@ -60,4 +61,38 @@
                 .isNotSameInstanceAs(lifecycle)
         }
     }
+
+    @Test
+    fun testViewTreeLifecycleOwnerWhenAddContentView() {
+        withUse(ActivityScenario.launch(AppCompatActivity::class.java)) {
+            lateinit var view: View
+            val dialog = withActivity {
+                view = View(this)
+                AppCompatDialog(this)
+            }
+            dialog.addContentView(
+                view,
+                ViewGroup.LayoutParams(
+                    ViewGroup.LayoutParams.MATCH_PARENT,
+                    ViewGroup.LayoutParams.WRAP_CONTENT
+                )
+            )
+
+            val lifecycle = dialog.lifecycle
+            assertThat(lifecycle.currentState).isEqualTo(Lifecycle.State.INITIALIZED)
+
+            onActivity { dialog.show() }
+            assertThat(lifecycle.currentState).isEqualTo(Lifecycle.State.RESUMED)
+
+            val viewOwner = dialog.window?.decorView?.findViewTreeLifecycleOwner()!!
+            assertThat(viewOwner).isEqualTo(dialog)
+
+            onActivity { dialog.dismiss() }
+            assertThat(lifecycle.currentState).isEqualTo(Lifecycle.State.DESTROYED)
+
+            assertWithMessage("A new Lifecycle object should be created after destruction")
+                .that(dialog.lifecycle)
+                .isNotSameInstanceAs(lifecycle)
+        }
+    }
 }
diff --git a/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDialog.java b/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDialog.java
index aa4aff9..6b4759e 100644
--- a/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDialog.java
+++ b/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDialog.java
@@ -140,6 +140,7 @@
 
     @Override
     public void addContentView(@NonNull View view, ViewGroup.LayoutParams params) {
+        initViewTreeOwners();
         getDelegate().addContentView(view, params);
     }
 
diff --git a/benchmark/OWNERS b/benchmark/OWNERS
index 42bca6c..7fc5842 100644
--- a/benchmark/OWNERS
+++ b/benchmark/OWNERS
@@ -3,3 +3,4 @@
 [email protected]
 [email protected]
 [email protected]
[email protected]
\ No newline at end of file
diff --git a/benchmark/baseline-profile-gradle-plugin/src/main/kotlin/androidx/baselineprofile/gradle/utils/Utils.kt b/benchmark/baseline-profile-gradle-plugin/src/main/kotlin/androidx/baselineprofile/gradle/utils/Utils.kt
index c8a8e25..9d51a3b 100644
--- a/benchmark/baseline-profile-gradle-plugin/src/main/kotlin/androidx/baselineprofile/gradle/utils/Utils.kt
+++ b/benchmark/baseline-profile-gradle-plugin/src/main/kotlin/androidx/baselineprofile/gradle/utils/Utils.kt
@@ -16,7 +16,7 @@
 
 package androidx.baselineprofile.gradle.utils
 
-import org.gradle.configurationcache.extensions.capitalized
+import java.util.Locale
 
 fun camelCase(vararg strings: String): String {
     if (strings.isEmpty()) return ""
@@ -30,3 +30,15 @@
         }
         .toString()
 }
+
+private fun CharSequence.capitalized(): String =
+    when {
+        isEmpty() -> ""
+        else ->
+            get(0).let { initial ->
+                when {
+                    initial.isLowerCase() -> initial.titlecase(Locale.getDefault()) + substring(1)
+                    else -> toString()
+                }
+            }
+    }
diff --git a/benchmark/benchmark-common/api/1.3.0-beta02.txt b/benchmark/benchmark-common/api/1.3.0-beta02.txt
new file mode 100644
index 0000000..9df6fae
--- /dev/null
+++ b/benchmark/benchmark-common/api/1.3.0-beta02.txt
@@ -0,0 +1,139 @@
+// Signature format: 4.0
+package androidx.benchmark {
+
+  public final class BenchmarkState {
+    ctor @SuppressCompatibility @androidx.benchmark.ExperimentalBenchmarkStateApi public BenchmarkState(optional Integer? warmupCount, optional Integer? repeatCount);
+    method @SuppressCompatibility @androidx.benchmark.ExperimentalBenchmarkStateApi public java.util.List<java.lang.Double> getMeasurementTimeNs();
+    method public boolean keepRunning();
+    method public void pauseTiming();
+    method @SuppressCompatibility @androidx.benchmark.BenchmarkState.Companion.ExperimentalExternalReport public static void reportData(String className, String testName, @IntRange(from=0L) long totalRunTimeNs, java.util.List<java.lang.Long> dataNs, @IntRange(from=0L) int warmupIterations, @IntRange(from=0L) long thermalThrottleSleepSeconds, @IntRange(from=1L) int repeatIterations);
+    method public void resumeTiming();
+    field public static final androidx.benchmark.BenchmarkState.Companion Companion;
+  }
+
+  public static final class BenchmarkState.Companion {
+    method @SuppressCompatibility @androidx.benchmark.BenchmarkState.Companion.ExperimentalExternalReport public void reportData(String className, String testName, @IntRange(from=0L) long totalRunTimeNs, java.util.List<java.lang.Long> dataNs, @IntRange(from=0L) int warmupIterations, @IntRange(from=0L) long thermalThrottleSleepSeconds, @IntRange(from=1L) int repeatIterations);
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=kotlin.annotation.AnnotationTarget.FUNCTION) public static @interface BenchmarkState.Companion.ExperimentalExternalReport {
+  }
+
+  @SuppressCompatibility @androidx.benchmark.ExperimentalBlackHoleApi public final class BlackHole {
+    method public static void consume(boolean value);
+    method public static void consume(byte value);
+    method public static void consume(char value);
+    method public static void consume(double value);
+    method public static void consume(float value);
+    method public static void consume(int value);
+    method public static void consume(Object value);
+    method public static void consume(long value);
+    method public static void consume(short value);
+    field public static final androidx.benchmark.BlackHole INSTANCE;
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalBenchmarkConfigApi {
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalBenchmarkStateApi {
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalBlackHoleApi {
+  }
+
+  @SuppressCompatibility @androidx.benchmark.ExperimentalBenchmarkConfigApi public abstract class MetricCapture {
+    ctor public MetricCapture(java.util.List<java.lang.String> names);
+    method public abstract void capturePaused();
+    method public abstract void captureResumed();
+    method public abstract void captureStart(long timeNs);
+    method public abstract void captureStop(long timeNs, long[] output, int offset);
+    method public final java.util.List<java.lang.String> getNames();
+    property public final java.util.List<java.lang.String> names;
+  }
+
+  @SuppressCompatibility @androidx.benchmark.ExperimentalBenchmarkConfigApi public final class MicrobenchmarkConfig {
+    ctor public MicrobenchmarkConfig(optional java.util.List<? extends androidx.benchmark.MetricCapture> metrics, optional boolean traceAppTagEnabled, optional boolean perfettoSdkTracingEnabled, optional androidx.benchmark.ProfilerConfig? profiler);
+    method public java.util.List<androidx.benchmark.MetricCapture> getMetrics();
+    method public androidx.benchmark.ProfilerConfig? getProfiler();
+    method public boolean isPerfettoSdkTracingEnabled();
+    method public boolean isTraceAppTagEnabled();
+    property public final java.util.List<androidx.benchmark.MetricCapture> metrics;
+    property public final boolean perfettoSdkTracingEnabled;
+    property public final androidx.benchmark.ProfilerConfig? profiler;
+    property public final boolean traceAppTagEnabled;
+  }
+
+  @SuppressCompatibility @androidx.benchmark.ExperimentalBenchmarkConfigApi public abstract sealed class ProfilerConfig {
+  }
+
+  public static final class ProfilerConfig.MethodTracing extends androidx.benchmark.ProfilerConfig {
+    ctor public ProfilerConfig.MethodTracing();
+    field public static final boolean AFFECTS_MEASUREMENTS_ON_THIS_DEVICE;
+    field public static final androidx.benchmark.ProfilerConfig.MethodTracing.Companion Companion;
+  }
+
+  public static final class ProfilerConfig.MethodTracing.Companion {
+  }
+
+  public static final class ProfilerConfig.StackSampling extends androidx.benchmark.ProfilerConfig {
+    ctor public ProfilerConfig.StackSampling();
+  }
+
+  @SuppressCompatibility @androidx.benchmark.ExperimentalBenchmarkConfigApi public final class TimeCapture extends androidx.benchmark.MetricCapture {
+    ctor public TimeCapture();
+    ctor public TimeCapture(optional String name);
+    method public void capturePaused();
+    method public void captureResumed();
+    method public void captureStart(long timeNs);
+    method public void captureStop(long timeNs, long[] output, int offset);
+  }
+
+}
+
+package androidx.benchmark.perfetto {
+
+  @SuppressCompatibility @kotlin.RequiresOptIn @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.CLASS, kotlin.annotation.AnnotationTarget.FUNCTION}) public @interface ExperimentalPerfettoCaptureApi {
+  }
+
+  @SuppressCompatibility @androidx.benchmark.perfetto.ExperimentalPerfettoCaptureApi public abstract sealed class PerfettoConfig {
+  }
+
+  public static final class PerfettoConfig.Binary extends androidx.benchmark.perfetto.PerfettoConfig {
+    ctor public PerfettoConfig.Binary(byte[] bytes);
+    method public byte[] getBytes();
+    property public final byte[] bytes;
+  }
+
+  public static final class PerfettoConfig.Text extends androidx.benchmark.perfetto.PerfettoConfig {
+    ctor public PerfettoConfig.Text(String text);
+    method public String getText();
+    property public final String text;
+  }
+
+  @SuppressCompatibility @RequiresApi(23) @androidx.benchmark.perfetto.ExperimentalPerfettoCaptureApi public final class PerfettoTrace {
+    ctor public PerfettoTrace(String path);
+    method public String getPath();
+    method public static void record(String fileLabel, androidx.benchmark.perfetto.PerfettoConfig config, optional String highlightPackage, optional String? userspaceTracingPackage, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method public static void record(String fileLabel, androidx.benchmark.perfetto.PerfettoConfig config, optional String highlightPackage, optional String? userspaceTracingPackage, optional kotlin.jvm.functions.Function1<? super androidx.benchmark.perfetto.PerfettoTrace,kotlin.Unit>? traceCallback, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method public static void record(String fileLabel, androidx.benchmark.perfetto.PerfettoConfig config, optional String highlightPackage, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method public static void record(String fileLabel, androidx.benchmark.perfetto.PerfettoConfig config, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method public static void record(String fileLabel, optional java.util.List<java.lang.String> appTagPackages, optional String? userspaceTracingPackage, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method public static void record(String fileLabel, optional java.util.List<java.lang.String> appTagPackages, optional String? userspaceTracingPackage, optional kotlin.jvm.functions.Function1<? super androidx.benchmark.perfetto.PerfettoTrace,kotlin.Unit>? traceCallback, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method public static void record(String fileLabel, optional java.util.List<java.lang.String> appTagPackages, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method public static void record(String fileLabel, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    property public final String path;
+    field public static final androidx.benchmark.perfetto.PerfettoTrace.Companion Companion;
+  }
+
+  public static final class PerfettoTrace.Companion {
+    method public void record(String fileLabel, androidx.benchmark.perfetto.PerfettoConfig config, optional String highlightPackage, optional String? userspaceTracingPackage, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method public void record(String fileLabel, androidx.benchmark.perfetto.PerfettoConfig config, optional String highlightPackage, optional String? userspaceTracingPackage, optional kotlin.jvm.functions.Function1<? super androidx.benchmark.perfetto.PerfettoTrace,kotlin.Unit>? traceCallback, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method public void record(String fileLabel, androidx.benchmark.perfetto.PerfettoConfig config, optional String highlightPackage, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method public void record(String fileLabel, androidx.benchmark.perfetto.PerfettoConfig config, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method public void record(String fileLabel, optional java.util.List<java.lang.String> appTagPackages, optional String? userspaceTracingPackage, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method public void record(String fileLabel, optional java.util.List<java.lang.String> appTagPackages, optional String? userspaceTracingPackage, optional kotlin.jvm.functions.Function1<? super androidx.benchmark.perfetto.PerfettoTrace,kotlin.Unit>? traceCallback, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method public void record(String fileLabel, optional java.util.List<java.lang.String> appTagPackages, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method public void record(String fileLabel, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+  }
+
+}
+
diff --git a/benchmark/benchmark-common/api/res-1.3.0-beta02.txt b/benchmark/benchmark-common/api/res-1.3.0-beta02.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/benchmark/benchmark-common/api/res-1.3.0-beta02.txt
diff --git a/benchmark/benchmark-common/api/restricted_1.3.0-beta02.txt b/benchmark/benchmark-common/api/restricted_1.3.0-beta02.txt
new file mode 100644
index 0000000..e2bfb40
--- /dev/null
+++ b/benchmark/benchmark-common/api/restricted_1.3.0-beta02.txt
@@ -0,0 +1,141 @@
+// Signature format: 4.0
+package androidx.benchmark {
+
+  public final class BenchmarkState {
+    ctor @SuppressCompatibility @androidx.benchmark.ExperimentalBenchmarkStateApi public BenchmarkState(optional Integer? warmupCount, optional Integer? repeatCount);
+    method @SuppressCompatibility @androidx.benchmark.ExperimentalBenchmarkStateApi public java.util.List<java.lang.Double> getMeasurementTimeNs();
+    method public boolean keepRunning();
+    method @kotlin.PublishedApi internal boolean keepRunningInternal();
+    method public void pauseTiming();
+    method @SuppressCompatibility @androidx.benchmark.BenchmarkState.Companion.ExperimentalExternalReport public static void reportData(String className, String testName, @IntRange(from=0L) long totalRunTimeNs, java.util.List<java.lang.Long> dataNs, @IntRange(from=0L) int warmupIterations, @IntRange(from=0L) long thermalThrottleSleepSeconds, @IntRange(from=1L) int repeatIterations);
+    method public void resumeTiming();
+    field public static final androidx.benchmark.BenchmarkState.Companion Companion;
+    field @kotlin.PublishedApi internal int iterationsRemaining;
+  }
+
+  public static final class BenchmarkState.Companion {
+    method @SuppressCompatibility @androidx.benchmark.BenchmarkState.Companion.ExperimentalExternalReport public void reportData(String className, String testName, @IntRange(from=0L) long totalRunTimeNs, java.util.List<java.lang.Long> dataNs, @IntRange(from=0L) int warmupIterations, @IntRange(from=0L) long thermalThrottleSleepSeconds, @IntRange(from=1L) int repeatIterations);
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=kotlin.annotation.AnnotationTarget.FUNCTION) public static @interface BenchmarkState.Companion.ExperimentalExternalReport {
+  }
+
+  @SuppressCompatibility @androidx.benchmark.ExperimentalBlackHoleApi public final class BlackHole {
+    method public static void consume(boolean value);
+    method public static void consume(byte value);
+    method public static void consume(char value);
+    method public static void consume(double value);
+    method public static void consume(float value);
+    method public static void consume(int value);
+    method public static void consume(Object value);
+    method public static void consume(long value);
+    method public static void consume(short value);
+    field public static final androidx.benchmark.BlackHole INSTANCE;
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalBenchmarkConfigApi {
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalBenchmarkStateApi {
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalBlackHoleApi {
+  }
+
+  @SuppressCompatibility @androidx.benchmark.ExperimentalBenchmarkConfigApi public abstract class MetricCapture {
+    ctor public MetricCapture(java.util.List<java.lang.String> names);
+    method public abstract void capturePaused();
+    method public abstract void captureResumed();
+    method public abstract void captureStart(long timeNs);
+    method public abstract void captureStop(long timeNs, long[] output, int offset);
+    method public final java.util.List<java.lang.String> getNames();
+    property public final java.util.List<java.lang.String> names;
+  }
+
+  @SuppressCompatibility @androidx.benchmark.ExperimentalBenchmarkConfigApi public final class MicrobenchmarkConfig {
+    ctor public MicrobenchmarkConfig(optional java.util.List<? extends androidx.benchmark.MetricCapture> metrics, optional boolean traceAppTagEnabled, optional boolean perfettoSdkTracingEnabled, optional androidx.benchmark.ProfilerConfig? profiler);
+    method public java.util.List<androidx.benchmark.MetricCapture> getMetrics();
+    method public androidx.benchmark.ProfilerConfig? getProfiler();
+    method public boolean isPerfettoSdkTracingEnabled();
+    method public boolean isTraceAppTagEnabled();
+    property public final java.util.List<androidx.benchmark.MetricCapture> metrics;
+    property public final boolean perfettoSdkTracingEnabled;
+    property public final androidx.benchmark.ProfilerConfig? profiler;
+    property public final boolean traceAppTagEnabled;
+  }
+
+  @SuppressCompatibility @androidx.benchmark.ExperimentalBenchmarkConfigApi public abstract sealed class ProfilerConfig {
+  }
+
+  public static final class ProfilerConfig.MethodTracing extends androidx.benchmark.ProfilerConfig {
+    ctor public ProfilerConfig.MethodTracing();
+    field public static final boolean AFFECTS_MEASUREMENTS_ON_THIS_DEVICE;
+    field public static final androidx.benchmark.ProfilerConfig.MethodTracing.Companion Companion;
+  }
+
+  public static final class ProfilerConfig.MethodTracing.Companion {
+  }
+
+  public static final class ProfilerConfig.StackSampling extends androidx.benchmark.ProfilerConfig {
+    ctor public ProfilerConfig.StackSampling();
+  }
+
+  @SuppressCompatibility @androidx.benchmark.ExperimentalBenchmarkConfigApi public final class TimeCapture extends androidx.benchmark.MetricCapture {
+    ctor public TimeCapture();
+    ctor public TimeCapture(optional String name);
+    method public void capturePaused();
+    method public void captureResumed();
+    method public void captureStart(long timeNs);
+    method public void captureStop(long timeNs, long[] output, int offset);
+  }
+
+}
+
+package androidx.benchmark.perfetto {
+
+  @SuppressCompatibility @kotlin.RequiresOptIn @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.CLASS, kotlin.annotation.AnnotationTarget.FUNCTION}) public @interface ExperimentalPerfettoCaptureApi {
+  }
+
+  @SuppressCompatibility @androidx.benchmark.perfetto.ExperimentalPerfettoCaptureApi public abstract sealed class PerfettoConfig {
+  }
+
+  public static final class PerfettoConfig.Binary extends androidx.benchmark.perfetto.PerfettoConfig {
+    ctor public PerfettoConfig.Binary(byte[] bytes);
+    method public byte[] getBytes();
+    property public final byte[] bytes;
+  }
+
+  public static final class PerfettoConfig.Text extends androidx.benchmark.perfetto.PerfettoConfig {
+    ctor public PerfettoConfig.Text(String text);
+    method public String getText();
+    property public final String text;
+  }
+
+  @SuppressCompatibility @RequiresApi(23) @androidx.benchmark.perfetto.ExperimentalPerfettoCaptureApi public final class PerfettoTrace {
+    ctor public PerfettoTrace(String path);
+    method public String getPath();
+    method public static void record(String fileLabel, androidx.benchmark.perfetto.PerfettoConfig config, optional String highlightPackage, optional String? userspaceTracingPackage, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method public static void record(String fileLabel, androidx.benchmark.perfetto.PerfettoConfig config, optional String highlightPackage, optional String? userspaceTracingPackage, optional kotlin.jvm.functions.Function1<? super androidx.benchmark.perfetto.PerfettoTrace,kotlin.Unit>? traceCallback, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method public static void record(String fileLabel, androidx.benchmark.perfetto.PerfettoConfig config, optional String highlightPackage, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method public static void record(String fileLabel, androidx.benchmark.perfetto.PerfettoConfig config, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method public static void record(String fileLabel, optional java.util.List<java.lang.String> appTagPackages, optional String? userspaceTracingPackage, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method public static void record(String fileLabel, optional java.util.List<java.lang.String> appTagPackages, optional String? userspaceTracingPackage, optional kotlin.jvm.functions.Function1<? super androidx.benchmark.perfetto.PerfettoTrace,kotlin.Unit>? traceCallback, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method public static void record(String fileLabel, optional java.util.List<java.lang.String> appTagPackages, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method public static void record(String fileLabel, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    property public final String path;
+    field public static final androidx.benchmark.perfetto.PerfettoTrace.Companion Companion;
+  }
+
+  public static final class PerfettoTrace.Companion {
+    method public void record(String fileLabel, androidx.benchmark.perfetto.PerfettoConfig config, optional String highlightPackage, optional String? userspaceTracingPackage, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method public void record(String fileLabel, androidx.benchmark.perfetto.PerfettoConfig config, optional String highlightPackage, optional String? userspaceTracingPackage, optional kotlin.jvm.functions.Function1<? super androidx.benchmark.perfetto.PerfettoTrace,kotlin.Unit>? traceCallback, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method public void record(String fileLabel, androidx.benchmark.perfetto.PerfettoConfig config, optional String highlightPackage, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method public void record(String fileLabel, androidx.benchmark.perfetto.PerfettoConfig config, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method public void record(String fileLabel, optional java.util.List<java.lang.String> appTagPackages, optional String? userspaceTracingPackage, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method public void record(String fileLabel, optional java.util.List<java.lang.String> appTagPackages, optional String? userspaceTracingPackage, optional kotlin.jvm.functions.Function1<? super androidx.benchmark.perfetto.PerfettoTrace,kotlin.Unit>? traceCallback, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method public void record(String fileLabel, optional java.util.List<java.lang.String> appTagPackages, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method public void record(String fileLabel, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+  }
+
+}
+
diff --git a/benchmark/benchmark-common/src/androidTest/java/androidx/benchmark/PerfettoHelperTest.kt b/benchmark/benchmark-common/src/androidTest/java/androidx/benchmark/PerfettoHelperTest.kt
index 8097084b..59bced6 100644
--- a/benchmark/benchmark-common/src/androidTest/java/androidx/benchmark/PerfettoHelperTest.kt
+++ b/benchmark/benchmark-common/src/androidTest/java/androidx/benchmark/PerfettoHelperTest.kt
@@ -26,6 +26,7 @@
 import kotlin.test.assertEquals
 import kotlin.test.assertFalse
 import kotlin.test.assertNotEquals
+import kotlin.test.assertNotNull
 import kotlin.test.assertTrue
 import org.junit.After
 import org.junit.Assume
@@ -82,4 +83,20 @@
 
         validateStopAllPerfettoProcesses(unbundled = true)
     }
+
+    @Test
+    fun parserPerfettoCommand() {
+        val pid = 8092
+        val exitCode = 0
+        val output =
+            """
+            $pid
+            EXITCODE=$exitCode
+        """
+                .trimIndent()
+        val parseResult = PerfettoHelper.parsePerfettoCommandOutput(output)
+        assertNotNull(parseResult)
+        assertEquals(parseResult.first, exitCode)
+        assertEquals(parseResult.second, pid)
+    }
 }
diff --git a/benchmark/benchmark-common/src/androidTest/java/androidx/benchmark/json/BenchmarkDataTest.kt b/benchmark/benchmark-common/src/androidTest/java/androidx/benchmark/json/BenchmarkDataTest.kt
index 4e7344d..2a1050e 100644
--- a/benchmark/benchmark-common/src/androidTest/java/androidx/benchmark/json/BenchmarkDataTest.kt
+++ b/benchmark/benchmark-common/src/androidTest/java/androidx/benchmark/json/BenchmarkDataTest.kt
@@ -122,7 +122,7 @@
                 // check we're not incorrectly parsing R from "REL"
                 assertNotEquals("R", this)
             }
-            if (Build.VERSION.SDK_INT != 23) {
+            if (Build.VERSION.SDK_INT !in listOf(23, 35)) {
                 // check we're not incorrectly parsing M from "MAIN"
                 assertNotEquals("M", this)
             }
diff --git a/benchmark/benchmark-common/src/main/java/androidx/benchmark/perfetto/PerfettoHelper.kt b/benchmark/benchmark-common/src/main/java/androidx/benchmark/perfetto/PerfettoHelper.kt
index 63796be..08bc5aa 100644
--- a/benchmark/benchmark-common/src/main/java/androidx/benchmark/perfetto/PerfettoHelper.kt
+++ b/benchmark/benchmark-common/src/main/java/androidx/benchmark/perfetto/PerfettoHelper.kt
@@ -130,15 +130,30 @@
                     .stdout
                     .trim()
 
-            val expectedSuffix = "\nEXITCODE=0"
-            if (!perfettoCmdOutput.endsWith(expectedSuffix)) {
-                throw perfettoStartupException(
-                    "Perfetto unexpected exit code, output = $perfettoCmdOutput",
-                    null
+            Log.i(LOG_TAG, "Perfetto output - $perfettoCmdOutput")
+            val parseResult = parsePerfettoCommandOutput(perfettoCmdOutput)
+            check(parseResult != null) {
+                "Perfetto unexpected exit code, output = $perfettoCmdOutput"
+            }
+            val (exitCode, pid) = parseResult
+            check(exitCode == 0 || exitCode == 2) {
+                "Perfetto unexpected exit code, output = $perfettoCmdOutput"
+            }
+            if (exitCode == 2) {
+                // https://source.corp.google.com/h/googleplex-android/platform/superproject/main/+/main:external/perfetto/src/perfetto_cmd/perfetto_cmd.h;l=109;drc=c244200710b3089cb4a3c24fe6e3ee5f6fd0f8df
+                // This means some of the data sources that Perfetto is using are not ready.
+                // Perfetto already logs which data sources are not ready, so we don't need to do
+                // any additional reporting here.
+                Log.w(
+                    LOG_TAG,
+                    """
+                        Some perfetto data sources may not be ready.
+                        Look at the `perfetto` log tag for additional information.
+                    """
+                        .trimIndent()
                 )
             }
-            Log.i(LOG_TAG, "Perfetto output - $perfettoCmdOutput")
-            perfettoPid = perfettoCmdOutput.removeSuffix(expectedSuffix).toInt()
+            perfettoPid = pid
         } catch (ioe: IOException) {
             throw perfettoStartupException("Unable to start perfetto tracing", ioe)
         }
@@ -427,6 +442,29 @@
             }
         }
 
+        private val PERFETTO_COMMAND_OUTPUT_REGEX =
+            """(?<pid>\d+)(?<whitespace>\W+)?EXITCODE=(?<code>\d+)$""".toRegex()
+
+        /**
+         * Parses the output of the perfetto start command, and pulls the `exitCode` and the `pid`
+         * of the process from the output.
+         */
+        fun parsePerfettoCommandOutput(output: String): Pair<Int, Int>? {
+            val matchResult = PERFETTO_COMMAND_OUTPUT_REGEX.matchEntire(output)
+            return if (matchResult == null) {
+                null
+            } else {
+                // Using named groups requires API 26.
+                val pid = matchResult.groups[1]?.value?.toIntOrNull()
+                val exitCode = matchResult.groups[3]?.value?.toIntOrNull()
+                if (pid != null && exitCode != null) {
+                    exitCode to pid
+                } else {
+                    null
+                }
+            }
+        }
+
         public fun stopAllPerfettoProcesses() {
             listOf("perfetto", "tracebox").forEach { processName ->
                 Shell.terminateProcessesAndWait(
diff --git a/benchmark/benchmark-junit4/api/1.3.0-beta02.txt b/benchmark/benchmark-junit4/api/1.3.0-beta02.txt
new file mode 100644
index 0000000..fc4b392
--- /dev/null
+++ b/benchmark/benchmark-junit4/api/1.3.0-beta02.txt
@@ -0,0 +1,36 @@
+// Signature format: 4.0
+package androidx.benchmark.junit4 {
+
+  public class AndroidBenchmarkRunner extends androidx.test.runner.AndroidJUnitRunner {
+    ctor public AndroidBenchmarkRunner();
+  }
+
+  public final class BenchmarkRule implements org.junit.rules.TestRule {
+    ctor public BenchmarkRule();
+    ctor @SuppressCompatibility @androidx.benchmark.ExperimentalBenchmarkConfigApi public BenchmarkRule(androidx.benchmark.MicrobenchmarkConfig config);
+    method public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description description);
+    method public androidx.benchmark.BenchmarkState getState();
+  }
+
+  public final class BenchmarkRule.Scope {
+    method public inline <T> T runWithTimingDisabled(kotlin.jvm.functions.Function0<? extends T> block);
+  }
+
+  public final class BenchmarkRuleKt {
+    method public static inline void measureRepeated(androidx.benchmark.junit4.BenchmarkRule, kotlin.jvm.functions.Function1<? super androidx.benchmark.junit4.BenchmarkRule.Scope,kotlin.Unit> block);
+    method public static inline void measureRepeatedOnMainThread(androidx.benchmark.junit4.BenchmarkRule, kotlin.jvm.functions.Function1<? super androidx.benchmark.junit4.BenchmarkRule.Scope,kotlin.Unit> block);
+  }
+
+  @SuppressCompatibility @androidx.benchmark.perfetto.ExperimentalPerfettoCaptureApi public final class PerfettoTraceRule implements org.junit.rules.TestRule {
+    ctor public PerfettoTraceRule(optional boolean enableAppTagTracing, optional boolean enableUserspaceTracing, optional kotlin.jvm.functions.Function1<? super androidx.benchmark.perfetto.PerfettoTrace,kotlin.Unit>? traceCallback);
+    method public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description description);
+    method public boolean getEnableAppTagTracing();
+    method public boolean getEnableUserspaceTracing();
+    method public kotlin.jvm.functions.Function1<androidx.benchmark.perfetto.PerfettoTrace,kotlin.Unit>? getTraceCallback();
+    property public final boolean enableAppTagTracing;
+    property public final boolean enableUserspaceTracing;
+    property public final kotlin.jvm.functions.Function1<androidx.benchmark.perfetto.PerfettoTrace,kotlin.Unit>? traceCallback;
+  }
+
+}
+
diff --git a/benchmark/benchmark-junit4/api/res-1.3.0-beta02.txt b/benchmark/benchmark-junit4/api/res-1.3.0-beta02.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/benchmark/benchmark-junit4/api/res-1.3.0-beta02.txt
diff --git a/benchmark/benchmark-junit4/api/restricted_1.3.0-beta02.txt b/benchmark/benchmark-junit4/api/restricted_1.3.0-beta02.txt
new file mode 100644
index 0000000..6aac49d
--- /dev/null
+++ b/benchmark/benchmark-junit4/api/restricted_1.3.0-beta02.txt
@@ -0,0 +1,37 @@
+// Signature format: 4.0
+package androidx.benchmark.junit4 {
+
+  public class AndroidBenchmarkRunner extends androidx.test.runner.AndroidJUnitRunner {
+    ctor public AndroidBenchmarkRunner();
+  }
+
+  public final class BenchmarkRule implements org.junit.rules.TestRule {
+    ctor public BenchmarkRule();
+    ctor @SuppressCompatibility @androidx.benchmark.ExperimentalBenchmarkConfigApi public BenchmarkRule(androidx.benchmark.MicrobenchmarkConfig config);
+    method public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description description);
+    method public androidx.benchmark.BenchmarkState getState();
+  }
+
+  public final class BenchmarkRule.Scope {
+    method @kotlin.PublishedApi internal androidx.benchmark.BenchmarkState getOuterState();
+    method public inline <T> T runWithTimingDisabled(kotlin.jvm.functions.Function0<? extends T> block);
+  }
+
+  public final class BenchmarkRuleKt {
+    method public static inline void measureRepeated(androidx.benchmark.junit4.BenchmarkRule, kotlin.jvm.functions.Function1<? super androidx.benchmark.junit4.BenchmarkRule.Scope,kotlin.Unit> block);
+    method public static inline void measureRepeatedOnMainThread(androidx.benchmark.junit4.BenchmarkRule, kotlin.jvm.functions.Function1<? super androidx.benchmark.junit4.BenchmarkRule.Scope,kotlin.Unit> block);
+  }
+
+  @SuppressCompatibility @androidx.benchmark.perfetto.ExperimentalPerfettoCaptureApi public final class PerfettoTraceRule implements org.junit.rules.TestRule {
+    ctor public PerfettoTraceRule(optional boolean enableAppTagTracing, optional boolean enableUserspaceTracing, optional kotlin.jvm.functions.Function1<? super androidx.benchmark.perfetto.PerfettoTrace,kotlin.Unit>? traceCallback);
+    method public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description description);
+    method public boolean getEnableAppTagTracing();
+    method public boolean getEnableUserspaceTracing();
+    method public kotlin.jvm.functions.Function1<androidx.benchmark.perfetto.PerfettoTrace,kotlin.Unit>? getTraceCallback();
+    property public final boolean enableAppTagTracing;
+    property public final boolean enableUserspaceTracing;
+    property public final kotlin.jvm.functions.Function1<androidx.benchmark.perfetto.PerfettoTrace,kotlin.Unit>? traceCallback;
+  }
+
+}
+
diff --git a/benchmark/benchmark-macro-junit4/api/1.3.0-beta02.txt b/benchmark/benchmark-macro-junit4/api/1.3.0-beta02.txt
new file mode 100644
index 0000000..e06bf57
--- /dev/null
+++ b/benchmark/benchmark-macro-junit4/api/1.3.0-beta02.txt
@@ -0,0 +1,30 @@
+// Signature format: 4.0
+package androidx.benchmark.macro.junit4 {
+
+  @RequiresApi(28) public final class BaselineProfileRule implements org.junit.rules.TestRule {
+    ctor public BaselineProfileRule();
+    method public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description description);
+    method public void collect(String packageName, optional int maxIterations, optional int stableIterations, optional String? outputFilePrefix, optional boolean includeInStartupProfile, optional boolean strictStability, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+    method public void collect(String packageName, optional int maxIterations, optional int stableIterations, optional String? outputFilePrefix, optional boolean includeInStartupProfile, optional boolean strictStability, optional kotlin.jvm.functions.Function1<? super java.lang.String,java.lang.Boolean> filterPredicate, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+    method public void collect(String packageName, optional int maxIterations, optional int stableIterations, optional String? outputFilePrefix, optional boolean includeInStartupProfile, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+    method public void collect(String packageName, optional int maxIterations, optional int stableIterations, optional String? outputFilePrefix, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+    method public void collect(String packageName, optional int maxIterations, optional int stableIterations, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+    method public void collect(String packageName, optional int maxIterations, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+    method public void collect(String packageName, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+  }
+
+  public final class MacrobenchmarkRule implements org.junit.rules.TestRule {
+    ctor public MacrobenchmarkRule();
+    method public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description description);
+    method public void measureRepeated(String packageName, java.util.List<? extends androidx.benchmark.macro.Metric> metrics, optional androidx.benchmark.macro.CompilationMode compilationMode, optional androidx.benchmark.macro.StartupMode? startupMode, @IntRange(from=1L) int iterations, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> measureBlock);
+    method public void measureRepeated(String packageName, java.util.List<? extends androidx.benchmark.macro.Metric> metrics, optional androidx.benchmark.macro.CompilationMode compilationMode, optional androidx.benchmark.macro.StartupMode? startupMode, @IntRange(from=1L) int iterations, optional kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> setupBlock, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> measureBlock);
+    method public void measureRepeated(String packageName, java.util.List<? extends androidx.benchmark.macro.Metric> metrics, optional androidx.benchmark.macro.CompilationMode compilationMode, @IntRange(from=1L) int iterations, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> measureBlock);
+    method @SuppressCompatibility @androidx.benchmark.perfetto.ExperimentalPerfettoCaptureApi public void measureRepeated(String packageName, java.util.List<? extends androidx.benchmark.macro.Metric> metrics, @IntRange(from=1L) int iterations, androidx.benchmark.perfetto.PerfettoConfig perfettoConfig, optional androidx.benchmark.macro.CompilationMode compilationMode, optional androidx.benchmark.macro.StartupMode? startupMode, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> measureBlock);
+    method @SuppressCompatibility @androidx.benchmark.perfetto.ExperimentalPerfettoCaptureApi public void measureRepeated(String packageName, java.util.List<? extends androidx.benchmark.macro.Metric> metrics, @IntRange(from=1L) int iterations, androidx.benchmark.perfetto.PerfettoConfig perfettoConfig, optional androidx.benchmark.macro.CompilationMode compilationMode, optional androidx.benchmark.macro.StartupMode? startupMode, optional kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> setupBlock, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> measureBlock);
+    method @SuppressCompatibility @androidx.benchmark.perfetto.ExperimentalPerfettoCaptureApi public void measureRepeated(String packageName, java.util.List<? extends androidx.benchmark.macro.Metric> metrics, @IntRange(from=1L) int iterations, androidx.benchmark.perfetto.PerfettoConfig perfettoConfig, optional androidx.benchmark.macro.CompilationMode compilationMode, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> measureBlock);
+    method @SuppressCompatibility @androidx.benchmark.perfetto.ExperimentalPerfettoCaptureApi public void measureRepeated(String packageName, java.util.List<? extends androidx.benchmark.macro.Metric> metrics, @IntRange(from=1L) int iterations, androidx.benchmark.perfetto.PerfettoConfig perfettoConfig, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> measureBlock);
+    method public void measureRepeated(String packageName, java.util.List<? extends androidx.benchmark.macro.Metric> metrics, @IntRange(from=1L) int iterations, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> measureBlock);
+  }
+
+}
+
diff --git a/benchmark/benchmark-macro-junit4/api/res-1.3.0-beta02.txt b/benchmark/benchmark-macro-junit4/api/res-1.3.0-beta02.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/benchmark/benchmark-macro-junit4/api/res-1.3.0-beta02.txt
diff --git a/benchmark/benchmark-macro-junit4/api/restricted_1.3.0-beta02.txt b/benchmark/benchmark-macro-junit4/api/restricted_1.3.0-beta02.txt
new file mode 100644
index 0000000..e06bf57
--- /dev/null
+++ b/benchmark/benchmark-macro-junit4/api/restricted_1.3.0-beta02.txt
@@ -0,0 +1,30 @@
+// Signature format: 4.0
+package androidx.benchmark.macro.junit4 {
+
+  @RequiresApi(28) public final class BaselineProfileRule implements org.junit.rules.TestRule {
+    ctor public BaselineProfileRule();
+    method public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description description);
+    method public void collect(String packageName, optional int maxIterations, optional int stableIterations, optional String? outputFilePrefix, optional boolean includeInStartupProfile, optional boolean strictStability, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+    method public void collect(String packageName, optional int maxIterations, optional int stableIterations, optional String? outputFilePrefix, optional boolean includeInStartupProfile, optional boolean strictStability, optional kotlin.jvm.functions.Function1<? super java.lang.String,java.lang.Boolean> filterPredicate, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+    method public void collect(String packageName, optional int maxIterations, optional int stableIterations, optional String? outputFilePrefix, optional boolean includeInStartupProfile, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+    method public void collect(String packageName, optional int maxIterations, optional int stableIterations, optional String? outputFilePrefix, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+    method public void collect(String packageName, optional int maxIterations, optional int stableIterations, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+    method public void collect(String packageName, optional int maxIterations, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+    method public void collect(String packageName, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+  }
+
+  public final class MacrobenchmarkRule implements org.junit.rules.TestRule {
+    ctor public MacrobenchmarkRule();
+    method public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description description);
+    method public void measureRepeated(String packageName, java.util.List<? extends androidx.benchmark.macro.Metric> metrics, optional androidx.benchmark.macro.CompilationMode compilationMode, optional androidx.benchmark.macro.StartupMode? startupMode, @IntRange(from=1L) int iterations, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> measureBlock);
+    method public void measureRepeated(String packageName, java.util.List<? extends androidx.benchmark.macro.Metric> metrics, optional androidx.benchmark.macro.CompilationMode compilationMode, optional androidx.benchmark.macro.StartupMode? startupMode, @IntRange(from=1L) int iterations, optional kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> setupBlock, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> measureBlock);
+    method public void measureRepeated(String packageName, java.util.List<? extends androidx.benchmark.macro.Metric> metrics, optional androidx.benchmark.macro.CompilationMode compilationMode, @IntRange(from=1L) int iterations, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> measureBlock);
+    method @SuppressCompatibility @androidx.benchmark.perfetto.ExperimentalPerfettoCaptureApi public void measureRepeated(String packageName, java.util.List<? extends androidx.benchmark.macro.Metric> metrics, @IntRange(from=1L) int iterations, androidx.benchmark.perfetto.PerfettoConfig perfettoConfig, optional androidx.benchmark.macro.CompilationMode compilationMode, optional androidx.benchmark.macro.StartupMode? startupMode, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> measureBlock);
+    method @SuppressCompatibility @androidx.benchmark.perfetto.ExperimentalPerfettoCaptureApi public void measureRepeated(String packageName, java.util.List<? extends androidx.benchmark.macro.Metric> metrics, @IntRange(from=1L) int iterations, androidx.benchmark.perfetto.PerfettoConfig perfettoConfig, optional androidx.benchmark.macro.CompilationMode compilationMode, optional androidx.benchmark.macro.StartupMode? startupMode, optional kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> setupBlock, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> measureBlock);
+    method @SuppressCompatibility @androidx.benchmark.perfetto.ExperimentalPerfettoCaptureApi public void measureRepeated(String packageName, java.util.List<? extends androidx.benchmark.macro.Metric> metrics, @IntRange(from=1L) int iterations, androidx.benchmark.perfetto.PerfettoConfig perfettoConfig, optional androidx.benchmark.macro.CompilationMode compilationMode, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> measureBlock);
+    method @SuppressCompatibility @androidx.benchmark.perfetto.ExperimentalPerfettoCaptureApi public void measureRepeated(String packageName, java.util.List<? extends androidx.benchmark.macro.Metric> metrics, @IntRange(from=1L) int iterations, androidx.benchmark.perfetto.PerfettoConfig perfettoConfig, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> measureBlock);
+    method public void measureRepeated(String packageName, java.util.List<? extends androidx.benchmark.macro.Metric> metrics, @IntRange(from=1L) int iterations, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> measureBlock);
+  }
+
+}
+
diff --git a/benchmark/benchmark-macro/api/1.3.0-beta02.txt b/benchmark/benchmark-macro/api/1.3.0-beta02.txt
new file mode 100644
index 0000000..ad9fb40
--- /dev/null
+++ b/benchmark/benchmark-macro/api/1.3.0-beta02.txt
@@ -0,0 +1,281 @@
+// Signature format: 4.0
+package androidx.benchmark.macro {
+
+  public enum BaselineProfileMode {
+    enum_constant public static final androidx.benchmark.macro.BaselineProfileMode Disable;
+    enum_constant public static final androidx.benchmark.macro.BaselineProfileMode Require;
+    enum_constant public static final androidx.benchmark.macro.BaselineProfileMode UseIfAvailable;
+  }
+
+  public abstract sealed class CompilationMode {
+    field public static final androidx.benchmark.macro.CompilationMode.Companion Companion;
+    field public static final androidx.benchmark.macro.CompilationMode DEFAULT;
+  }
+
+  public static final class CompilationMode.Companion {
+  }
+
+  public static final class CompilationMode.Full extends androidx.benchmark.macro.CompilationMode {
+    ctor public CompilationMode.Full();
+  }
+
+  @SuppressCompatibility @androidx.benchmark.macro.ExperimentalMacrobenchmarkApi public static final class CompilationMode.Ignore extends androidx.benchmark.macro.CompilationMode {
+    ctor public CompilationMode.Ignore();
+  }
+
+  @RequiresApi(24) public static final class CompilationMode.None extends androidx.benchmark.macro.CompilationMode {
+    ctor public CompilationMode.None();
+  }
+
+  @RequiresApi(24) public static final class CompilationMode.Partial extends androidx.benchmark.macro.CompilationMode {
+    ctor public CompilationMode.Partial();
+    ctor public CompilationMode.Partial(optional androidx.benchmark.macro.BaselineProfileMode baselineProfileMode);
+    ctor public CompilationMode.Partial(optional androidx.benchmark.macro.BaselineProfileMode baselineProfileMode, optional @IntRange(from=0L) int warmupIterations);
+    method public androidx.benchmark.macro.BaselineProfileMode getBaselineProfileMode();
+    method public int getWarmupIterations();
+    property public final androidx.benchmark.macro.BaselineProfileMode baselineProfileMode;
+    property public final int warmupIterations;
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn(message="This Macrobenchmark API is experimental.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.CLASS, kotlin.annotation.AnnotationTarget.FUNCTION}) public @interface ExperimentalMacrobenchmarkApi {
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn(message="This Metric API is experimental.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.CLASS, kotlin.annotation.AnnotationTarget.FUNCTION}) public @interface ExperimentalMetricApi {
+  }
+
+  @SuppressCompatibility @androidx.benchmark.macro.ExperimentalMetricApi public final class FrameTimingGfxInfoMetric extends androidx.benchmark.macro.Metric {
+    ctor public FrameTimingGfxInfoMetric();
+  }
+
+  public final class FrameTimingMetric extends androidx.benchmark.macro.Metric {
+    ctor public FrameTimingMetric();
+  }
+
+  public final class MacrobenchmarkScope {
+    ctor public MacrobenchmarkScope(String packageName, boolean launchWithClearTask);
+    method public void dropKernelPageCache();
+    method public void dropShaderCache();
+    method public androidx.test.uiautomator.UiDevice getDevice();
+    method public Integer? getIteration();
+    method public String getPackageName();
+    method public void killProcess();
+    method @Deprecated public void killProcess(optional boolean useKillAll);
+    method public void pressHome();
+    method public void pressHome(optional long delayDurationMs);
+    method public void startActivityAndWait();
+    method public void startActivityAndWait(android.content.Intent intent);
+    method public void startActivityAndWait(optional kotlin.jvm.functions.Function1<? super android.content.Intent,kotlin.Unit> block);
+    property public final androidx.test.uiautomator.UiDevice device;
+    property public final Integer? iteration;
+    property public final String packageName;
+  }
+
+  @SuppressCompatibility @androidx.benchmark.macro.ExperimentalMetricApi public final class MemoryCountersMetric extends androidx.benchmark.macro.TraceMetric {
+    ctor public MemoryCountersMetric();
+    method public java.util.List<androidx.benchmark.macro.Metric.Measurement> getMeasurements(androidx.benchmark.macro.Metric.CaptureInfo captureInfo, androidx.benchmark.perfetto.PerfettoTraceProcessor.Session traceSession);
+  }
+
+  @SuppressCompatibility @androidx.benchmark.macro.ExperimentalMetricApi public final class MemoryUsageMetric extends androidx.benchmark.macro.TraceMetric {
+    ctor public MemoryUsageMetric(androidx.benchmark.macro.MemoryUsageMetric.Mode mode, optional java.util.List<? extends androidx.benchmark.macro.MemoryUsageMetric.SubMetric> subMetrics);
+    method public java.util.List<androidx.benchmark.macro.Metric.Measurement> getMeasurements(androidx.benchmark.macro.Metric.CaptureInfo captureInfo, androidx.benchmark.perfetto.PerfettoTraceProcessor.Session traceSession);
+  }
+
+  public enum MemoryUsageMetric.Mode {
+    enum_constant public static final androidx.benchmark.macro.MemoryUsageMetric.Mode Last;
+    enum_constant public static final androidx.benchmark.macro.MemoryUsageMetric.Mode Max;
+  }
+
+  public enum MemoryUsageMetric.SubMetric {
+    enum_constant public static final androidx.benchmark.macro.MemoryUsageMetric.SubMetric Gpu;
+    enum_constant public static final androidx.benchmark.macro.MemoryUsageMetric.SubMetric HeapSize;
+    enum_constant public static final androidx.benchmark.macro.MemoryUsageMetric.SubMetric RssAnon;
+    enum_constant public static final androidx.benchmark.macro.MemoryUsageMetric.SubMetric RssFile;
+    enum_constant public static final androidx.benchmark.macro.MemoryUsageMetric.SubMetric RssShmem;
+  }
+
+  public abstract sealed class Metric {
+  }
+
+  @SuppressCompatibility @androidx.benchmark.macro.ExperimentalMetricApi public static final class Metric.CaptureInfo {
+    ctor public Metric.CaptureInfo(int apiLevel, String targetPackageName, String testPackageName, androidx.benchmark.macro.StartupMode? startupMode);
+    method public int component1();
+    method public String component2();
+    method public String component3();
+    method public androidx.benchmark.macro.StartupMode? component4();
+    method public androidx.benchmark.macro.Metric.CaptureInfo copy(int apiLevel, String targetPackageName, String testPackageName, androidx.benchmark.macro.StartupMode? startupMode);
+    method public int getApiLevel();
+    method public androidx.benchmark.macro.StartupMode? getStartupMode();
+    method public String getTargetPackageName();
+    method public String getTestPackageName();
+    property public final int apiLevel;
+    property public final androidx.benchmark.macro.StartupMode? startupMode;
+    property public final String targetPackageName;
+    property public final String testPackageName;
+  }
+
+  @SuppressCompatibility @androidx.benchmark.macro.ExperimentalMetricApi public static final class Metric.Measurement {
+    ctor public Metric.Measurement(String name, double data);
+    ctor public Metric.Measurement(String name, java.util.List<java.lang.Double> dataSamples);
+    method public String component1();
+    method public java.util.List<java.lang.Double> component2();
+    method public boolean component3();
+    method public androidx.benchmark.macro.Metric.Measurement copy(String name, java.util.List<java.lang.Double> data, boolean requireSingleValue);
+    method public java.util.List<java.lang.Double> getData();
+    method public String getName();
+    method public boolean getRequireSingleValue();
+    property public final java.util.List<java.lang.Double> data;
+    property public final String name;
+    property public final boolean requireSingleValue;
+  }
+
+  public final class MetricResultExtensionsKt {
+    method @SuppressCompatibility @androidx.benchmark.macro.ExperimentalMetricApi public static void assertEqualMeasurements(java.util.List<androidx.benchmark.macro.Metric.Measurement> expected, java.util.List<androidx.benchmark.macro.Metric.Measurement> observed, double threshold);
+  }
+
+  @SuppressCompatibility @androidx.benchmark.macro.ExperimentalMetricApi public enum PowerCategory {
+    enum_constant public static final androidx.benchmark.macro.PowerCategory CPU;
+    enum_constant public static final androidx.benchmark.macro.PowerCategory DISPLAY;
+    enum_constant public static final androidx.benchmark.macro.PowerCategory GPS;
+    enum_constant public static final androidx.benchmark.macro.PowerCategory GPU;
+    enum_constant public static final androidx.benchmark.macro.PowerCategory MACHINE_LEARNING;
+    enum_constant public static final androidx.benchmark.macro.PowerCategory MEMORY;
+    enum_constant public static final androidx.benchmark.macro.PowerCategory NETWORK;
+    enum_constant public static final androidx.benchmark.macro.PowerCategory UNCATEGORIZED;
+  }
+
+  @SuppressCompatibility @androidx.benchmark.macro.ExperimentalMetricApi public enum PowerCategoryDisplayLevel {
+    enum_constant public static final androidx.benchmark.macro.PowerCategoryDisplayLevel BREAKDOWN;
+    enum_constant public static final androidx.benchmark.macro.PowerCategoryDisplayLevel TOTAL;
+  }
+
+  @SuppressCompatibility @RequiresApi(29) @androidx.benchmark.macro.ExperimentalMetricApi public final class PowerMetric extends androidx.benchmark.macro.Metric {
+    ctor public PowerMetric(androidx.benchmark.macro.PowerMetric.Type type);
+    method public static androidx.benchmark.macro.PowerMetric.Type.Battery Battery();
+    method public static androidx.benchmark.macro.PowerMetric.Type.Energy Energy(optional java.util.Map<androidx.benchmark.macro.PowerCategory,? extends androidx.benchmark.macro.PowerCategoryDisplayLevel> categories);
+    method public static androidx.benchmark.macro.PowerMetric.Type.Power Power(optional java.util.Map<androidx.benchmark.macro.PowerCategory,? extends androidx.benchmark.macro.PowerCategoryDisplayLevel> categories);
+    method public static boolean deviceBatteryHasMinimumCharge();
+    method public static boolean deviceSupportsHighPrecisionTracking();
+    field public static final androidx.benchmark.macro.PowerMetric.Companion Companion;
+  }
+
+  public static final class PowerMetric.Companion {
+    method public androidx.benchmark.macro.PowerMetric.Type.Battery Battery();
+    method public androidx.benchmark.macro.PowerMetric.Type.Energy Energy(optional java.util.Map<androidx.benchmark.macro.PowerCategory,? extends androidx.benchmark.macro.PowerCategoryDisplayLevel> categories);
+    method public androidx.benchmark.macro.PowerMetric.Type.Power Power(optional java.util.Map<androidx.benchmark.macro.PowerCategory,? extends androidx.benchmark.macro.PowerCategoryDisplayLevel> categories);
+    method public boolean deviceBatteryHasMinimumCharge();
+    method public boolean deviceSupportsHighPrecisionTracking();
+  }
+
+  public abstract static sealed class PowerMetric.Type {
+    method public final java.util.Map<androidx.benchmark.macro.PowerCategory,androidx.benchmark.macro.PowerCategoryDisplayLevel> getCategories();
+    method public final void setCategories(java.util.Map<androidx.benchmark.macro.PowerCategory,? extends androidx.benchmark.macro.PowerCategoryDisplayLevel>);
+    property public final java.util.Map<androidx.benchmark.macro.PowerCategory,androidx.benchmark.macro.PowerCategoryDisplayLevel> categories;
+  }
+
+  public static final class PowerMetric.Type.Battery extends androidx.benchmark.macro.PowerMetric.Type {
+    ctor public PowerMetric.Type.Battery();
+  }
+
+  public static final class PowerMetric.Type.Energy extends androidx.benchmark.macro.PowerMetric.Type {
+    ctor public PowerMetric.Type.Energy(optional java.util.Map<androidx.benchmark.macro.PowerCategory,? extends androidx.benchmark.macro.PowerCategoryDisplayLevel> energyCategories);
+  }
+
+  public static final class PowerMetric.Type.Power extends androidx.benchmark.macro.PowerMetric.Type {
+    ctor public PowerMetric.Type.Power(optional java.util.Map<androidx.benchmark.macro.PowerCategory,? extends androidx.benchmark.macro.PowerCategoryDisplayLevel> powerCategories);
+  }
+
+  public enum StartupMode {
+    enum_constant public static final androidx.benchmark.macro.StartupMode COLD;
+    enum_constant public static final androidx.benchmark.macro.StartupMode HOT;
+    enum_constant public static final androidx.benchmark.macro.StartupMode WARM;
+  }
+
+  public final class StartupTimingMetric extends androidx.benchmark.macro.Metric {
+    ctor public StartupTimingMetric();
+  }
+
+  @SuppressCompatibility @androidx.benchmark.macro.ExperimentalMetricApi public abstract class TraceMetric extends androidx.benchmark.macro.Metric {
+    ctor public TraceMetric();
+    method public abstract java.util.List<androidx.benchmark.macro.Metric.Measurement> getMeasurements(androidx.benchmark.macro.Metric.CaptureInfo captureInfo, androidx.benchmark.perfetto.PerfettoTraceProcessor.Session traceSession);
+  }
+
+  @SuppressCompatibility @androidx.benchmark.macro.ExperimentalMetricApi public final class TraceSectionMetric extends androidx.benchmark.macro.Metric {
+    ctor public TraceSectionMetric(String sectionName);
+    ctor public TraceSectionMetric(String sectionName, optional androidx.benchmark.macro.TraceSectionMetric.Mode mode);
+    ctor public TraceSectionMetric(String sectionName, optional androidx.benchmark.macro.TraceSectionMetric.Mode mode, optional String label);
+    ctor public TraceSectionMetric(String sectionName, optional androidx.benchmark.macro.TraceSectionMetric.Mode mode, optional String label, optional boolean targetPackageOnly);
+  }
+
+  public abstract static sealed class TraceSectionMetric.Mode {
+  }
+
+  public static final class TraceSectionMetric.Mode.Average extends androidx.benchmark.macro.TraceSectionMetric.Mode {
+    field public static final androidx.benchmark.macro.TraceSectionMetric.Mode.Average INSTANCE;
+  }
+
+  public static final class TraceSectionMetric.Mode.Count extends androidx.benchmark.macro.TraceSectionMetric.Mode {
+    field public static final androidx.benchmark.macro.TraceSectionMetric.Mode.Count INSTANCE;
+  }
+
+  public static final class TraceSectionMetric.Mode.First extends androidx.benchmark.macro.TraceSectionMetric.Mode {
+    field public static final androidx.benchmark.macro.TraceSectionMetric.Mode.First INSTANCE;
+  }
+
+  public static final class TraceSectionMetric.Mode.Max extends androidx.benchmark.macro.TraceSectionMetric.Mode {
+    field public static final androidx.benchmark.macro.TraceSectionMetric.Mode.Max INSTANCE;
+  }
+
+  public static final class TraceSectionMetric.Mode.Min extends androidx.benchmark.macro.TraceSectionMetric.Mode {
+    field public static final androidx.benchmark.macro.TraceSectionMetric.Mode.Min INSTANCE;
+  }
+
+  public static final class TraceSectionMetric.Mode.Sum extends androidx.benchmark.macro.TraceSectionMetric.Mode {
+    field public static final androidx.benchmark.macro.TraceSectionMetric.Mode.Sum INSTANCE;
+  }
+
+}
+
+package androidx.benchmark.perfetto {
+
+  @SuppressCompatibility @kotlin.RequiresOptIn @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.CLASS, kotlin.annotation.AnnotationTarget.FUNCTION}) public @interface ExperimentalPerfettoTraceProcessorApi {
+  }
+
+  @SuppressCompatibility @androidx.benchmark.perfetto.ExperimentalPerfettoTraceProcessorApi public final class PerfettoTraceProcessor {
+    ctor public PerfettoTraceProcessor();
+    method public <T> T loadTrace(androidx.benchmark.perfetto.PerfettoTrace trace, kotlin.jvm.functions.Function1<? super androidx.benchmark.perfetto.PerfettoTraceProcessor.Session,? extends T> block);
+    method public static <T> T runServer(kotlin.jvm.functions.Function1<? super androidx.benchmark.perfetto.PerfettoTraceProcessor,? extends T> block);
+    method public static <T> T runServer(long timeout, kotlin.jvm.functions.Function1<? super androidx.benchmark.perfetto.PerfettoTraceProcessor,? extends T> block);
+    field public static final androidx.benchmark.perfetto.PerfettoTraceProcessor.Companion Companion;
+  }
+
+  public static final class PerfettoTraceProcessor.Companion {
+    method public <T> T runServer(kotlin.jvm.functions.Function1<? super androidx.benchmark.perfetto.PerfettoTraceProcessor,? extends T> block);
+    method public static <T> T runServer(long timeout, kotlin.jvm.functions.Function1<? super androidx.benchmark.perfetto.PerfettoTraceProcessor,? extends T> block);
+  }
+
+  public static final class PerfettoTraceProcessor.Session {
+    method public kotlin.sequences.Sequence<androidx.benchmark.perfetto.Row> query(@org.intellij.lang.annotations.Language("sql") String query);
+    method public String queryMetricsJson(java.util.List<java.lang.String> metrics);
+    method public byte[] queryMetricsProtoBinary(java.util.List<java.lang.String> metrics);
+    method public String queryMetricsProtoText(java.util.List<java.lang.String> metrics);
+    method public byte[] rawQuery(@org.intellij.lang.annotations.Language("sql") String query);
+  }
+
+  @SuppressCompatibility @androidx.benchmark.perfetto.ExperimentalPerfettoTraceProcessorApi public final class Row implements kotlin.jvm.internal.markers.KMappedMarker java.util.Map<java.lang.String,java.lang.Object?> {
+    ctor public Row(java.util.Map<java.lang.String,? extends java.lang.Object?> map);
+    method public byte[] bytes(String columnName);
+    method public double double(String columnName);
+    method public long long(String columnName);
+    method public byte[]? nullableBytes(String columnName);
+    method public Double? nullableDouble(String columnName);
+    method public Long? nullableLong(String columnName);
+    method public String? nullableString(String columnName);
+    method public String string(String columnName);
+  }
+
+  public final class RowKt {
+    method @SuppressCompatibility @androidx.benchmark.perfetto.ExperimentalPerfettoTraceProcessorApi public static androidx.benchmark.perfetto.Row rowOf(kotlin.Pair<java.lang.String,? extends java.lang.Object?>... pairs);
+  }
+
+}
+
diff --git a/benchmark/benchmark-macro/api/res-1.3.0-beta02.txt b/benchmark/benchmark-macro/api/res-1.3.0-beta02.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/benchmark/benchmark-macro/api/res-1.3.0-beta02.txt
diff --git a/benchmark/benchmark-macro/api/restricted_1.3.0-beta02.txt b/benchmark/benchmark-macro/api/restricted_1.3.0-beta02.txt
new file mode 100644
index 0000000..4c883fb
--- /dev/null
+++ b/benchmark/benchmark-macro/api/restricted_1.3.0-beta02.txt
@@ -0,0 +1,303 @@
+// Signature format: 4.0
+package androidx.benchmark.macro {
+
+  public enum BaselineProfileMode {
+    enum_constant public static final androidx.benchmark.macro.BaselineProfileMode Disable;
+    enum_constant public static final androidx.benchmark.macro.BaselineProfileMode Require;
+    enum_constant public static final androidx.benchmark.macro.BaselineProfileMode UseIfAvailable;
+  }
+
+  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final class BatteryCharge {
+    method public boolean hasMinimumCharge(optional boolean throwOnMissingMetrics);
+    field public static final androidx.benchmark.macro.BatteryCharge INSTANCE;
+  }
+
+  public abstract sealed class CompilationMode {
+    field public static final androidx.benchmark.macro.CompilationMode.Companion Companion;
+    field public static final androidx.benchmark.macro.CompilationMode DEFAULT;
+  }
+
+  public static final class CompilationMode.Companion {
+  }
+
+  public static final class CompilationMode.Full extends androidx.benchmark.macro.CompilationMode {
+    ctor public CompilationMode.Full();
+  }
+
+  @SuppressCompatibility @androidx.benchmark.macro.ExperimentalMacrobenchmarkApi public static final class CompilationMode.Ignore extends androidx.benchmark.macro.CompilationMode {
+    ctor public CompilationMode.Ignore();
+  }
+
+  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final class CompilationMode.Interpreted extends androidx.benchmark.macro.CompilationMode {
+    field public static final androidx.benchmark.macro.CompilationMode.Interpreted INSTANCE;
+  }
+
+  @RequiresApi(24) public static final class CompilationMode.None extends androidx.benchmark.macro.CompilationMode {
+    ctor public CompilationMode.None();
+  }
+
+  @RequiresApi(24) public static final class CompilationMode.Partial extends androidx.benchmark.macro.CompilationMode {
+    ctor public CompilationMode.Partial();
+    ctor public CompilationMode.Partial(optional androidx.benchmark.macro.BaselineProfileMode baselineProfileMode);
+    ctor public CompilationMode.Partial(optional androidx.benchmark.macro.BaselineProfileMode baselineProfileMode, optional @IntRange(from=0L) int warmupIterations);
+    method public androidx.benchmark.macro.BaselineProfileMode getBaselineProfileMode();
+    method public int getWarmupIterations();
+    property public final androidx.benchmark.macro.BaselineProfileMode baselineProfileMode;
+    property public final int warmupIterations;
+  }
+
+  public final class CompilationModeKt {
+    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static boolean isSupportedWithVmSettings(androidx.benchmark.macro.CompilationMode);
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn(message="This Macrobenchmark API is experimental.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.CLASS, kotlin.annotation.AnnotationTarget.FUNCTION}) public @interface ExperimentalMacrobenchmarkApi {
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn(message="This Metric API is experimental.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.CLASS, kotlin.annotation.AnnotationTarget.FUNCTION}) public @interface ExperimentalMetricApi {
+  }
+
+  @SuppressCompatibility @androidx.benchmark.macro.ExperimentalMetricApi public final class FrameTimingGfxInfoMetric extends androidx.benchmark.macro.Metric {
+    ctor public FrameTimingGfxInfoMetric();
+  }
+
+  public final class FrameTimingMetric extends androidx.benchmark.macro.Metric {
+    ctor public FrameTimingMetric();
+  }
+
+  public final class MacrobenchmarkScope {
+    ctor public MacrobenchmarkScope(String packageName, boolean launchWithClearTask);
+    method public void dropKernelPageCache();
+    method public void dropShaderCache();
+    method public androidx.test.uiautomator.UiDevice getDevice();
+    method public Integer? getIteration();
+    method public String getPackageName();
+    method public void killProcess();
+    method @Deprecated public void killProcess(optional boolean useKillAll);
+    method public void pressHome();
+    method public void pressHome(optional long delayDurationMs);
+    method public void startActivityAndWait();
+    method public void startActivityAndWait(android.content.Intent intent);
+    method public void startActivityAndWait(optional kotlin.jvm.functions.Function1<? super android.content.Intent,kotlin.Unit> block);
+    property public final androidx.test.uiautomator.UiDevice device;
+    property public final Integer? iteration;
+    property public final String packageName;
+  }
+
+  @SuppressCompatibility @androidx.benchmark.macro.ExperimentalMetricApi public final class MemoryCountersMetric extends androidx.benchmark.macro.TraceMetric {
+    ctor public MemoryCountersMetric();
+    method public java.util.List<androidx.benchmark.macro.Metric.Measurement> getMeasurements(androidx.benchmark.macro.Metric.CaptureInfo captureInfo, androidx.benchmark.perfetto.PerfettoTraceProcessor.Session traceSession);
+  }
+
+  @SuppressCompatibility @androidx.benchmark.macro.ExperimentalMetricApi public final class MemoryUsageMetric extends androidx.benchmark.macro.TraceMetric {
+    ctor public MemoryUsageMetric(androidx.benchmark.macro.MemoryUsageMetric.Mode mode, optional java.util.List<? extends androidx.benchmark.macro.MemoryUsageMetric.SubMetric> subMetrics);
+    method public java.util.List<androidx.benchmark.macro.Metric.Measurement> getMeasurements(androidx.benchmark.macro.Metric.CaptureInfo captureInfo, androidx.benchmark.perfetto.PerfettoTraceProcessor.Session traceSession);
+  }
+
+  public enum MemoryUsageMetric.Mode {
+    enum_constant public static final androidx.benchmark.macro.MemoryUsageMetric.Mode Last;
+    enum_constant public static final androidx.benchmark.macro.MemoryUsageMetric.Mode Max;
+  }
+
+  public enum MemoryUsageMetric.SubMetric {
+    enum_constant public static final androidx.benchmark.macro.MemoryUsageMetric.SubMetric Gpu;
+    enum_constant public static final androidx.benchmark.macro.MemoryUsageMetric.SubMetric HeapSize;
+    enum_constant public static final androidx.benchmark.macro.MemoryUsageMetric.SubMetric RssAnon;
+    enum_constant public static final androidx.benchmark.macro.MemoryUsageMetric.SubMetric RssFile;
+    enum_constant public static final androidx.benchmark.macro.MemoryUsageMetric.SubMetric RssShmem;
+  }
+
+  public abstract sealed class Metric {
+  }
+
+  @SuppressCompatibility @androidx.benchmark.macro.ExperimentalMetricApi public static final class Metric.CaptureInfo {
+    ctor public Metric.CaptureInfo(int apiLevel, String targetPackageName, String testPackageName, androidx.benchmark.macro.StartupMode? startupMode);
+    method public int component1();
+    method public String component2();
+    method public String component3();
+    method public androidx.benchmark.macro.StartupMode? component4();
+    method public androidx.benchmark.macro.Metric.CaptureInfo copy(int apiLevel, String targetPackageName, String testPackageName, androidx.benchmark.macro.StartupMode? startupMode);
+    method public int getApiLevel();
+    method public androidx.benchmark.macro.StartupMode? getStartupMode();
+    method public String getTargetPackageName();
+    method public String getTestPackageName();
+    property public final int apiLevel;
+    property public final androidx.benchmark.macro.StartupMode? startupMode;
+    property public final String targetPackageName;
+    property public final String testPackageName;
+  }
+
+  @SuppressCompatibility @androidx.benchmark.macro.ExperimentalMetricApi public static final class Metric.Measurement {
+    ctor public Metric.Measurement(String name, double data);
+    ctor public Metric.Measurement(String name, java.util.List<java.lang.Double> dataSamples);
+    method public String component1();
+    method public java.util.List<java.lang.Double> component2();
+    method public boolean component3();
+    method public androidx.benchmark.macro.Metric.Measurement copy(String name, java.util.List<java.lang.Double> data, boolean requireSingleValue);
+    method public java.util.List<java.lang.Double> getData();
+    method public String getName();
+    method public boolean getRequireSingleValue();
+    property public final java.util.List<java.lang.Double> data;
+    property public final String name;
+    property public final boolean requireSingleValue;
+  }
+
+  public final class MetricResultExtensionsKt {
+    method @SuppressCompatibility @androidx.benchmark.macro.ExperimentalMetricApi public static void assertEqualMeasurements(java.util.List<androidx.benchmark.macro.Metric.Measurement> expected, java.util.List<androidx.benchmark.macro.Metric.Measurement> observed, double threshold);
+  }
+
+  @SuppressCompatibility @androidx.benchmark.macro.ExperimentalMetricApi public enum PowerCategory {
+    enum_constant public static final androidx.benchmark.macro.PowerCategory CPU;
+    enum_constant public static final androidx.benchmark.macro.PowerCategory DISPLAY;
+    enum_constant public static final androidx.benchmark.macro.PowerCategory GPS;
+    enum_constant public static final androidx.benchmark.macro.PowerCategory GPU;
+    enum_constant public static final androidx.benchmark.macro.PowerCategory MACHINE_LEARNING;
+    enum_constant public static final androidx.benchmark.macro.PowerCategory MEMORY;
+    enum_constant public static final androidx.benchmark.macro.PowerCategory NETWORK;
+    enum_constant public static final androidx.benchmark.macro.PowerCategory UNCATEGORIZED;
+  }
+
+  @SuppressCompatibility @androidx.benchmark.macro.ExperimentalMetricApi public enum PowerCategoryDisplayLevel {
+    enum_constant public static final androidx.benchmark.macro.PowerCategoryDisplayLevel BREAKDOWN;
+    enum_constant public static final androidx.benchmark.macro.PowerCategoryDisplayLevel TOTAL;
+  }
+
+  @SuppressCompatibility @RequiresApi(29) @androidx.benchmark.macro.ExperimentalMetricApi public final class PowerMetric extends androidx.benchmark.macro.Metric {
+    ctor public PowerMetric(androidx.benchmark.macro.PowerMetric.Type type);
+    method public static androidx.benchmark.macro.PowerMetric.Type.Battery Battery();
+    method public static androidx.benchmark.macro.PowerMetric.Type.Energy Energy(optional java.util.Map<androidx.benchmark.macro.PowerCategory,? extends androidx.benchmark.macro.PowerCategoryDisplayLevel> categories);
+    method public static androidx.benchmark.macro.PowerMetric.Type.Power Power(optional java.util.Map<androidx.benchmark.macro.PowerCategory,? extends androidx.benchmark.macro.PowerCategoryDisplayLevel> categories);
+    method public static boolean deviceBatteryHasMinimumCharge();
+    method public static boolean deviceSupportsHighPrecisionTracking();
+    field public static final androidx.benchmark.macro.PowerMetric.Companion Companion;
+  }
+
+  public static final class PowerMetric.Companion {
+    method public androidx.benchmark.macro.PowerMetric.Type.Battery Battery();
+    method public androidx.benchmark.macro.PowerMetric.Type.Energy Energy(optional java.util.Map<androidx.benchmark.macro.PowerCategory,? extends androidx.benchmark.macro.PowerCategoryDisplayLevel> categories);
+    method public androidx.benchmark.macro.PowerMetric.Type.Power Power(optional java.util.Map<androidx.benchmark.macro.PowerCategory,? extends androidx.benchmark.macro.PowerCategoryDisplayLevel> categories);
+    method public boolean deviceBatteryHasMinimumCharge();
+    method public boolean deviceSupportsHighPrecisionTracking();
+  }
+
+  public abstract static sealed class PowerMetric.Type {
+    method public final java.util.Map<androidx.benchmark.macro.PowerCategory,androidx.benchmark.macro.PowerCategoryDisplayLevel> getCategories();
+    method public final void setCategories(java.util.Map<androidx.benchmark.macro.PowerCategory,? extends androidx.benchmark.macro.PowerCategoryDisplayLevel>);
+    property public final java.util.Map<androidx.benchmark.macro.PowerCategory,androidx.benchmark.macro.PowerCategoryDisplayLevel> categories;
+  }
+
+  public static final class PowerMetric.Type.Battery extends androidx.benchmark.macro.PowerMetric.Type {
+    ctor public PowerMetric.Type.Battery();
+  }
+
+  public static final class PowerMetric.Type.Energy extends androidx.benchmark.macro.PowerMetric.Type {
+    ctor public PowerMetric.Type.Energy(optional java.util.Map<androidx.benchmark.macro.PowerCategory,? extends androidx.benchmark.macro.PowerCategoryDisplayLevel> energyCategories);
+  }
+
+  public static final class PowerMetric.Type.Power extends androidx.benchmark.macro.PowerMetric.Type {
+    ctor public PowerMetric.Type.Power(optional java.util.Map<androidx.benchmark.macro.PowerCategory,? extends androidx.benchmark.macro.PowerCategoryDisplayLevel> powerCategories);
+  }
+
+  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final class PowerRail {
+    method public boolean hasMetrics(optional boolean throwOnMissingMetrics);
+    field public static final androidx.benchmark.macro.PowerRail INSTANCE;
+  }
+
+  public enum StartupMode {
+    enum_constant public static final androidx.benchmark.macro.StartupMode COLD;
+    enum_constant public static final androidx.benchmark.macro.StartupMode HOT;
+    enum_constant public static final androidx.benchmark.macro.StartupMode WARM;
+  }
+
+  @RequiresApi(29) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final class StartupTimingLegacyMetric extends androidx.benchmark.macro.Metric {
+    ctor public StartupTimingLegacyMetric();
+  }
+
+  public final class StartupTimingMetric extends androidx.benchmark.macro.Metric {
+    ctor public StartupTimingMetric();
+  }
+
+  @SuppressCompatibility @androidx.benchmark.macro.ExperimentalMetricApi public abstract class TraceMetric extends androidx.benchmark.macro.Metric {
+    ctor public TraceMetric();
+    method public abstract java.util.List<androidx.benchmark.macro.Metric.Measurement> getMeasurements(androidx.benchmark.macro.Metric.CaptureInfo captureInfo, androidx.benchmark.perfetto.PerfettoTraceProcessor.Session traceSession);
+  }
+
+  @SuppressCompatibility @androidx.benchmark.macro.ExperimentalMetricApi public final class TraceSectionMetric extends androidx.benchmark.macro.Metric {
+    ctor public TraceSectionMetric(String sectionName);
+    ctor public TraceSectionMetric(String sectionName, optional androidx.benchmark.macro.TraceSectionMetric.Mode mode);
+    ctor public TraceSectionMetric(String sectionName, optional androidx.benchmark.macro.TraceSectionMetric.Mode mode, optional String label);
+    ctor public TraceSectionMetric(String sectionName, optional androidx.benchmark.macro.TraceSectionMetric.Mode mode, optional String label, optional boolean targetPackageOnly);
+  }
+
+  public abstract static sealed class TraceSectionMetric.Mode {
+  }
+
+  public static final class TraceSectionMetric.Mode.Average extends androidx.benchmark.macro.TraceSectionMetric.Mode {
+    field public static final androidx.benchmark.macro.TraceSectionMetric.Mode.Average INSTANCE;
+  }
+
+  public static final class TraceSectionMetric.Mode.Count extends androidx.benchmark.macro.TraceSectionMetric.Mode {
+    field public static final androidx.benchmark.macro.TraceSectionMetric.Mode.Count INSTANCE;
+  }
+
+  public static final class TraceSectionMetric.Mode.First extends androidx.benchmark.macro.TraceSectionMetric.Mode {
+    field public static final androidx.benchmark.macro.TraceSectionMetric.Mode.First INSTANCE;
+  }
+
+  public static final class TraceSectionMetric.Mode.Max extends androidx.benchmark.macro.TraceSectionMetric.Mode {
+    field public static final androidx.benchmark.macro.TraceSectionMetric.Mode.Max INSTANCE;
+  }
+
+  public static final class TraceSectionMetric.Mode.Min extends androidx.benchmark.macro.TraceSectionMetric.Mode {
+    field public static final androidx.benchmark.macro.TraceSectionMetric.Mode.Min INSTANCE;
+  }
+
+  public static final class TraceSectionMetric.Mode.Sum extends androidx.benchmark.macro.TraceSectionMetric.Mode {
+    field public static final androidx.benchmark.macro.TraceSectionMetric.Mode.Sum INSTANCE;
+  }
+
+}
+
+package androidx.benchmark.perfetto {
+
+  @SuppressCompatibility @kotlin.RequiresOptIn @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.CLASS, kotlin.annotation.AnnotationTarget.FUNCTION}) public @interface ExperimentalPerfettoTraceProcessorApi {
+  }
+
+  @SuppressCompatibility @androidx.benchmark.perfetto.ExperimentalPerfettoTraceProcessorApi public final class PerfettoTraceProcessor {
+    ctor public PerfettoTraceProcessor();
+    method public <T> T loadTrace(androidx.benchmark.perfetto.PerfettoTrace trace, kotlin.jvm.functions.Function1<? super androidx.benchmark.perfetto.PerfettoTraceProcessor.Session,? extends T> block);
+    method public static <T> T runServer(kotlin.jvm.functions.Function1<? super androidx.benchmark.perfetto.PerfettoTraceProcessor,? extends T> block);
+    method public static <T> T runServer(long timeout, kotlin.jvm.functions.Function1<? super androidx.benchmark.perfetto.PerfettoTraceProcessor,? extends T> block);
+    field public static final androidx.benchmark.perfetto.PerfettoTraceProcessor.Companion Companion;
+  }
+
+  public static final class PerfettoTraceProcessor.Companion {
+    method public <T> T runServer(kotlin.jvm.functions.Function1<? super androidx.benchmark.perfetto.PerfettoTraceProcessor,? extends T> block);
+    method public static <T> T runServer(long timeout, kotlin.jvm.functions.Function1<? super androidx.benchmark.perfetto.PerfettoTraceProcessor,? extends T> block);
+  }
+
+  public static final class PerfettoTraceProcessor.Session {
+    method public kotlin.sequences.Sequence<androidx.benchmark.perfetto.Row> query(@org.intellij.lang.annotations.Language("sql") String query);
+    method public String queryMetricsJson(java.util.List<java.lang.String> metrics);
+    method public byte[] queryMetricsProtoBinary(java.util.List<java.lang.String> metrics);
+    method public String queryMetricsProtoText(java.util.List<java.lang.String> metrics);
+    method public byte[] rawQuery(@org.intellij.lang.annotations.Language("sql") String query);
+  }
+
+  @SuppressCompatibility @androidx.benchmark.perfetto.ExperimentalPerfettoTraceProcessorApi public final class Row implements kotlin.jvm.internal.markers.KMappedMarker java.util.Map<java.lang.String,java.lang.Object?> {
+    ctor public Row(java.util.Map<java.lang.String,? extends java.lang.Object?> map);
+    method public byte[] bytes(String columnName);
+    method public double double(String columnName);
+    method public long long(String columnName);
+    method public byte[]? nullableBytes(String columnName);
+    method public Double? nullableDouble(String columnName);
+    method public Long? nullableLong(String columnName);
+    method public String? nullableString(String columnName);
+    method public String string(String columnName);
+  }
+
+  public final class RowKt {
+    method @SuppressCompatibility @androidx.benchmark.perfetto.ExperimentalPerfettoTraceProcessorApi public static androidx.benchmark.perfetto.Row rowOf(kotlin.Pair<java.lang.String,? extends java.lang.Object?>... pairs);
+  }
+
+}
+
diff --git a/browser/browser/api/current.txt b/browser/browser/api/current.txt
index 4db6b75..08b4165 100644
--- a/browser/browser/api/current.txt
+++ b/browser/browser/api/current.txt
@@ -303,6 +303,7 @@
     method public boolean mayLaunchUrl(android.net.Uri?, android.os.Bundle?, java.util.List<android.os.Bundle!>?);
     method @androidx.browser.customtabs.CustomTabsService.Result public int postMessage(String, android.os.Bundle?);
     method @SuppressCompatibility @androidx.browser.customtabs.ExperimentalPrefetch public void prefetch(android.net.Uri, androidx.browser.customtabs.PrefetchOptions);
+    method @SuppressCompatibility @androidx.browser.customtabs.ExperimentalPrefetch public void prefetch(java.util.List<android.net.Uri!>, androidx.browser.customtabs.PrefetchOptions);
     method public boolean receiveFile(android.net.Uri, int, android.os.Bundle?);
     method public boolean requestPostMessageChannel(android.net.Uri);
     method public boolean requestPostMessageChannel(android.net.Uri, android.net.Uri?, android.os.Bundle);
diff --git a/browser/browser/api/restricted_current.txt b/browser/browser/api/restricted_current.txt
index 82f71f0..8df6fe2 100644
--- a/browser/browser/api/restricted_current.txt
+++ b/browser/browser/api/restricted_current.txt
@@ -314,6 +314,7 @@
     method public boolean mayLaunchUrl(android.net.Uri?, android.os.Bundle?, java.util.List<android.os.Bundle!>?);
     method @androidx.browser.customtabs.CustomTabsService.Result public int postMessage(String, android.os.Bundle?);
     method @SuppressCompatibility @androidx.browser.customtabs.ExperimentalPrefetch public void prefetch(android.net.Uri, androidx.browser.customtabs.PrefetchOptions);
+    method @SuppressCompatibility @androidx.browser.customtabs.ExperimentalPrefetch public void prefetch(java.util.List<android.net.Uri!>, androidx.browser.customtabs.PrefetchOptions);
     method public boolean receiveFile(android.net.Uri, int, android.os.Bundle?);
     method public boolean requestPostMessageChannel(android.net.Uri);
     method public boolean requestPostMessageChannel(android.net.Uri, android.net.Uri?, android.os.Bundle);
diff --git a/browser/browser/src/main/java/androidx/browser/customtabs/CustomTabsSession.java b/browser/browser/src/main/java/androidx/browser/customtabs/CustomTabsSession.java
index e7a87c7..ca297bb 100644
--- a/browser/browser/src/main/java/androidx/browser/customtabs/CustomTabsSession.java
+++ b/browser/browser/src/main/java/androidx/browser/customtabs/CustomTabsSession.java
@@ -136,6 +136,26 @@
     }
 
     /**
+     * Request the browser to start navigational prefetch to the pages that will be used for future
+     * navigations.
+     *
+     * @param urls     The urls to be prefetched for upcoming navigations.
+     * @param options The option used for prefetch request. Please see
+     *                {@link PrefetchOptions}.
+     */
+    @ExperimentalPrefetch
+    @SuppressWarnings("NullAway")  // TODO: b/142938599
+    public void prefetch(@NonNull List<Uri> urls, @NonNull PrefetchOptions options) {
+        try {
+            for (Uri uri : urls) {
+                mService.prefetch(mCallback, uri, options.toBundle());
+            }
+        } catch (RemoteException e) {
+            return;
+        }
+    }
+
+    /**
      * This sets the action button on the toolbar with ID
      * {@link CustomTabsIntent#TOOLBAR_ACTION_BUTTON_ID}.
      *
diff --git a/browser/browser/src/main/res/values-ne/strings.xml b/browser/browser/src/main/res/values-ne/strings.xml
index b166614..f0fca2a1 100644
--- a/browser/browser/src/main/res/values-ne/strings.xml
+++ b/browser/browser/src/main/res/values-ne/strings.xml
@@ -17,7 +17,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="fallback_menu_item_open_in_browser" msgid="3413186855122069269">"ब्राउजरमा खोल्नुहोस्"</string>
-    <string name="fallback_menu_item_copy_link" msgid="4566929209979330987">"लिंक प्रतिलिपि गर्नुहोस्"</string>
+    <string name="fallback_menu_item_copy_link" msgid="4566929209979330987">"लिंक कपी गर्नुहोस्"</string>
     <string name="fallback_menu_item_share_link" msgid="7145444925855055364">"लिंक सेयर गर्नुहोस्"</string>
     <string name="copy_toast_msg" msgid="3260749812566568062">"क्लिपबोर्डमा लिंक कपी गरियो"</string>
 </resources>
diff --git a/buildSrc-tests/build.gradle b/buildSrc-tests/build.gradle
index dc181d4..da28c38 100644
--- a/buildSrc-tests/build.gradle
+++ b/buildSrc-tests/build.gradle
@@ -54,18 +54,31 @@
 apply from: "${buildscript.sourceFile.parentFile.parent}/buildSrc/shared-dependencies.gradle"
 
 dependencies {
+    api(libs.javaxInject)
+    api(libs.johnrengelmanShadow)
+    api(libs.guavaAndroid)
+    api(libs.kotlinGradlePluginApi)
+    api(libs.kotlinNativeUtils)
+    api(libs.kotlinStdlib)
+
     implementation(project(":benchmark:benchmark-gradle-plugin"))
     implementation(project(":inspection:inspection-gradle-plugin"))
     implementation(project(":stableaidl:stableaidl-gradle-plugin"))
     implementation(project(":binarycompatibilityvalidator:binarycompatibilityvalidator"))
     implementation(project.ext.findGradleKotlinDsl())
+    implementation(libs.kotlinGradlePluginAnnotations)
+    implementation(libs.kotlinToolingCore)
+    implementation(libs.binaryCompatibilityValidator)
+    implementation(libs.jetbrainsBinaryCompatibilityValidator)
+    implementation(libs.xmlApis)
+
+    testImplementation(libs.checkmark)
+    testImplementation libs.hamcrestCore
     testImplementation(libs.junit)
     testImplementation(libs.truth)
     testImplementation(project(":internal-testutils-gradle-plugin"))
     testImplementation(project(":internal-testutils-truth"))
     testImplementation(gradleTestKit())
-    testImplementation(libs.checkmark)
-    testImplementation(libs.toml)
 }
 
 tasks.withType(Test).configureEach {
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXComposeImplPlugin.kt b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXComposeImplPlugin.kt
index e36662f..93fa12e 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXComposeImplPlugin.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXComposeImplPlugin.kt
@@ -184,11 +184,18 @@
             }
         // Add Compose compiler plugin to kotlinPlugin configuration, making sure it works
         // for Playground builds as well
-        val pluginVersionToml = project.getVersionByName("composeCompilerPlugin")
-        val versionToUse =
-            if (ProjectLayoutType.isPlayground(project)) {
-                pluginVersionToml
-            } else {
+        val compilerPluginVersion = project.getVersionByName("composeCompilerPlugin")
+        project.dependencies.add(
+            COMPILER_PLUGIN_CONFIGURATION,
+            "androidx.compose.compiler:compiler:$compilerPluginVersion"
+        )
+
+        if (
+            !ProjectLayoutType.isPlayground(project) &&
+                // ksp is also a compiler plugin, updating Kotlin for it will likely break the build
+                !project.plugins.hasPlugin("com.google.devtools.ksp")
+        ) {
+            if (compilerPluginVersion.endsWith("-SNAPSHOT")) {
                 // use exact project path instead of subprojects.find, it is faster
                 val compilerProject = project.rootProject.resolveProject(":compose")
                 val compilerMavenDirectory =
@@ -196,22 +203,30 @@
                         compilerProject.projectDir,
                         "compiler/compose-compiler-snapshot-repository"
                     )
-                if (!compilerMavenDirectory.exists()) {
-                    pluginVersionToml
-                } else {
-                    project.repositories.maven { it.url = compilerMavenDirectory.toURI() }
-                    // Version chosen to be not a "-SNAPSHOT" since apparently gradle doesn't
-                    // validate signatures for -SNAPSHOT builds.  Version is chosen to be higher
-                    // than anything real to ensure it is seen as newer than any explicit dependency
-                    // to prevent gradle from "upgrading" to a stable build instead of local build.
-                    // This version is built by: snapshot-compose-compiler.sh (in compiler project)
-                    "99.0.0"
+                project.repositories.maven { it.url = compilerMavenDirectory.toURI() }
+                project.configurations.configureEach {
+                    it.resolutionStrategy.eachDependency { dep ->
+                        val requested = dep.requested
+                        if (
+                            requested.group == "org.jetbrains.kotlin" &&
+                                (requested.name == "kotlin-compiler-embeddable" ||
+                                    requested.name == "kotlin-compose-compiler-plugin-embeddable")
+                        ) {
+                            dep.useVersion(compilerPluginVersion)
+                        }
+
+                        if (
+                            requested.group == "androidx.compose.compiler" &&
+                                requested.name == "compiler"
+                        ) {
+                            dep.useTarget(
+                                "org.jetbrains.kotlin:kotlin-compose-compiler-plugin-embeddable:$compilerPluginVersion"
+                            )
+                        }
+                    }
                 }
             }
-        project.dependencies.add(
-            COMPILER_PLUGIN_CONFIGURATION,
-            "androidx.compose.compiler:compiler:$versionToUse"
-        )
+        }
 
         val kotlinPluginProvider =
             project.provider {
@@ -238,7 +253,7 @@
 
             compile.pluginClasspath.from(kotlinPluginProvider.get())
 
-            // todo(b/291587160): enable when Compose compiler 2.0 is merged
+            // todo(b/291587160): enable when Compose compiler 2.0.20 is merged
             // compile.enableFeatureFlag(ComposeFeatureFlag.StrongSkipping)
             // compile.enableFeatureFlag(ComposeFeatureFlag.OptimizeNonSkippingGroups)
             compile.addPluginOption(ComposeCompileOptions.StrongSkipping, "true")
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
index 10cb49a..e453f50 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
@@ -805,11 +805,6 @@
 
             configureAndroidBaseOptions(project, androidXExtension)
 
-            // Move to api that allows settings of targetSdk on each variant's androidTest when
-            // b/335257447 is fixed
-            @Suppress("DEPRECATION")
-            defaultConfig.targetSdk = project.defaultAndroidConfig.targetSdk
-
             val debugSigningConfig = signingConfigs.getByName("debug")
             // Use a local debug keystore to avoid build server issues.
             debugSigningConfig.storeFile = project.getKeystore()
@@ -834,10 +829,15 @@
                 // this is okay because AGP automatically embeds forceCompileSdkPreview in the AAR
                 // metadata and uses it instead of minCompileSdk.
                 it.defaultConfig.aarMetadata.minCompileSdk = it.compileSdk
+                it.lint.targetSdk = project.defaultAndroidConfig.targetSdk
+                it.testOptions.targetSdk = project.defaultAndroidConfig.targetSdk
             }
             beforeVariants(selector().withBuildType("release")) { variant ->
                 (variant as HasUnitTestBuilder).enableUnitTest = false
             }
+            beforeVariants(selector().all()) { variant ->
+                variant.androidTest.targetSdk = project.defaultAndroidConfig.targetSdk
+            }
             onVariants { variant ->
                 variant.configureTests()
                 variant.enableLongMethodTracingInMicrobenchmark(project)
@@ -913,7 +913,8 @@
     ): JavaVersion {
         return when {
             projectName != null && projectName.contains("desktop") -> VERSION_11
-            targetName != null && targetName == "desktop" -> VERSION_11
+            targetName != null && (targetName == "desktop" || targetName == "jvmStubs") ->
+                VERSION_11
             libraryType == LibraryType.COMPILER_PLUGIN -> VERSION_11
             libraryType.compilationTarget == CompilationTarget.HOST -> VERSION_17
             else -> VERSION_1_8
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXMultiplatformExtension.kt b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXMultiplatformExtension.kt
index 7beb7ad..940e9db 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXMultiplatformExtension.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXMultiplatformExtension.kt
@@ -332,6 +332,16 @@
         }
     }
 
+    @JvmOverloads
+    fun jvmStubs(block: Action<KotlinJvmTarget>? = null): KotlinJvmTarget? {
+        supportedPlatforms.add(PlatformIdentifier.JVM_STUBS)
+        return if (project.enableJvm()) {
+            kotlinExtension.jvm("jvmStubs") { block?.execute(this) }
+        } else {
+            null
+        }
+    }
+
     @OptIn(ExperimentalKotlinGradlePluginApi::class)
     @JvmOverloads
     fun android(block: Action<KotlinAndroidTarget>? = null): KotlinAndroidTarget? {
@@ -447,6 +457,12 @@
         }
     }
 
+    /** Configures all ios targets supported by AndroidX. */
+    @JvmOverloads
+    fun ios(block: Action<KotlinNativeTarget>? = null): List<KotlinNativeTarget> {
+        return listOfNotNull(iosX64(block), iosArm64(block), iosSimulatorArm64(block))
+    }
+
     @JvmOverloads
     fun iosArm64(block: Action<KotlinNativeTarget>? = null): KotlinNativeTarget? {
         supportedPlatforms.add(PlatformIdentifier.IOS_ARM_64)
@@ -457,12 +473,6 @@
         }
     }
 
-    /** Configures all ios targets supported by AndroidX. */
-    @JvmOverloads
-    fun ios(block: Action<KotlinNativeTarget>? = null): List<KotlinNativeTarget> {
-        return listOfNotNull(iosX64(block), iosArm64(block), iosSimulatorArm64(block))
-    }
-
     @JvmOverloads
     fun iosX64(block: Action<KotlinNativeTarget>? = null): KotlinNativeTarget? {
         supportedPlatforms.add(PlatformIdentifier.IOS_X_64)
@@ -483,6 +493,93 @@
         }
     }
 
+    /** Configures all watchos targets supported by AndroidX. */
+    @JvmOverloads
+    fun watchos(block: Action<KotlinNativeTarget>? = null): List<KotlinNativeTarget> {
+        return listOfNotNull(
+            watchosX64(block),
+            watchosArm32(block),
+            watchosArm64(block),
+            watchosSimulatorArm64(block)
+        )
+    }
+
+    @JvmOverloads
+    fun watchosArm32(block: Action<KotlinNativeTarget>? = null): KotlinNativeTarget? {
+        supportedPlatforms.add(PlatformIdentifier.WATCHOS_ARM_32)
+        return if (project.enableMac()) {
+            kotlinExtension.watchosArm32().also { block?.execute(it) }
+        } else {
+            null
+        }
+    }
+
+    @JvmOverloads
+    fun watchosArm64(block: Action<KotlinNativeTarget>? = null): KotlinNativeTarget? {
+        supportedPlatforms.add(PlatformIdentifier.WATCHOS_ARM_64)
+        return if (project.enableMac()) {
+            kotlinExtension.watchosArm64().also { block?.execute(it) }
+        } else {
+            null
+        }
+    }
+
+    @JvmOverloads
+    fun watchosX64(block: Action<KotlinNativeTarget>? = null): KotlinNativeTarget? {
+        supportedPlatforms.add(PlatformIdentifier.WATCHOS_X_64)
+        return if (project.enableMac()) {
+            kotlinExtension.watchosX64().also { block?.execute(it) }
+        } else {
+            null
+        }
+    }
+
+    @JvmOverloads
+    fun watchosSimulatorArm64(block: Action<KotlinNativeTarget>? = null): KotlinNativeTarget? {
+        supportedPlatforms.add(PlatformIdentifier.WATCHOS_SIMULATOR_ARM_64)
+        return if (project.enableMac()) {
+            kotlinExtension.watchosSimulatorArm64().also { block?.execute(it) }
+        } else {
+            null
+        }
+    }
+
+    /** Configures all tvos targets supported by AndroidX. */
+    @JvmOverloads
+    fun tvos(block: Action<KotlinNativeTarget>? = null): List<KotlinNativeTarget> {
+        return listOfNotNull(tvosX64(block), tvosArm64(block), tvosSimulatorArm64(block))
+    }
+
+    @JvmOverloads
+    fun tvosArm64(block: Action<KotlinNativeTarget>? = null): KotlinNativeTarget? {
+        supportedPlatforms.add(PlatformIdentifier.TVOS_ARM_64)
+        return if (project.enableMac()) {
+            kotlinExtension.tvosArm64().also { block?.execute(it) }
+        } else {
+            null
+        }
+    }
+
+    @JvmOverloads
+    fun tvosX64(block: Action<KotlinNativeTarget>? = null): KotlinNativeTarget? {
+        supportedPlatforms.add(PlatformIdentifier.TVOS_X_64)
+        return if (project.enableMac()) {
+            kotlinExtension.tvosX64().also { block?.execute(it) }
+        } else {
+            null
+        }
+    }
+
+    @JvmOverloads
+    fun tvosSimulatorArm64(block: Action<KotlinNativeTarget>? = null): KotlinNativeTarget? {
+        supportedPlatforms.add(PlatformIdentifier.TVOS_SIMULATOR_ARM_64)
+        return if (project.enableMac()) {
+            kotlinExtension.tvosSimulatorArm64().also { block?.execute(it) }
+        } else {
+            null
+        }
+    }
+
     @JvmOverloads
     fun linux(block: Action<KotlinNativeTarget>? = null): List<KotlinNativeTarget> {
         return listOfNotNull(
@@ -512,6 +609,16 @@
     }
 
     @JvmOverloads
+    fun linuxX64Stubs(block: Action<KotlinNativeTarget>? = null): KotlinNativeTarget? {
+        supportedPlatforms.add(PlatformIdentifier.LINUX_X_64_STUBS)
+        return if (project.enableLinux()) {
+            kotlinExtension.linuxX64("linuxx64Stubs").also { block?.execute(it) }
+        } else {
+            null
+        }
+    }
+
+    @JvmOverloads
     fun js(block: Action<KotlinJsTargetDsl>? = null): KotlinJsTargetDsl? {
         supportedPlatforms.add(PlatformIdentifier.JS)
         return if (project.enableJs()) {
@@ -642,7 +749,8 @@
      * List of Kotlin target names which may be used as source file suffixes. Any target whose name
      * does not appear in this list will use its [KotlinPlatformType] name.
      */
-    private val allowedTargetNameSuffixes = setOf("android", "desktop", "jvm")
+    private val allowedTargetNameSuffixes =
+        setOf("android", "desktop", "jvm", "jvmStubs", "linuxx64Stubs")
 
     /** The preferred source file suffix for the target's platform type. */
     private val KotlinTarget.preferredSourceFileSuffix: String
@@ -653,3 +761,9 @@
                 platformType.name
             }
 }
+
+/**
+ * Set of targets are there to serve as stubs, but are not expected to be consumed by library
+ * consumers.
+ */
+internal val setOfStubTargets = setOf("jvmStubs", "linuxx64Stubs")
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXRootImplPlugin.kt b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXRootImplPlugin.kt
index 79e005d..0f41141 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXRootImplPlugin.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXRootImplPlugin.kt
@@ -185,10 +185,6 @@
          */
         if (!project.usingMaxDepVersions()) {
             project.plugins.apply("com.autonomousapps.dependency-analysis")
-            project.tasks
-                .withType(com.autonomousapps.tasks.BuildHealthTask::class.java)
-                .configureEach { it.cacheEvenIfNoOutputs() }
-            buildOnServerTask.dependsOn("buildHealth")
         }
     }
 
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/SourceJarTaskHelper.kt b/buildSrc/private/src/main/kotlin/androidx/build/SourceJarTaskHelper.kt
index 5bb2b6d..6efe979 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/SourceJarTaskHelper.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/SourceJarTaskHelper.kt
@@ -158,6 +158,8 @@
             // Different sourceSets in KMP should use different platform infixes, see b/203764756
             task.duplicatesStrategy = DuplicatesStrategy.FAIL
             kmpExtension.targets
+                // Filter out sources from stub targets as they are not intended to be documented
+                .filterNot { it.name in setOfStubTargets }
                 .flatMap { it.mainCompilation().allKotlinSourceSets }
                 .toSet()
                 .forEach { sourceSet ->
@@ -259,6 +261,8 @@
                 )
         )
     kmpExtension.targets.forEach { target ->
+        // Skip adding entries for stub targets are they are not intended to be documented
+        if (target.name in setOfStubTargets) return@forEach
         target.mainCompilation().allKotlinSourceSets.forEach {
             sourceSetsByName.getOrPut(it.name) {
                 mapOf(
diff --git a/buildSrc/public/src/main/kotlin/androidx/build/ApkCopyHelper.kt b/buildSrc/public/src/main/kotlin/androidx/build/ApkCopyHelper.kt
index 1f3e69a..f139a1b 100644
--- a/buildSrc/public/src/main/kotlin/androidx/build/ApkCopyHelper.kt
+++ b/buildSrc/public/src/main/kotlin/androidx/build/ApkCopyHelper.kt
@@ -61,7 +61,7 @@
     project.extensions.findByType(ApplicationAndroidComponentsExtension::class.java)?.apply {
         onVariants(selector().withBuildType(buildType)) { variant ->
             val apkCopy =
-                project.tasks.register("copyAppApk", ApkCopyTask::class.java) { task ->
+                project.tasks.register("copyAppApk-$buildType", ApkCopyTask::class.java) { task ->
                     task.apkFolder.set(variant.artifacts.get(SingleArtifact.APK))
                     task.apkLoader.set(variant.artifacts.getBuiltArtifactsLoader())
                     val file =
diff --git a/buildSrc/public/src/main/kotlin/androidx/build/KmpPlatforms.kt b/buildSrc/public/src/main/kotlin/androidx/build/KmpPlatforms.kt
index 66b59e5..c3893a7 100644
--- a/buildSrc/public/src/main/kotlin/androidx/build/KmpPlatforms.kt
+++ b/buildSrc/public/src/main/kotlin/androidx/build/KmpPlatforms.kt
@@ -59,6 +59,7 @@
     @Suppress("unused") private val group: PlatformGroup
 ) {
     JVM("jvm", PlatformGroup.JVM),
+    JVM_STUBS("jvmStubs", PlatformGroup.JVM),
     JS("js", PlatformGroup.JS),
     ANDROID("android", PlatformGroup.JVM),
     ANDROID_NATIVE_ARM32("androidNativeArm32", PlatformGroup.ANDROID_NATIVE),
@@ -69,9 +70,17 @@
     MAC_OSX_64("macosx64", PlatformGroup.MAC),
     LINUX_ARM_64("linuxarm64", PlatformGroup.LINUX),
     LINUX_X_64("linuxx64", PlatformGroup.LINUX),
+    LINUX_X_64_STUBS("linuxx64Stubs", PlatformGroup.LINUX),
     IOS_SIMULATOR_ARM_64("iossimulatorarm64", PlatformGroup.MAC),
     IOS_X_64("iosx64", PlatformGroup.MAC),
     IOS_ARM_64("iosarm64", PlatformGroup.MAC),
+    WATCHOS_SIMULATOR_ARM_64("watchossimulatorarm64", PlatformGroup.MAC),
+    WATCHOS_X_64("watchosx64", PlatformGroup.MAC),
+    WATCHOS_ARM_32("watchosarm64", PlatformGroup.MAC),
+    WATCHOS_ARM_64("watchosarm64", PlatformGroup.MAC),
+    TVOS_SIMULATOR_ARM_64("tvossimulatorarm64", PlatformGroup.MAC),
+    TVOS_X_64("tvosx64", PlatformGroup.MAC),
+    TVOS_ARM_64("tvosarm64", PlatformGroup.MAC),
     DESKTOP("desktop", PlatformGroup.JVM);
 
     companion object {
diff --git a/buildSrc/shared-dependencies.gradle b/buildSrc/shared-dependencies.gradle
index 27e03e3..356e5ef 100644
--- a/buildSrc/shared-dependencies.gradle
+++ b/buildSrc/shared-dependencies.gradle
@@ -10,17 +10,17 @@
     compileOnly(findGradleKotlinDsl())
 
     // Android Gradle Plugin APIs used by Stable AIDL
-    implementation(libs.androidGradlePluginApi)
+    api(libs.androidGradlePluginApi)
 
     // Plugins we use and configure
+    api(libs.kotlinGradlePluginz)
+    api(libs.kotlinCompilerEmbeddable) // for clang compiler
     implementation(libs.androidGradlePluginz)
     implementation(libs.androidToolsCommon) // for com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION
     implementation(libs.androidToolsRepository) // com.android.repository for Stable AIDL plugin
     implementation(libs.androidToolsSdkCommon) // com.android.ide.common for Stable AIDL plugin
-    implementation(libs.kotlinGradlePluginz)
     implementation(libs.spdxGradlePluginz)
     implementation(libs.androidKotlinMultiplatform)
-    implementation(libs.kotlinCompilerEmbeddable) // for clang compiler
     implementation(libs.binaryCompatibilityValidator)
 
     // For Room Gradle Plugin
@@ -42,7 +42,7 @@
     implementation(libs.ktfmt)
     implementation(libs.kotlinCoroutinesCore)
     implementation(libs.shadow) // used by BundleInsideHelper.kt
-    implementation(libs.apacheAnt) // used in AarManifestTransformerTask.kt for unziping
+    api(libs.apacheAnt) // used in AarManifestTransformerTask.kt for unziping
     implementation(libs.toml)
     implementation(libs.apacheCommonIo) // used in CheckApiEquivalenceTask.kt
 
diff --git a/busytown/androidx_multiplatform_mac_host_tests_arm64.sh b/busytown/androidx_multiplatform_mac_host_tests_arm64.sh
index 5319a5c..7dc0519 100755
--- a/busytown/androidx_multiplatform_mac_host_tests_arm64.sh
+++ b/busytown/androidx_multiplatform_mac_host_tests_arm64.sh
@@ -15,11 +15,14 @@
 # Setup simulators
 impl/androidx-native-mac-simulator-setup.sh
 
-impl/build.sh darwinBenchmarkResults allHostTests \
+# simulator tests disabled due to b/350735930
+impl/build.sh allHostTests \
     --no-configuration-cache \
     -Pandroidx.ignoreTestFailures \
     -Pandroidx.displayTestOutput=false \
     -Pandroidx.lowMemory \
+    -x tvosSimulatorArm64Test \
+    -x watchosSimulatorArm64Test \
     "$@"
 
 echo "Completing $0 at $(date)"
diff --git a/camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/integration/CameraControlAdapterDeviceTest.kt b/camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/integration/CameraControlAdapterDeviceTest.kt
index 89c6a9f..1e453f4 100644
--- a/camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/integration/CameraControlAdapterDeviceTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/integration/CameraControlAdapterDeviceTest.kt
@@ -566,7 +566,7 @@
                     addSurface(deferrableSurface)
                 }
 
-            updateSessionConfig(sessionConfigBuilder.build())
+            updateSessionConfig(listOf(sessionConfigBuilder.build()))
             notifyActive()
         }
 
diff --git a/camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/integration/CaptureConfigAdapterDeviceTest.kt b/camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/integration/CaptureConfigAdapterDeviceTest.kt
index 4bbe5a4..d36f218 100644
--- a/camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/integration/CaptureConfigAdapterDeviceTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/integration/CaptureConfigAdapterDeviceTest.kt
@@ -205,7 +205,7 @@
     ) : FakeUseCase(config) {
 
         fun setupSessionConfig(sessionConfigBuilder: SessionConfig.Builder) {
-            updateSessionConfig(sessionConfigBuilder.build())
+            updateSessionConfig(listOf(sessionConfigBuilder.build()))
             notifyActive()
         }
     }
diff --git a/camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/integration/UseCaseSurfaceManagerDeviceTest.kt b/camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/integration/UseCaseSurfaceManagerDeviceTest.kt
index 28d9ce3..5810c6e 100644
--- a/camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/integration/UseCaseSurfaceManagerDeviceTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/integration/UseCaseSurfaceManagerDeviceTest.kt
@@ -264,7 +264,7 @@
     private fun createFakeUseCase() =
         object : FakeUseCase(FakeUseCaseConfig.Builder().setTargetName("UseCase").useCaseConfig) {
             fun setupSessionConfig(sessionConfig: SessionConfig) {
-                updateSessionConfig(sessionConfig)
+                updateSessionConfig(listOf(sessionConfig))
                 notifyActive()
             }
         }
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraInternalAdapter.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraInternalAdapter.kt
index 4854a50..ad25703 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraInternalAdapter.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraInternalAdapter.kt
@@ -57,6 +57,7 @@
         CameraConfigs.defaultConfig()
     private val debugId = cameraAdapterIds.incrementAndGet()
     private var sessionProcessor: SessionProcessor? = null
+    private var isPrimary = true
 
     init {
         debug { "Created $this for $cameraId" }
@@ -83,6 +84,10 @@
         debug { "$this#close" }
     }
 
+    override fun setPrimary(isPrimary: Boolean) {
+        this.isPrimary = isPrimary
+    }
+
     override fun setActiveResumingMode(enabled: Boolean) {
         useCaseManager.setActiveResumeMode(enabled)
     }
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraSurfaceAdapter.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraSurfaceAdapter.kt
index 9c2c3dd..b5474c5 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraSurfaceAdapter.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraSurfaceAdapter.kt
@@ -133,6 +133,7 @@
      * @param newUseCaseConfigsSupportedSizeMap map of configurations of the use cases to the
      *   supported sizes list that will be given a suggested stream specification
      * @param isPreviewStabilizationOn whether the preview stabilization is enabled.
+     * @param hasVideoCapture whether the use cases has video capture.
      * @return map of suggested stream specifications for given use cases
      * @throws IllegalArgumentException if {@code newUseCaseConfigs} is an empty list, if there
      *   isn't a supported combination of surfaces available, or if the {@code cameraId} is not a
@@ -143,7 +144,8 @@
         cameraId: String,
         existingSurfaces: List<AttachedSurfaceInfo>,
         newUseCaseConfigsSupportedSizeMap: Map<UseCaseConfig<*>, List<Size>>,
-        isPreviewStabilizationOn: Boolean
+        isPreviewStabilizationOn: Boolean,
+        hasVideoCapture: Boolean
     ): Pair<Map<UseCaseConfig<*>, StreamSpec>, Map<AttachedSurfaceInfo, StreamSpec>> {
 
         if (!checkIfSupportedCombinationExist(cameraId)) {
@@ -156,7 +158,8 @@
             cameraMode,
             existingSurfaces,
             newUseCaseConfigsSupportedSizeMap,
-            isPreviewStabilizationOn
+            isPreviewStabilizationOn,
+            hasVideoCapture
         )
     }
 }
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/SessionConfigAdapter.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/SessionConfigAdapter.kt
index 1776fcb..43e1835 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/SessionConfigAdapter.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/SessionConfigAdapter.kt
@@ -109,11 +109,8 @@
         CoroutineScope(Dispatchers.Main.immediate).launch {
             // The error listener is used to notify the UseCase to recreate the pipeline,
             // and the create pipeline task would be executed on the main thread.
-            sessionConfig?.errorListeners?.forEach {
-                it.onError(
-                    sessionConfig,
-                    SessionConfig.SessionError.SESSION_ERROR_SURFACE_NEEDS_RESET
-                )
+            sessionConfig?.errorListener?.apply {
+                onError(sessionConfig, SessionConfig.SessionError.SESSION_ERROR_SURFACE_NEEDS_RESET)
             }
         }
     }
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/SupportedSurfaceCombination.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/SupportedSurfaceCombination.kt
index b2441af..74bba1f 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/SupportedSurfaceCombination.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/SupportedSurfaceCombination.kt
@@ -235,6 +235,7 @@
      * @param newUseCaseConfigsSupportedSizeMap newly added UseCaseConfig to supported output sizes
      *   map.
      * @param isPreviewStabilizationOn whether the preview stabilization is enabled.
+     * @param hasVideoCapture whether the use cases has video capture.
      * @return the suggested stream specs, which is a mapping from UseCaseConfig to the suggested
      *   stream specification.
      * @throws IllegalArgumentException if the suggested solution for newUseCaseConfigs cannot be
@@ -244,7 +245,8 @@
         cameraMode: Int,
         attachedSurfaces: List<AttachedSurfaceInfo>,
         newUseCaseConfigsSupportedSizeMap: Map<UseCaseConfig<*>, List<Size>>,
-        isPreviewStabilizationOn: Boolean = false
+        isPreviewStabilizationOn: Boolean = false,
+        hasVideoCapture: Boolean = false
     ): Pair<Map<UseCaseConfig<*>, StreamSpec>, Map<AttachedSurfaceInfo, StreamSpec>> {
         // Refresh Preview Size based on current display configurations.
         refreshPreviewSize()
@@ -336,6 +338,7 @@
                 newUseCaseConfigs,
                 useCasesPriorityOrder,
                 resolvedDynamicRanges,
+                hasVideoCapture
             )
         val attachedSurfaceStreamSpecMap = mutableMapOf<AttachedSurfaceInfo, StreamSpec>()
 
@@ -808,6 +811,7 @@
         newUseCaseConfigs: List<UseCaseConfig<*>>,
         useCasesPriorityOrder: List<Int>,
         resolvedDynamicRanges: Map<UseCaseConfig<*>, DynamicRange>,
+        hasVideoCapture: Boolean
     ): MutableMap<UseCaseConfig<*>, StreamSpec> {
         val suggestedStreamSpecMap = mutableMapOf<UseCaseConfig<*>, StreamSpec>()
         var targetFrameRateForDevice: Range<Int>? = null
@@ -824,6 +828,7 @@
                     .setImplementationOptions(
                         StreamUseCaseUtil.getStreamSpecImplementationOptions(useCaseConfig)
                     )
+                    .setZslDisabled(hasVideoCapture)
 
             if (targetFrameRateForDevice != null) {
                 streamSpecBuilder.setExpectedFrameRateRange(targetFrameRateForDevice)
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/ImageCaptureFailedForVideoSnapshotQuirk.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/ImageCaptureFailedForVideoSnapshotQuirk.kt
index e60cd90..32b27e8 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/ImageCaptureFailedForVideoSnapshotQuirk.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/ImageCaptureFailedForVideoSnapshotQuirk.kt
@@ -24,7 +24,7 @@
 
 /**
  * QuirkSummary
- * - Bug Id: b/344704367
+ * - Bug Id: b/344704367, b/349542870
  * - Description: When taking pictures with [CameraDevice.TEMPLATE_VIDEO_SNAPSHOT], there is no
  *   response from camera HAL. On itel l6006, itel w6004, moto g(20), moto e13, moto e20, rmx3231,
  *   rmx3511, sm-a032f, sm-a035m, it happens when there are only two surfaces (JPEG + ANY) are
@@ -32,16 +32,19 @@
  *   GraphicBufferSource (ex: when OpenGL pipeline is used, the Surface is from SurfaceTexture) no
  *   matter how many surfaces are configured to camera capture session. All the above devices adopt
  *   UniSoc chipset. The workaround is to use [CaptureRequest.CONTROL_CAPTURE_INTENT_STILL_CAPTURE]
- *   instead of [CaptureRequest.CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT] on UniSoc chipset devices.
+ *   instead of [CaptureRequest.CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT] on UniSoc chipset devices. On
+ *   the Huawei P Smart (b/349542870), taking pictures consistently fails when using
+ *   CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT, regardless of the surface combinations or capture intent
+ *   specified in repeated request.
  * - Device(s): itel l6006, itel w6004, moto g(20), moto e13, moto e20, rmx3231, rmx3511, sm-a032f,
- *   sm-a035m, tecno mobile bf6.
+ *   sm-a035m, tecno mobile bf6, Huawei P Smart.
  */
 @SuppressLint("CameraXQuirksClassDetector")
 class ImageCaptureFailedForVideoSnapshotQuirk : Quirk {
 
     companion object {
         fun isEnabled(): Boolean {
-            return isUniSocChipsetDevice()
+            return isUniSocChipsetDevice() || isHuaweiPSmart()
         }
 
         private val PROBLEMATIC_UNI_SOC_MODELS =
@@ -68,5 +71,10 @@
                 ("itel".equals(Build.BRAND, ignoreCase = true) &&
                     Build.HARDWARE.lowercase().startsWith("sp"))
         }
+
+        private fun isHuaweiPSmart(): Boolean {
+            return "HUAWEI".equals(Build.BRAND, ignoreCase = true) &&
+                "FIG-LX1".equals(Build.MODEL, ignoreCase = true)
+        }
     }
 }
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/MeteringRepeating.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/MeteringRepeating.kt
index 3edeefb..5dd8c6b 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/MeteringRepeating.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/MeteringRepeating.kt
@@ -37,6 +37,7 @@
 import androidx.camera.core.impl.ImmediateSurface
 import androidx.camera.core.impl.MutableOptionsBundle
 import androidx.camera.core.impl.SessionConfig
+import androidx.camera.core.impl.SessionConfig.CloseableErrorListener
 import androidx.camera.core.impl.StreamSpec
 import androidx.camera.core.impl.UseCaseConfig
 import androidx.camera.core.impl.UseCaseConfig.OPTION_CAPTURE_TYPE
@@ -63,6 +64,8 @@
 
     private val deferrableSurfaceLock = Any()
 
+    private var closeableErrorListener: CloseableErrorListener? = null
+
     @GuardedBy("deferrableSurfaceLock") private var deferrableSurface: DeferrableSurface? = null
 
     override fun getDefaultConfig(applyDefaultConfig: Boolean, factory: UseCaseConfigFactory) =
@@ -71,10 +74,13 @@
     override fun getUseCaseConfigBuilder(config: Config) =
         Builder(cameraProperties, displayInfoManager)
 
-    override fun onSuggestedStreamSpecUpdated(suggestedStreamSpec: StreamSpec): StreamSpec {
-        updateSessionConfig(createPipeline(meteringSurfaceSize).build())
+    override fun onSuggestedStreamSpecUpdated(
+        primaryStreamSpec: StreamSpec,
+        secondaryStreamSpec: StreamSpec?,
+    ): StreamSpec {
+        updateSessionConfig(listOf(createPipeline(meteringSurfaceSize).build()))
         notifyActive()
-        return suggestedStreamSpec.toBuilder().setResolution(meteringSurfaceSize).build()
+        return primaryStreamSpec.toBuilder().setResolution(meteringSurfaceSize).build()
     }
 
     override fun onUnbind() {
@@ -88,7 +94,7 @@
     fun setupSession() {
         // The suggested stream spec passed to `updateSuggestedStreamSpec` doesn't matter since
         // this use case uses the min preview size.
-        updateSuggestedStreamSpec(StreamSpec.builder(DEFAULT_PREVIEW_SIZE).build())
+        updateSuggestedStreamSpec(StreamSpec.builder(DEFAULT_PREVIEW_SIZE).build(), null)
     }
 
     private fun createPipeline(resolution: Size): SessionConfig.Builder {
@@ -112,13 +118,18 @@
                 )
         }
 
+        // Closes the old error listener if there is
+        closeableErrorListener?.close()
+        val errorListener = CloseableErrorListener { _, _ ->
+            updateSessionConfig(listOf(createPipeline(resolution).build()))
+            notifyReset()
+        }
+        closeableErrorListener = errorListener
+
         return SessionConfig.Builder.createFrom(MeteringRepeatingConfig(), resolution).apply {
             setTemplateType(CameraDevice.TEMPLATE_PREVIEW)
             addSurface(deferrableSurface!!)
-            addErrorListener { _, _ ->
-                updateSessionConfig(createPipeline(resolution).build())
-                notifyReset()
-            }
+            setErrorListener(errorListener)
         }
     }
 
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt
index 1efebfd..aaefadf 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt
@@ -549,7 +549,7 @@
 
     @GuardedBy("lock")
     private fun addRepeatingUseCase() {
-        meteringRepeating.bindToCamera(cameraInternal.get(), null, null)
+        meteringRepeating.bindToCamera(cameraInternal.get(), null, null, null)
         meteringRepeating.setupSession()
         attach(listOf(meteringRepeating))
         activate(meteringRepeating)
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/FocusMeteringControlTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/FocusMeteringControlTest.kt
index dc0d559..b5bcfe9 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/FocusMeteringControlTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/FocusMeteringControlTest.kt
@@ -637,7 +637,7 @@
     fun customFovAdjusted() {
         // 16:9 to 4:3
         val useCase = FakeUseCase()
-        useCase.updateSuggestedStreamSpec(StreamSpec.builder(Size(1920, 1080)).build())
+        useCase.updateSuggestedStreamSpec(StreamSpec.builder(Size(1920, 1080)).build(), null)
 
         val factory = SurfaceOrientedMeteringPointFactory(1.0f, 1.0f, useCase)
         val point = factory.createPoint(0f, 0f)
@@ -1723,9 +1723,10 @@
                 )
             }
             .also {
-                it.bindToCamera(FakeCamera("0"), null, null)
+                it.bindToCamera(FakeCamera("0"), null, null, null)
                 it.updateSuggestedStreamSpec(
-                    StreamSpec.builder(suggestedStreamSpecResolution).build()
+                    StreamSpec.builder(suggestedStreamSpecResolution).build(),
+                    null
                 )
             }
 
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/SessionConfigAdapterTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/SessionConfigAdapterTest.kt
index 28fb432..a11268a 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/SessionConfigAdapterTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/SessionConfigAdapterTest.kt
@@ -95,7 +95,7 @@
                 SessionConfig.Builder().also { sessionConfigBuilder ->
                     sessionConfigBuilder.setTemplateType(CameraDevice.TEMPLATE_PREVIEW)
                     sessionConfigBuilder.addSurface(testDeferrableSurface)
-                    sessionConfigBuilder.addErrorListener(errorListener)
+                    sessionConfigBuilder.setErrorListener(errorListener)
                 }
             )
         }
@@ -104,7 +104,7 @@
                 SessionConfig.Builder().also { sessionConfigBuilder ->
                     sessionConfigBuilder.setTemplateType(CameraDevice.TEMPLATE_PREVIEW)
                     sessionConfigBuilder.addSurface(createTestDeferrableSurface().apply { close() })
-                    sessionConfigBuilder.addErrorListener(errorListener)
+                    sessionConfigBuilder.setErrorListener(errorListener)
                 }
             )
         }
@@ -150,7 +150,7 @@
     var cameraControlReady = false
 
     fun setupSessionConfig(sessionConfigBuilder: SessionConfig.Builder) {
-        updateSessionConfig(sessionConfigBuilder.build())
+        updateSessionConfig(listOf(sessionConfigBuilder.build()))
         notifyActive()
     }
 
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/SupportedSurfaceCombinationTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/SupportedSurfaceCombinationTest.kt
index 52a48a5..551b056b 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/SupportedSurfaceCombinationTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/SupportedSurfaceCombinationTest.kt
@@ -24,6 +24,7 @@
 import android.hardware.camera2.CameraCharacteristics.REQUEST_RECOMMENDED_TEN_BIT_DYNAMIC_RANGE_PROFILE
 import android.hardware.camera2.CameraManager
 import android.hardware.camera2.CameraMetadata
+import android.hardware.camera2.CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED
 import android.hardware.camera2.params.DynamicRangeProfiles
 import android.hardware.camera2.params.StreamConfigurationMap
 import android.media.CamcorderProfile.QUALITY_1080P
@@ -79,6 +80,7 @@
 import androidx.camera.core.impl.SurfaceConfig
 import androidx.camera.core.impl.UseCaseConfig
 import androidx.camera.core.impl.UseCaseConfigFactory
+import androidx.camera.core.impl.UseCaseConfigFactory.CaptureType
 import androidx.camera.core.internal.utils.SizeUtil
 import androidx.camera.core.internal.utils.SizeUtil.RESOLUTION_1440P
 import androidx.camera.core.internal.utils.SizeUtil.RESOLUTION_720P
@@ -1466,6 +1468,34 @@
         )
     }
 
+    @Test
+    fun hasVideoCapture_suggestedStreamSpecZslDisabled() {
+        val useCase1 = createUseCase(CaptureType.VIDEO_CAPTURE) // VIDEO
+        val useCase2 = createUseCase(CaptureType.PREVIEW) // PREVIEW
+        val useCaseExpectedResultMap =
+            mutableMapOf<UseCase, Size>().apply {
+                put(useCase1, recordSize)
+                put(useCase2, previewSize)
+            }
+        getSuggestedSpecsAndVerify(
+            useCaseExpectedResultMap,
+            hardwareLevel = INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED,
+            hasVideoCapture = true
+        )
+    }
+
+    @Test
+    fun hasNoVideoCapture_suggestedStreamSpecZslNotDisabled() {
+        val privUseCase = createUseCase(CaptureType.PREVIEW) // PREVIEW
+        val jpegUseCase = createUseCase(CaptureType.IMAGE_CAPTURE) // JPEG
+        val useCaseExpectedResultMap =
+            mutableMapOf<UseCase, Size>().apply {
+                put(privUseCase, if (Build.VERSION.SDK_INT == 21) RESOLUTION_VGA else previewSize)
+                put(jpegUseCase, maximumSize)
+            }
+        getSuggestedSpecsAndVerify(useCaseExpectedResultMap, hasVideoCapture = false)
+    }
+
     private fun getSuggestedSpecsAndVerify(
         useCasesExpectedResultMap: Map<UseCase, Size>,
         attachedSurfaceInfoList: List<AttachedSurfaceInfo> = emptyList(),
@@ -1477,6 +1507,8 @@
         useCasesExpectedDynamicRangeMap: Map<UseCase, DynamicRange> = emptyMap(),
         dynamicRangeProfiles: DynamicRangeProfiles? = null,
         default10BitProfile: Long? = null,
+        isPreviewStabilizationOn: Boolean = false,
+        hasVideoCapture: Boolean = false
     ): Pair<Map<UseCaseConfig<*>, StreamSpec>, Map<AttachedSurfaceInfo, StreamSpec>> {
         setupCamera(
             hardwareLevel = hardwareLevel,
@@ -1494,7 +1526,9 @@
             supportedSurfaceCombination.getSuggestedStreamSpecifications(
                 cameraMode,
                 attachedSurfaceInfoList,
-                useCaseConfigToOutputSizesMap
+                useCaseConfigToOutputSizesMap,
+                isPreviewStabilizationOn,
+                hasVideoCapture
             )
         val suggestedStreamSpecsForNewUseCases = resultPair.first
         val suggestedStreamSpecsForOldSurfaces = resultPair.second
@@ -1515,6 +1549,8 @@
                     )
                     .isEqualTo(compareExpectedFps)
             }
+            val zslDisabled = suggestedStreamSpecsForNewUseCases[useCaseConfigMap[it]]!!.zslDisabled
+            assertThat(zslDisabled == hasVideoCapture)
         }
 
         useCasesExpectedDynamicRangeMap.keys.forEach {
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/MeteringRepeatingTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/MeteringRepeatingTest.kt
index 4d68ac8..4fd20d7 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/MeteringRepeatingTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/MeteringRepeatingTest.kt
@@ -161,7 +161,7 @@
     fun surfaceResolutionIsLargestLessThan640x480_when640x480NotPresentInOutputSizes() {
         meteringRepeating = getMeteringRepeatingAndInitDisplay(dummySizeListWithout640x480)
 
-        meteringRepeating.updateSuggestedStreamSpec(dummyZeroSizeStreamSpec)
+        meteringRepeating.updateSuggestedStreamSpec(dummyZeroSizeStreamSpec, null)
 
         assertEquals(Size(320, 240), meteringRepeating.attachedSurfaceResolution)
     }
@@ -170,7 +170,7 @@
     fun surfaceResolutionIs640x480_when640x480PresentInOutputSizes() {
         meteringRepeating = getMeteringRepeatingAndInitDisplay(dummySizeListWith640x480)
 
-        meteringRepeating.updateSuggestedStreamSpec(dummyZeroSizeStreamSpec)
+        meteringRepeating.updateSuggestedStreamSpec(dummyZeroSizeStreamSpec, null)
 
         assertEquals(Size(640, 480), meteringRepeating.attachedSurfaceResolution)
     }
@@ -179,7 +179,7 @@
     fun surfaceResolutionFallsBackToMinimum_whenAllOutputSizesLargerThan640x480() {
         meteringRepeating = getMeteringRepeatingAndInitDisplay(dummySizeListWithoutSmaller)
 
-        meteringRepeating.updateSuggestedStreamSpec(dummyZeroSizeStreamSpec)
+        meteringRepeating.updateSuggestedStreamSpec(dummyZeroSizeStreamSpec, null)
 
         assertEquals(Size(1280, 720), meteringRepeating.attachedSurfaceResolution)
     }
@@ -188,7 +188,7 @@
     fun surfaceResolutionIsLargestWithinPreviewSize_whenAllOutputSizesLessThan640x480() {
         meteringRepeating = getMeteringRepeatingAndInitDisplay(dummySizeListSmallerThan640x480)
 
-        meteringRepeating.updateSuggestedStreamSpec(dummyZeroSizeStreamSpec)
+        meteringRepeating.updateSuggestedStreamSpec(dummyZeroSizeStreamSpec, null)
 
         assertEquals(Size(320, 480), meteringRepeating.attachedSurfaceResolution)
     }
@@ -198,7 +198,7 @@
         meteringRepeating =
             getMeteringRepeatingAndInitDisplay(dummySizeListNotWithin320x240And640x480)
 
-        meteringRepeating.updateSuggestedStreamSpec(dummyZeroSizeStreamSpec)
+        meteringRepeating.updateSuggestedStreamSpec(dummyZeroSizeStreamSpec, null)
 
         assertThat(meteringRepeating.attachedSurfaceResolution).isEqualTo(Size(240, 144))
     }
@@ -211,7 +211,7 @@
         meteringRepeating =
             getMeteringRepeatingAndInitDisplay(dummySizeListNotWithin320x240And640x480)
 
-        meteringRepeating.updateSuggestedStreamSpec(dummyZeroSizeStreamSpec)
+        meteringRepeating.updateSuggestedStreamSpec(dummyZeroSizeStreamSpec, null)
 
         assertThat(meteringRepeating.attachedSurfaceResolution).isEqualTo(Size(1280, 720))
     }
@@ -223,7 +223,7 @@
 
         meteringRepeating = getMeteringRepeatingAndInitDisplay(dummySizeListSmallerThan320x240)
 
-        meteringRepeating.updateSuggestedStreamSpec(dummyZeroSizeStreamSpec)
+        meteringRepeating.updateSuggestedStreamSpec(dummyZeroSizeStreamSpec, null)
 
         assertThat(meteringRepeating.attachedSurfaceResolution).isEqualTo(Size(240, 144))
     }
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/UseCaseCameraTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/UseCaseCameraTest.kt
index df4439a..c900d84 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/UseCaseCameraTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/UseCaseCameraTest.kt
@@ -151,7 +151,7 @@
     FakeUseCase(FakeUseCaseConfig.Builder().setTargetName("UseCase").useCaseConfig) {
 
     fun setupSessionConfig(sessionConfigBuilder: SessionConfig.Builder) {
-        updateSessionConfig(sessionConfigBuilder.build())
+        updateSessionConfig(listOf(sessionConfigBuilder.build()))
         notifyActive()
     }
 }
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManagerTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManagerTest.kt
index c295a48..89ed085 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManagerTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManagerTest.kt
@@ -719,11 +719,12 @@
         bindToCamera(
             FakeCamera("0"),
             null,
+            null,
             getDefaultConfig(
                 true,
                 CameraUseCaseAdapter(ApplicationProvider.getApplicationContext())
             )
         )
-        updateSuggestedStreamSpec(StreamSpec.builder(supportedSizes[0]).build())
+        updateSuggestedStreamSpec(StreamSpec.builder(supportedSizes[0]).build(), null)
     }
 }
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/UseCaseSurfaceManagerTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/UseCaseSurfaceManagerTest.kt
index 6ac4d25..d3bcdd1 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/UseCaseSurfaceManagerTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/UseCaseSurfaceManagerTest.kt
@@ -94,7 +94,7 @@
                 SessionConfig.Builder().also { sessionConfigBuilder ->
                     sessionConfigBuilder.setTemplateType(CameraDevice.TEMPLATE_PREVIEW)
                     sessionConfigBuilder.addSurface(testDeferrableSurface1)
-                    sessionConfigBuilder.addErrorListener(errorListener)
+                    sessionConfigBuilder.setErrorListener(errorListener)
                 }
             )
         }
@@ -103,7 +103,7 @@
                 SessionConfig.Builder().also { sessionConfigBuilder ->
                     sessionConfigBuilder.setTemplateType(CameraDevice.TEMPLATE_PREVIEW)
                     sessionConfigBuilder.addSurface(testDeferrableSurface2)
-                    sessionConfigBuilder.addErrorListener(errorListener)
+                    sessionConfigBuilder.setErrorListener(errorListener)
                 }
             )
         }
@@ -222,7 +222,7 @@
                 SessionConfig.Builder().also { sessionConfigBuilder ->
                     sessionConfigBuilder.setTemplateType(CameraDevice.TEMPLATE_PREVIEW)
                     sessionConfigBuilder.addSurface(neverCompleteDeferrableSurface)
-                    sessionConfigBuilder.addErrorListener(errorListener)
+                    sessionConfigBuilder.setErrorListener(errorListener)
                 }
             )
         }
@@ -292,7 +292,7 @@
                 SessionConfig.Builder().also { sessionConfigBuilder ->
                     sessionConfigBuilder.setTemplateType(CameraDevice.TEMPLATE_PREVIEW)
                     sessionConfigBuilder.addSurface(neverCompleteDeferrableSurface)
-                    sessionConfigBuilder.addErrorListener(errorListener)
+                    sessionConfigBuilder.setErrorListener(errorListener)
                 }
             )
         }
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/internal/StreamUseCaseTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/internal/StreamUseCaseTest.kt
index f1833ef..8055baf 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/internal/StreamUseCaseTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/internal/StreamUseCaseTest.kt
@@ -29,6 +29,7 @@
 import androidx.camera.core.DynamicRange
 import androidx.camera.core.ImageCapture
 import androidx.camera.core.ImageCapture.CaptureMode
+import androidx.camera.core.LayoutSettings
 import androidx.camera.core.UseCase
 import androidx.camera.core.impl.AttachedSurfaceInfo
 import androidx.camera.core.impl.CameraMode
@@ -639,7 +640,15 @@
                 FakeUseCase(FakeUseCaseConfig.Builder().useCaseConfig, CaptureType.IMAGE_CAPTURE),
                 FakeUseCase(FakeUseCaseConfig.Builder().useCaseConfig, CaptureType.VIDEO_CAPTURE)
             )
-        val streamSharing = StreamSharing(FakeCamera(), children, useCaseConfigFactory)
+        val streamSharing =
+            StreamSharing(
+                FakeCamera(),
+                null,
+                LayoutSettings.DEFAULT,
+                LayoutSettings.DEFAULT,
+                children,
+                useCaseConfigFactory
+            )
         val surfaceConfigAttachedSurfaceInfoMap: Map<Int, AttachedSurfaceInfo> = mutableMapOf()
         val surfaceConfigUseCaseConfigMap: MutableMap<Int, UseCaseConfig<*>> = mutableMapOf()
         surfaceConfigUseCaseConfigMap[0] =
diff --git a/camera/camera-camera2/api/1.4.0-beta03.txt b/camera/camera-camera2/api/1.4.0-beta03.txt
new file mode 100644
index 0000000..2962218
--- /dev/null
+++ b/camera/camera-camera2/api/1.4.0-beta03.txt
@@ -0,0 +1,54 @@
+// Signature format: 4.0
+package androidx.camera.camera2 {
+
+  public final class Camera2Config {
+    method public static androidx.camera.core.CameraXConfig defaultConfig();
+  }
+
+}
+
+package androidx.camera.camera2.interop {
+
+  @SuppressCompatibility @androidx.camera.camera2.interop.ExperimentalCamera2Interop public final class Camera2CameraControl {
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> addCaptureRequestOptions(androidx.camera.camera2.interop.CaptureRequestOptions);
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> clearCaptureRequestOptions();
+    method public static androidx.camera.camera2.interop.Camera2CameraControl from(androidx.camera.core.CameraControl);
+    method public androidx.camera.camera2.interop.CaptureRequestOptions getCaptureRequestOptions();
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setCaptureRequestOptions(androidx.camera.camera2.interop.CaptureRequestOptions);
+  }
+
+  @SuppressCompatibility @androidx.camera.camera2.interop.ExperimentalCamera2Interop public final class Camera2CameraInfo {
+    method public static androidx.camera.camera2.interop.Camera2CameraInfo from(androidx.camera.core.CameraInfo);
+    method public <T> T? getCameraCharacteristic(android.hardware.camera2.CameraCharacteristics.Key<T!>);
+    method public String getCameraId();
+  }
+
+  @SuppressCompatibility @androidx.camera.camera2.interop.ExperimentalCamera2Interop public final class Camera2Interop {
+  }
+
+  public static final class Camera2Interop.Extender<T> {
+    ctor public Camera2Interop.Extender(androidx.camera.core.ExtendableBuilder<T!>);
+    method public <ValueT> androidx.camera.camera2.interop.Camera2Interop.Extender<T!> setCaptureRequestOption(android.hardware.camera2.CaptureRequest.Key<ValueT!>, ValueT);
+    method public androidx.camera.camera2.interop.Camera2Interop.Extender<T!> setDeviceStateCallback(android.hardware.camera2.CameraDevice.StateCallback);
+    method @RequiresApi(28) public androidx.camera.camera2.interop.Camera2Interop.Extender<T!> setPhysicalCameraId(String);
+    method public androidx.camera.camera2.interop.Camera2Interop.Extender<T!> setSessionCaptureCallback(android.hardware.camera2.CameraCaptureSession.CaptureCallback);
+    method public androidx.camera.camera2.interop.Camera2Interop.Extender<T!> setSessionStateCallback(android.hardware.camera2.CameraCaptureSession.StateCallback);
+    method @RequiresApi(33) public androidx.camera.camera2.interop.Camera2Interop.Extender<T!> setStreamUseCase(long);
+  }
+
+  @SuppressCompatibility @androidx.camera.camera2.interop.ExperimentalCamera2Interop public class CaptureRequestOptions {
+    method public <ValueT> ValueT? getCaptureRequestOption(android.hardware.camera2.CaptureRequest.Key<ValueT!>);
+  }
+
+  public static final class CaptureRequestOptions.Builder implements androidx.camera.core.ExtendableBuilder<androidx.camera.camera2.interop.CaptureRequestOptions!> {
+    ctor public CaptureRequestOptions.Builder();
+    method public androidx.camera.camera2.interop.CaptureRequestOptions build();
+    method public <ValueT> androidx.camera.camera2.interop.CaptureRequestOptions.Builder clearCaptureRequestOption(android.hardware.camera2.CaptureRequest.Key<ValueT!>);
+    method public <ValueT> androidx.camera.camera2.interop.CaptureRequestOptions.Builder setCaptureRequestOption(android.hardware.camera2.CaptureRequest.Key<ValueT!>, ValueT);
+  }
+
+  @SuppressCompatibility @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface ExperimentalCamera2Interop {
+  }
+
+}
+
diff --git a/camera/camera-camera2/api/res-1.4.0-beta03.txt b/camera/camera-camera2/api/res-1.4.0-beta03.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/camera/camera-camera2/api/res-1.4.0-beta03.txt
diff --git a/camera/camera-camera2/api/restricted_1.4.0-beta03.txt b/camera/camera-camera2/api/restricted_1.4.0-beta03.txt
new file mode 100644
index 0000000..2962218
--- /dev/null
+++ b/camera/camera-camera2/api/restricted_1.4.0-beta03.txt
@@ -0,0 +1,54 @@
+// Signature format: 4.0
+package androidx.camera.camera2 {
+
+  public final class Camera2Config {
+    method public static androidx.camera.core.CameraXConfig defaultConfig();
+  }
+
+}
+
+package androidx.camera.camera2.interop {
+
+  @SuppressCompatibility @androidx.camera.camera2.interop.ExperimentalCamera2Interop public final class Camera2CameraControl {
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> addCaptureRequestOptions(androidx.camera.camera2.interop.CaptureRequestOptions);
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> clearCaptureRequestOptions();
+    method public static androidx.camera.camera2.interop.Camera2CameraControl from(androidx.camera.core.CameraControl);
+    method public androidx.camera.camera2.interop.CaptureRequestOptions getCaptureRequestOptions();
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setCaptureRequestOptions(androidx.camera.camera2.interop.CaptureRequestOptions);
+  }
+
+  @SuppressCompatibility @androidx.camera.camera2.interop.ExperimentalCamera2Interop public final class Camera2CameraInfo {
+    method public static androidx.camera.camera2.interop.Camera2CameraInfo from(androidx.camera.core.CameraInfo);
+    method public <T> T? getCameraCharacteristic(android.hardware.camera2.CameraCharacteristics.Key<T!>);
+    method public String getCameraId();
+  }
+
+  @SuppressCompatibility @androidx.camera.camera2.interop.ExperimentalCamera2Interop public final class Camera2Interop {
+  }
+
+  public static final class Camera2Interop.Extender<T> {
+    ctor public Camera2Interop.Extender(androidx.camera.core.ExtendableBuilder<T!>);
+    method public <ValueT> androidx.camera.camera2.interop.Camera2Interop.Extender<T!> setCaptureRequestOption(android.hardware.camera2.CaptureRequest.Key<ValueT!>, ValueT);
+    method public androidx.camera.camera2.interop.Camera2Interop.Extender<T!> setDeviceStateCallback(android.hardware.camera2.CameraDevice.StateCallback);
+    method @RequiresApi(28) public androidx.camera.camera2.interop.Camera2Interop.Extender<T!> setPhysicalCameraId(String);
+    method public androidx.camera.camera2.interop.Camera2Interop.Extender<T!> setSessionCaptureCallback(android.hardware.camera2.CameraCaptureSession.CaptureCallback);
+    method public androidx.camera.camera2.interop.Camera2Interop.Extender<T!> setSessionStateCallback(android.hardware.camera2.CameraCaptureSession.StateCallback);
+    method @RequiresApi(33) public androidx.camera.camera2.interop.Camera2Interop.Extender<T!> setStreamUseCase(long);
+  }
+
+  @SuppressCompatibility @androidx.camera.camera2.interop.ExperimentalCamera2Interop public class CaptureRequestOptions {
+    method public <ValueT> ValueT? getCaptureRequestOption(android.hardware.camera2.CaptureRequest.Key<ValueT!>);
+  }
+
+  public static final class CaptureRequestOptions.Builder implements androidx.camera.core.ExtendableBuilder<androidx.camera.camera2.interop.CaptureRequestOptions!> {
+    ctor public CaptureRequestOptions.Builder();
+    method public androidx.camera.camera2.interop.CaptureRequestOptions build();
+    method public <ValueT> androidx.camera.camera2.interop.CaptureRequestOptions.Builder clearCaptureRequestOption(android.hardware.camera2.CaptureRequest.Key<ValueT!>);
+    method public <ValueT> androidx.camera.camera2.interop.CaptureRequestOptions.Builder setCaptureRequestOption(android.hardware.camera2.CaptureRequest.Key<ValueT!>, ValueT);
+  }
+
+  @SuppressCompatibility @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface ExperimentalCamera2Interop {
+  }
+
+}
+
diff --git a/camera/camera-camera2/build.gradle b/camera/camera-camera2/build.gradle
index 04ce49c..5fdd589 100644
--- a/camera/camera-camera2/build.gradle
+++ b/camera/camera-camera2/build.gradle
@@ -34,6 +34,7 @@
     api("androidx.annotation:annotation:1.2.0")
     implementation("androidx.core:core:1.1.0")
     implementation("androidx.concurrent:concurrent-futures:1.0.0")
+    implementation("androidx.tracing:tracing:1.2.0")
     implementation(libs.guavaListenableFuture)
     implementation(libs.autoValueAnnotations)
 
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2CameraImplTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2CameraImplTest.java
index bb80af5..76d5559 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2CameraImplTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2CameraImplTest.java
@@ -72,6 +72,7 @@
 import androidx.camera.core.CameraControl;
 import androidx.camera.core.CameraSelector;
 import androidx.camera.core.ImageCapture;
+import androidx.camera.core.LayoutSettings;
 import androidx.camera.core.Preview;
 import androidx.camera.core.UseCase;
 import androidx.camera.core.impl.CameraCaptureCallback;
@@ -944,7 +945,8 @@
 
         testUseCase.updateSuggestedStreamSpec(StreamSpec.builder(
                 new Size(640, 480)).setImplementationOptions(
-                StreamUseCaseUtil.getStreamSpecImplementationOptions(config)).build());
+                StreamUseCaseUtil.getStreamSpecImplementationOptions(config)).build(),
+                null);
         mFakeUseCases.add(testUseCase);
         return testUseCase;
     }
@@ -962,13 +964,15 @@
         new Camera2Interop.Extender<>(configBuilder).setSessionStateCallback(mSessionStateCallback);
         UseCaseConfig<?> config = configBuilder.getUseCaseConfig();
 
-        imageCapture.bindToCamera(mCamera2CameraImpl, null, imageCapture.getDefaultConfig(true,
+        imageCapture.bindToCamera(mCamera2CameraImpl, null, null,
+                imageCapture.getDefaultConfig(true,
                 useCaseConfigFactory));
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync(
                 () -> imageCapture.updateSuggestedStreamSpec(StreamSpec.builder(
                         new Size(640, 480)).setImplementationOptions(
-                        StreamUseCaseUtil.getStreamSpecImplementationOptions(config)).build()));
+                        StreamUseCaseUtil.getStreamSpecImplementationOptions(config)).build(),
+                        null));
 
         mFakeUseCases.add(imageCapture);
         return imageCapture;
@@ -980,7 +984,10 @@
                 new Camera2UseCaseConfigFactory(ApplicationProvider.getApplicationContext());
 
         StreamSharing streamSharing =
-                new StreamSharing(mCamera2CameraImpl, children, useCaseConfigFactory);
+                new StreamSharing(mCamera2CameraImpl, null,
+                        LayoutSettings.DEFAULT,
+                        LayoutSettings.DEFAULT,
+                        children, useCaseConfigFactory);
 
         FakeUseCaseConfig.Builder configBuilder =
                 new FakeUseCaseConfig.Builder().setSessionOptionUnpacker(
@@ -988,13 +995,15 @@
         new Camera2Interop.Extender<>(configBuilder).setSessionStateCallback(mSessionStateCallback);
         UseCaseConfig<?> config = configBuilder.getUseCaseConfig();
 
-        streamSharing.bindToCamera(mCamera2CameraImpl, null, streamSharing.getDefaultConfig(true,
+        streamSharing.bindToCamera(mCamera2CameraImpl, null, null,
+                streamSharing.getDefaultConfig(true,
                 useCaseConfigFactory));
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync(
                 () -> streamSharing.updateSuggestedStreamSpec(StreamSpec.builder(
                         new Size(640, 480)).setImplementationOptions(
-                        StreamUseCaseUtil.getStreamSpecImplementationOptions(config)).build()));
+                        StreamUseCaseUtil.getStreamSpecImplementationOptions(config)).build(),
+                        null));
 
         mFakeUseCases.add(streamSharing);
         return streamSharing;
@@ -1369,7 +1378,7 @@
         useCase.updateSuggestedStreamSpec(StreamSpec.builder(
                 new Size(640, 480)).setImplementationOptions(
                 StreamUseCaseUtil.getStreamSpecImplementationOptions(
-                        useCase.getCurrentConfig())).build());
+                        useCase.getCurrentConfig())).build(), null);
     }
 
     private static boolean getDefaultZslDisabled(int templateType) {
@@ -1416,10 +1425,11 @@
             mRepeatingCaptureCallback = repeatingCaptureCallback;
             mHandlerThread.start();
             mHandler = new Handler(mHandlerThread.getLooper());
-            bindToCamera(camera, null, null);
+            bindToCamera(camera, null, null, null);
             updateSuggestedStreamSpec(StreamSpec.builder(
                     new Size(640, 480)).setImplementationOptions(
-                    StreamUseCaseUtil.getStreamSpecImplementationOptions(config)).build());
+                    StreamUseCaseUtil.getStreamSpecImplementationOptions(config)).build(),
+                    null);
         }
 
         public void close() {
@@ -1440,25 +1450,26 @@
         @Override
         @NonNull
         protected StreamSpec onSuggestedStreamSpecUpdated(
-                @NonNull StreamSpec suggestedStreamSpec) {
+                @NonNull StreamSpec primaryStreamSpec,
+                @Nullable StreamSpec secondaryStreamSpec) {
             if (mDeferrableSurface != null) {
                 mDeferrableSurface.close();
             }
-            mDeferrableSurface = createDeferrableSurface(suggestedStreamSpec, mImageFormat);
+            mDeferrableSurface = createDeferrableSurface(primaryStreamSpec, mImageFormat);
             mSessionConfigBuilder = SessionConfig.Builder.createFrom(mConfig,
-                    suggestedStreamSpec.getResolution());
+                    primaryStreamSpec.getResolution());
             mSessionConfigBuilder.setTemplateType(mTemplate);
             mSessionConfigBuilder.addRepeatingCameraCaptureCallback(mRepeatingCaptureCallback);
             updateSessionBuilderBySurfaceOption();
-            updateSessionConfig(mSessionConfigBuilder.build());
-            return suggestedStreamSpec;
+            updateSessionConfig(List.of(mSessionConfigBuilder.build()));
+            return primaryStreamSpec;
         }
 
         public void setSurfaceOption(@NonNull SurfaceOption surfaceOption) {
             if (mSurfaceOption != surfaceOption) {
                 mSurfaceOption = surfaceOption;
                 updateSessionBuilderBySurfaceOption();
-                updateSessionConfig(mSessionConfigBuilder.build());
+                updateSessionConfig(List.of(mSessionConfigBuilder.build()));
             }
         }
 
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/ExposureDeviceTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/ExposureDeviceTest.java
index 99d61a0..0938fa4 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/ExposureDeviceTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/ExposureDeviceTest.java
@@ -41,6 +41,7 @@
 import android.view.Surface;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.camera.camera2.Camera2Config;
 import androidx.camera.camera2.internal.compat.CameraManagerCompat;
 import androidx.camera.camera2.internal.util.SemaphoreReleasingCamera2Callbacks;
@@ -446,10 +447,11 @@
         @Override
         @NonNull
         protected StreamSpec onSuggestedStreamSpecUpdated(
-                @NonNull StreamSpec suggestedStreamSpec) {
-            createPipeline(suggestedStreamSpec);
+                @NonNull StreamSpec primaryStreamSpec,
+                @Nullable StreamSpec secondaryStreamSpec) {
+            createPipeline(primaryStreamSpec);
             notifyActive();
-            return suggestedStreamSpec;
+            return primaryStreamSpec;
         }
 
         private void createPipeline(StreamSpec streamSpec) {
@@ -486,11 +488,11 @@
                         }
                     }));
 
-            builder.addErrorListener((sessionConfig, error) -> {
+            builder.setErrorListener((sessionConfig, error) -> {
                 // Create new pipeline and it will close the old one.
                 createPipeline(streamSpec);
             });
-            updateSessionConfig(builder.build());
+            updateSessionConfig(List.of(builder.build()));
         }
     }
 }
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
index 6b5591d..8467c8ba 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
@@ -83,6 +83,7 @@
 import androidx.camera.core.streamsharing.StreamSharing;
 import androidx.concurrent.futures.CallbackToFutureAdapter;
 import androidx.core.util.Preconditions;
+import androidx.tracing.Trace;
 
 import com.google.auto.value.AutoValue;
 import com.google.common.util.concurrent.ListenableFuture;
@@ -176,6 +177,8 @@
     @SuppressWarnings("WeakerAccess") /* synthetic accessor */
     final Map<CaptureSessionInterface, ListenableFuture<Void>> mReleasedCaptureSessions =
             new LinkedHashMap<>();
+    // Used to keep track of number of state errors while tracing is enabled
+    private int mTraceStateErrorCount = 0;
 
     @NonNull final CameraAvailability mCameraAvailability;
     @NonNull final CameraConfigureAvailable mCameraConfigureAvailable;
@@ -186,6 +189,7 @@
     private final boolean mConfigAndCloseQuirk;
     private boolean mIsConfigAndCloseRequired = false;
     private boolean mIsConfiguringForClose = false;
+    private boolean mIsPrimary = true;
 
     // The metering repeating use case for ImageCapture only case.
     private MeteringRepeatingSession mMeteringRepeatingSession;
@@ -773,7 +777,8 @@
     public void onUseCaseActive(@NonNull UseCase useCase) {
         Preconditions.checkNotNull(useCase);
         String useCaseId = getUseCaseId(useCase);
-        SessionConfig sessionConfig = useCase.getSessionConfig();
+        SessionConfig sessionConfig = mIsPrimary ? useCase.getSessionConfig()
+                : useCase.getSecondarySessionConfig();
         UseCaseConfig<?> useCaseConfig = useCase.getCurrentConfig();
         StreamSpec streamSpec = useCase.getAttachedStreamSpec();
         List<UseCaseConfigFactory.CaptureType> captureTypes = getCaptureTypes(useCase);
@@ -806,7 +811,8 @@
     public void onUseCaseUpdated(@NonNull UseCase useCase) {
         Preconditions.checkNotNull(useCase);
         String useCaseId = getUseCaseId(useCase);
-        SessionConfig sessionConfig = useCase.getSessionConfig();
+        SessionConfig sessionConfig = mIsPrimary ? useCase.getSessionConfig()
+                : useCase.getSecondarySessionConfig();
         UseCaseConfig<?> useCaseConfig = useCase.getCurrentConfig();
         StreamSpec streamSpec = useCase.getAttachedStreamSpec();
         List<UseCaseConfigFactory.CaptureType> captureTypes = getCaptureTypes(useCase);
@@ -821,7 +827,8 @@
     @Override
     public void onUseCaseReset(@NonNull UseCase useCase) {
         Preconditions.checkNotNull(useCase);
-        SessionConfig sessionConfig = useCase.getSessionConfig();
+        SessionConfig sessionConfig = mIsPrimary ? useCase.getSessionConfig()
+                : useCase.getSecondarySessionConfig();
         UseCaseConfig<?> useCaseConfig = useCase.getCurrentConfig();
         StreamSpec streamSpec = useCase.getAttachedStreamSpec();
         List<UseCaseConfigFactory.CaptureType> captureTypes = getCaptureTypes(useCase);
@@ -1005,7 +1012,7 @@
         List<UseCaseInfo> useCaseInfos = new ArrayList<>();
 
         for (UseCase useCase : useCases) {
-            useCaseInfos.add(UseCaseInfo.from(useCase));
+            useCaseInfos.add(UseCaseInfo.from(useCase, mIsPrimary));
         }
 
         return useCaseInfos;
@@ -1250,7 +1257,7 @@
 
         try {
             mSupportedSurfaceCombination.getSuggestedStreamSpecifications(cameraMode,
-                    attachedSurfaces, useCaseConfigToSizeMap, false);
+                    attachedSurfaces, useCaseConfigToSizeMap, false, false);
         } catch (IllegalArgumentException e) {
             debugLog("Surface combination with metering repeating  not supported!", e);
             return false;
@@ -1361,6 +1368,11 @@
     }
 
     @Override
+    public void setPrimary(boolean isPrimary) {
+        mIsPrimary = isPrimary;
+    }
+
+    @Override
     public void setActiveResumingMode(boolean enabled) {
         mExecutor.execute(() -> {
             // Enables/Disables active resuming mode which will reopen the camera regardless of the
@@ -1633,9 +1645,8 @@
     @SuppressWarnings("WeakerAccess") /* synthetic accessor */
     void postSurfaceClosedError(@NonNull SessionConfig sessionConfig) {
         Executor executor = CameraXExecutors.mainThreadExecutor();
-        List<SessionConfig.ErrorListener> errorListeners = sessionConfig.getErrorListeners();
-        if (!errorListeners.isEmpty()) {
-            SessionConfig.ErrorListener errorListener = errorListeners.get(0);
+        SessionConfig.ErrorListener errorListener = sessionConfig.getErrorListener();
+        if (errorListener != null) {
             debugLog("Posting surface closed", new Throwable());
             executor.execute(() -> errorListener.onError(sessionConfig,
                     SessionConfig.SessionError.SESSION_ERROR_SURFACE_NEEDS_RESET));
@@ -1823,6 +1834,19 @@
 
     enum InternalState {
         /**
+         * A stable state where the camera has been permanently closed.
+         *
+         * <p>During this state all resources should be released and all operations on the camera
+         * will do nothing.
+         */
+        RELEASED,
+        /**
+         * A transitional state where the camera will be closing permanently.
+         *
+         * <p>At the end of this state, the camera should move into the RELEASED state.
+         */
+        RELEASING,
+        /**
          * Stable state once the camera has been constructed.
          *
          * <p>At this state the {@link CameraDevice} should be invalid, but threads should be still
@@ -1843,6 +1867,33 @@
          */
         PENDING_OPEN,
         /**
+         * A transitional state where the camera device is currently closing.
+         *
+         * <p>At the end of this state, the camera should move into the INITIALIZED state.
+         */
+        CLOSING,
+        /**
+         * A transitional state where the camera is actively transitioning from the OPENED state
+         * towards being fully closed, with the intention of being immediately reopened.
+         *
+         * <p>This state can serve the {@link LegacyCameraOutputConfigNullPointerQuirk}
+         * workaround: Forcing the camera to close and reopen to address device-specific quirks.
+         *
+         * <p>At the end of this state, the camera should move into the OPENING state, assuming
+         * successful initialization.
+         */
+        REOPENING_QUIRK,
+        /**
+         * A transitional state where the camera was previously closing, but not fully closed before
+         * a call to open was made.
+         *
+         * <p>At the end of this state, the camera should move into one of two states. The OPENING
+         * state if the device becomes fully closed, since it must restart the process of opening a
+         * camera. The OPENED state if the device becomes opened, which can occur if a call to close
+         * had been done during the OPENING state.
+         */
+        REOPENING,
+        /**
          * A transitional state where the camera device is currently opening.
          *
          * <p>At the end of this state, the camera should move into either the OPENED or CLOSING
@@ -1863,46 +1914,6 @@
          * capture session configuration status.
          */
         CONFIGURED,
-        /**
-         * A transitional state where the camera device is currently closing.
-         *
-         * <p>At the end of this state, the camera should move into the INITIALIZED state.
-         */
-        CLOSING,
-        /**
-         * A transitional state where the camera was previously closing, but not fully closed before
-         * a call to open was made.
-         *
-         * <p>At the end of this state, the camera should move into one of two states. The OPENING
-         * state if the device becomes fully closed, since it must restart the process of opening a
-         * camera. The OPENED state if the device becomes opened, which can occur if a call to close
-         * had been done during the OPENING state.
-         */
-        REOPENING,
-        /**
-         * A transitional state where the camera is actively transitioning from the OPENED state
-         * towards being fully closed, with the intention of being immediately reopened.
-         *
-         * <p>This state can serve the {@link LegacyCameraOutputConfigNullPointerQuirk}
-         * workaround: Forcing the camera to close and reopen to address device-specific quirks.
-         *
-         * <p>At the end of this state, the camera should move into the OPENING state, assuming
-         * successful initialization.
-         */
-        REOPENING_QUIRK,
-        /**
-         * A transitional state where the camera will be closing permanently.
-         *
-         * <p>At the end of this state, the camera should move into the RELEASED state.
-         */
-        RELEASING,
-        /**
-         * A stable state where the camera has been permanently closed.
-         *
-         * <p>During this state all resources should be released and all operations on the camera
-         * will do nothing.
-         */
-        RELEASED
     }
 
     @SuppressWarnings("WeakerAccess") /* synthetic accessor */
@@ -1930,6 +1941,7 @@
     void setState(@NonNull InternalState state, @Nullable CameraState.StateError stateError,
             boolean notifyImmediately) {
         debugLog("Transitioning camera internal state: " + mState + " --> " + state);
+        traceInternalState(state, stateError);
         mState = state;
         // Convert the internal state to the publicly visible state
         State publicState;
@@ -1968,6 +1980,25 @@
         mCameraStateMachine.updateState(publicState, stateError);
     }
 
+    @ExecutedBy("mExecutor")
+    void traceInternalState(@NonNull InternalState state,
+            @Nullable CameraState.StateError stateError) {
+        if (Trace.isEnabled()) {
+            String counterName = "CX:C2State[" + this + "]";
+            Trace.setCounter(counterName, state.ordinal());
+
+            if (stateError != null) {
+                mTraceStateErrorCount++;
+            }
+
+            if (mTraceStateErrorCount > 0) {
+                String errorCounterName = "CX:C2StateErrorCode[" + this + "]";
+                int errorCode = stateError != null ? stateError.getCode() : 0;
+                Trace.setCounter(errorCounterName, errorCode);
+            }
+        }
+    }
+
     @SuppressWarnings("WeakerAccess") /* synthetic accessor */
     static String getErrorMessage(int errorCode) {
         switch (errorCode) {
@@ -2010,9 +2041,12 @@
         }
 
         @NonNull
-        static UseCaseInfo from(@NonNull UseCase useCase) {
-            return create(Camera2CameraImpl.getUseCaseId(useCase), useCase.getClass(),
-                    useCase.getSessionConfig(), useCase.getCurrentConfig(),
+        static UseCaseInfo from(@NonNull UseCase useCase, boolean isPrimary) {
+            return create(Camera2CameraImpl.getUseCaseId(useCase),
+                    useCase.getClass(),
+                    isPrimary ? useCase.getSessionConfig()
+                            : useCase.getSecondarySessionConfig(),
+                    useCase.getCurrentConfig(),
                     useCase.getAttachedSurfaceResolution(),
                     useCase.getAttachedStreamSpec(), Camera2CameraImpl.getCaptureTypes(useCase));
         }
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2DeviceSurfaceManager.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2DeviceSurfaceManager.java
index 8eb5953..9aee9a7 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2DeviceSurfaceManager.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2DeviceSurfaceManager.java
@@ -155,6 +155,8 @@
      * @param newUseCaseConfigsSupportedSizeMap map of configurations of the use cases to the
      *                                          supported sizes list that will be given a
      *                                          suggested stream specification
+     * @param isPreviewStabilizationOn          whether the preview stabilization is enabled.
+     * @param hasVideoCapture                   whether the use cases has video capture.
      * @return map of suggested stream specifications for given use cases
      * @throws IllegalStateException    if not initialized
      * @throws IllegalArgumentException if {@code newUseCaseConfigs} is an empty list, if
@@ -170,7 +172,8 @@
             @NonNull String cameraId,
             @NonNull List<AttachedSurfaceInfo> existingSurfaces,
             @NonNull Map<UseCaseConfig<?>, List<Size>> newUseCaseConfigsSupportedSizeMap,
-            boolean isPreviewStabilizationOn) {
+            boolean isPreviewStabilizationOn,
+            boolean hasVideoCapture) {
         Preconditions.checkArgument(!newUseCaseConfigsSupportedSizeMap.isEmpty(),
                 "No new use cases to be bound.");
 
@@ -186,6 +189,7 @@
                 cameraMode,
                 existingSurfaces,
                 newUseCaseConfigsSupportedSizeMap,
-                isPreviewStabilizationOn);
+                isPreviewStabilizationOn,
+                hasVideoCapture);
     }
 }
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/MeteringRepeatingSession.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/MeteringRepeatingSession.java
index 57381e0..0d488b3 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/MeteringRepeatingSession.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/MeteringRepeatingSession.java
@@ -79,6 +79,8 @@
 
     @Nullable
     private final SurfaceResetCallback mSurfaceResetCallback;
+    @Nullable
+    private SessionConfig.CloseableErrorListener mCloseableErrorListener = null;
 
     /** Creates a new instance of a {@link MeteringRepeatingSession}. */
     MeteringRepeatingSession(@NonNull CameraCharacteristicsCompat cameraCharacteristicsCompat,
@@ -125,12 +127,20 @@
 
         builder.addSurface(mDeferrableSurface);
 
-        builder.addErrorListener((sessionConfig, error) -> {
-            mSessionConfig = createSessionConfig();
-            if (mSurfaceResetCallback != null) {
-                mSurfaceResetCallback.onSurfaceReset();
-            }
-        });
+        // Closes old error listener
+        if (mCloseableErrorListener != null) {
+            mCloseableErrorListener.close();
+        }
+
+        mCloseableErrorListener = new SessionConfig.CloseableErrorListener(
+                (sessionConfig, error) -> {
+                    mSessionConfig = createSessionConfig();
+                    if (mSurfaceResetCallback != null) {
+                        mSurfaceResetCallback.onSurfaceReset();
+                    }
+                });
+
+        builder.setErrorListener(mCloseableErrorListener);
 
         return builder.build();
     }
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SupportedSurfaceCombination.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SupportedSurfaceCombination.java
index f12154d..929edd0 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SupportedSurfaceCombination.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SupportedSurfaceCombination.java
@@ -558,6 +558,7 @@
      * @param newUseCaseConfigsSupportedSizeMap newly added UseCaseConfig to supported output
      *                                          sizes map.
      * @param isPreviewStabilizationOn          whether the preview stabilization is enabled.
+     * @param hasVideoCapture                   whether the use cases has video capture.
      * @return the suggested stream specifications, which is a pair of mappings. The first
      * mapping is from UseCaseConfig to the suggested stream specification representing new
      * UseCases. The second mapping is from attachedSurfaceInfo to the suggested stream
@@ -574,7 +575,8 @@
             @CameraMode.Mode int cameraMode,
             @NonNull List<AttachedSurfaceInfo> attachedSurfaces,
             @NonNull Map<UseCaseConfig<?>, List<Size>> newUseCaseConfigsSupportedSizeMap,
-            boolean isPreviewStabilizationOn) {
+            boolean isPreviewStabilizationOn,
+            boolean hasVideoCapture) {
         // Refresh Preview Size based on current display configurations.
         refreshPreviewSize();
 
@@ -787,7 +789,8 @@
                                 resolvedDynamicRanges.get(useCaseConfig)))
                         .setImplementationOptions(
                                 StreamUseCaseUtil.getStreamSpecImplementationOptions(useCaseConfig)
-                        );
+                        )
+                        .setZslDisabled(hasVideoCapture);
                 if (targetFramerateForDevice != null) {
                     streamSpecBuilder.setExpectedFrameRateRange(targetFramerateForDevice);
                 }
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/CameraCharacteristicsCompat.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/CameraCharacteristicsCompat.java
index e4fc92ea..ffbb516 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/CameraCharacteristicsCompat.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/CameraCharacteristicsCompat.java
@@ -131,7 +131,7 @@
             try {
                 map = get(
                         CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
-            } catch (AssertionError e) {
+            } catch (NullPointerException | AssertionError e) {
                 // Some devices may throw AssertionError when querying stream configuration map
                 // from CameraCharacteristics during bindToLifecycle. Catch the AssertionError and
                 // throw IllegalArgumentException so app level can decide how to handle.
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/ImageCaptureFailedForVideoSnapshotQuirk.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/ImageCaptureFailedForVideoSnapshotQuirk.java
index 1c7049b..30852e5 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/ImageCaptureFailedForVideoSnapshotQuirk.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/ImageCaptureFailedForVideoSnapshotQuirk.java
@@ -30,7 +30,7 @@
 
 /**
  * <p>QuirkSummary
- *     Bug Id: b/344704367
+ *     Bug Id: b/344704367, b/349542870
  *     Description: When taking pictures with {@link CameraDevice#TEMPLATE_VIDEO_SNAPSHOT}, there
  *                  is no response from camera HAL. On itel l6006, itel w6004, moto g(20), moto
  *                  e13, moto e20, rmx3231, rmx3511, sm-a032f, sm-a035m, it happens when there
@@ -42,8 +42,11 @@
  *                  {@link CaptureRequest#CONTROL_CAPTURE_INTENT_STILL_CAPTURE} instead of
  *                  {@link CaptureRequest#CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT} on UniSoc
  *                  chipset devices.
+ *                  On the Huawei P Smart (b/349542870), taking pictures consistently fails when
+ *                  using CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT, regardless of the surface
+ *                  combinations or capture intent specified in repeated request.
  *     Device(s): itel l6006, itel w6004, moto g(20), moto e13, moto e20, rmx3231, rmx3511,
- *                sm-a032f, sm-a035m, tecno mobile bf6.
+ *                sm-a032f, sm-a035m, tecno mobile bf6, Huawei P Smart.
  */
 public class ImageCaptureFailedForVideoSnapshotQuirk implements Quirk {
 
@@ -61,7 +64,7 @@
     ));
 
     static boolean load() {
-        return isUniSocChipsetDevice();
+        return isUniSocChipsetDevice() || isHuaweiPSmart();
     }
 
     private static boolean isUniSocChipsetDevice() {
@@ -74,4 +77,8 @@
                 || ("itel".equalsIgnoreCase(Build.BRAND) && Build.HARDWARE.toLowerCase(
                 Locale.US).startsWith("sp"));
     }
+
+    private static boolean isHuaweiPSmart() {
+        return "HUAWEI".equalsIgnoreCase(Build.BRAND) && "FIG-LX1".equalsIgnoreCase(Build.MODEL);
+    }
 }
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/StreamUseCaseTest.java b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/StreamUseCaseTest.java
index a661164..301336d 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/StreamUseCaseTest.java
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/StreamUseCaseTest.java
@@ -42,6 +42,7 @@
 import androidx.camera.camera2.internal.compat.CameraCharacteristicsCompat;
 import androidx.camera.core.DynamicRange;
 import androidx.camera.core.ImageCapture;
+import androidx.camera.core.LayoutSettings;
 import androidx.camera.core.UseCase;
 import androidx.camera.core.impl.AttachedSurfaceInfo;
 import androidx.camera.core.impl.CameraMode;
@@ -481,7 +482,8 @@
                 UseCaseConfigFactory.CaptureType.IMAGE_CAPTURE));
         children.add(new FakeUseCase(new FakeUseCaseConfig.Builder().getUseCaseConfig(),
                 UseCaseConfigFactory.CaptureType.VIDEO_CAPTURE));
-        StreamSharing streamSharing = new StreamSharing(new FakeCamera(), children,
+        StreamSharing streamSharing = new StreamSharing(new FakeCamera(), null,
+                LayoutSettings.DEFAULT, LayoutSettings.DEFAULT, children,
                 useCaseConfigFactory);
         Map<Integer, AttachedSurfaceInfo> surfaceConfigAttachedSurfaceInfoMap =
                 new HashMap<>();
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.kt b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.kt
index 92b8822..b4059b9 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.kt
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.kt
@@ -1572,6 +1572,34 @@
         )
     }
 
+    @Test
+    fun hasVideoCapture_suggestedStreamSpecZslDisabled() {
+        val useCase1 = createUseCase(CaptureType.VIDEO_CAPTURE) // VIDEO
+        val useCase2 = createUseCase(CaptureType.PREVIEW) // PREVIEW
+        val useCaseExpectedResultMap =
+            mutableMapOf<UseCase, Size>().apply {
+                put(useCase1, RECORD_SIZE)
+                put(useCase2, PREVIEW_SIZE)
+            }
+        getSuggestedSpecsAndVerify(
+            useCaseExpectedResultMap,
+            hardwareLevel = INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED,
+            hasVideoCapture = true
+        )
+    }
+
+    @Test
+    fun hasNoVideoCapture_suggestedStreamSpecZslNotDisabled() {
+        val privUseCase = createUseCase(CaptureType.PREVIEW) // PREVIEW
+        val jpegUseCase = createUseCase(CaptureType.IMAGE_CAPTURE) // JPEG
+        val useCaseExpectedResultMap =
+            mutableMapOf<UseCase, Size>().apply {
+                put(privUseCase, if (Build.VERSION.SDK_INT == 21) RESOLUTION_VGA else PREVIEW_SIZE)
+                put(jpegUseCase, MAXIMUM_SIZE)
+            }
+        getSuggestedSpecsAndVerify(useCaseExpectedResultMap, hasVideoCapture = false)
+    }
+
     private fun getSuggestedSpecsAndVerify(
         useCasesExpectedSizeMap: Map<UseCase, Size>,
         attachedSurfaceInfoList: List<AttachedSurfaceInfo> = emptyList(),
@@ -1584,6 +1612,8 @@
         default10BitProfile: Long? = null,
         useCasesExpectedDynamicRangeMap: Map<UseCase, DynamicRange> = emptyMap(),
         supportedOutputFormats: IntArray? = null,
+        isPreviewStabilizationOn: Boolean = false,
+        hasVideoCapture: Boolean = false
     ): Pair<Map<UseCaseConfig<*>, StreamSpec>, Map<AttachedSurfaceInfo, StreamSpec>> {
         setupCameraAndInitCameraX(
             hardwareLevel = hardwareLevel,
@@ -1608,7 +1638,8 @@
                 cameraMode,
                 attachedSurfaceInfoList,
                 useCaseConfigToOutputSizesMap,
-                false
+                isPreviewStabilizationOn,
+                hasVideoCapture
             )
         val suggestedStreamSpecsForNewUseCases = resultPair.first
         val suggestedStreamSpecsForOldSurfaces = resultPair.second
@@ -1629,6 +1660,8 @@
                         .expectedFrameRateRange == compareExpectedFps
                 )
             }
+            val zslDisabled = suggestedStreamSpecsForNewUseCases[useCaseConfigMap[it]]!!.zslDisabled
+            assertThat(zslDisabled == hasVideoCapture)
         }
 
         useCasesExpectedDynamicRangeMap.keys.forEach {
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/CameraCharacteristicsCompatTest.java b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/CameraCharacteristicsCompatTest.java
index aa9de1a..33c850f 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/CameraCharacteristicsCompatTest.java
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/CameraCharacteristicsCompatTest.java
@@ -139,12 +139,25 @@
         verify(cameraCharacteristics, times(2)).get(CameraCharacteristics.SENSOR_ORIENTATION);
     }
 
-
     @Test(expected = IllegalArgumentException.class)
-    public void getStreamConfigurationMapCompat() {
+    public void getStreamConfigurationMapCompat_assertionError() {
         CameraCharacteristics cameraCharacteristics = spy(mCharacteristics);
         when(cameraCharacteristics.get(SCALER_STREAM_CONFIGURATION_MAP)).thenThrow(
-                new AssertionError("cannot get stream configuration map"));
+                new AssertionError(
+                        "At least one stream configuration for IMPLEMENTATION_DEFINED must exist"));
+        CameraCharacteristicsCompat characteristicsCompat =
+                CameraCharacteristicsCompat.toCameraCharacteristicsCompat(cameraCharacteristics,
+                        CAMERA_ID_0);
+
+        characteristicsCompat.getStreamConfigurationMapCompat();
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void getStreamConfigurationMapCompat_nullPointerException() {
+        CameraCharacteristics cameraCharacteristics = spy(mCharacteristics);
+        when(cameraCharacteristics.get(SCALER_STREAM_CONFIGURATION_MAP)).thenThrow(
+                new NullPointerException(
+                        "At least one of color/depth/heic configurations must not be null"));
         CameraCharacteristicsCompat characteristicsCompat =
                 CameraCharacteristicsCompat.toCameraCharacteristicsCompat(cameraCharacteristics,
                         CAMERA_ID_0);
diff --git a/camera/camera-core/api/1.4.0-beta03.txt b/camera/camera-core/api/1.4.0-beta03.txt
new file mode 100644
index 0000000..be07f31
--- /dev/null
+++ b/camera/camera-core/api/1.4.0-beta03.txt
@@ -0,0 +1,742 @@
+// Signature format: 4.0
+package androidx.camera.core {
+
+  public class AspectRatio {
+    field public static final int RATIO_16_9 = 1; // 0x1
+    field public static final int RATIO_4_3 = 0; // 0x0
+    field public static final int RATIO_DEFAULT = -1; // 0xffffffff
+  }
+
+  public interface Camera {
+    method public androidx.camera.core.CameraControl getCameraControl();
+    method public androidx.camera.core.CameraInfo getCameraInfo();
+  }
+
+  public interface CameraControl {
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> cancelFocusAndMetering();
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enableTorch(boolean);
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Integer!> setExposureCompensationIndex(int);
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setLinearZoom(@FloatRange(from=0.0f, to=1.0f) float);
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setZoomRatio(float);
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.camera.core.FocusMeteringResult!> startFocusAndMetering(androidx.camera.core.FocusMeteringAction);
+  }
+
+  public static final class CameraControl.OperationCanceledException extends java.lang.Exception {
+  }
+
+  public abstract class CameraEffect {
+    ctor protected CameraEffect(int, java.util.concurrent.Executor, androidx.camera.core.ImageProcessor, androidx.core.util.Consumer<java.lang.Throwable!>);
+    ctor protected CameraEffect(int, java.util.concurrent.Executor, androidx.camera.core.SurfaceProcessor, androidx.core.util.Consumer<java.lang.Throwable!>);
+    method public androidx.core.util.Consumer<java.lang.Throwable!> getErrorListener();
+    method public java.util.concurrent.Executor getExecutor();
+    method public androidx.camera.core.SurfaceProcessor? getSurfaceProcessor();
+    method public int getTargets();
+    field public static final int IMAGE_CAPTURE = 4; // 0x4
+    field public static final int PREVIEW = 1; // 0x1
+    field public static final int VIDEO_CAPTURE = 2; // 0x2
+  }
+
+  public interface CameraFilter {
+    method public java.util.List<androidx.camera.core.CameraInfo!> filter(java.util.List<androidx.camera.core.CameraInfo!>);
+  }
+
+  public interface CameraInfo {
+    method public androidx.camera.core.CameraSelector getCameraSelector();
+    method public androidx.lifecycle.LiveData<androidx.camera.core.CameraState!> getCameraState();
+    method public androidx.camera.core.ExposureState getExposureState();
+    method @FloatRange(from=0, fromInclusive=false) public default float getIntrinsicZoomRatio();
+    method public default int getLensFacing();
+    method public default java.util.Set<androidx.camera.core.CameraInfo!> getPhysicalCameraInfos();
+    method public int getSensorRotationDegrees();
+    method public int getSensorRotationDegrees(int);
+    method public default java.util.Set<android.util.Range<java.lang.Integer!>!> getSupportedFrameRateRanges();
+    method public androidx.lifecycle.LiveData<java.lang.Integer!> getTorchState();
+    method public androidx.lifecycle.LiveData<androidx.camera.core.ZoomState!> getZoomState();
+    method public boolean hasFlashUnit();
+    method public default boolean isFocusMeteringSupported(androidx.camera.core.FocusMeteringAction);
+    method public default boolean isLogicalMultiCameraSupported();
+    method @SuppressCompatibility @androidx.camera.core.ExperimentalZeroShutterLag public default boolean isZslSupported();
+    method public static boolean mustPlayShutterSound();
+    method public default java.util.Set<androidx.camera.core.DynamicRange!> querySupportedDynamicRanges(java.util.Set<androidx.camera.core.DynamicRange!>);
+  }
+
+  public final class CameraInfoUnavailableException extends java.lang.Exception {
+  }
+
+  public interface CameraProvider {
+    method public java.util.List<androidx.camera.core.CameraInfo!> getAvailableCameraInfos();
+    method @SuppressCompatibility @androidx.camera.core.ExperimentalCameraInfo public default androidx.camera.core.CameraInfo getCameraInfo(androidx.camera.core.CameraSelector);
+    method public boolean hasCamera(androidx.camera.core.CameraSelector) throws androidx.camera.core.CameraInfoUnavailableException;
+  }
+
+  public final class CameraSelector {
+    method public java.util.List<androidx.camera.core.CameraInfo!> filter(java.util.List<androidx.camera.core.CameraInfo!>);
+    method public String? getPhysicalCameraId();
+    field public static final androidx.camera.core.CameraSelector DEFAULT_BACK_CAMERA;
+    field public static final androidx.camera.core.CameraSelector DEFAULT_FRONT_CAMERA;
+    field public static final int LENS_FACING_BACK = 1; // 0x1
+    field @SuppressCompatibility @androidx.camera.core.ExperimentalLensFacing public static final int LENS_FACING_EXTERNAL = 2; // 0x2
+    field public static final int LENS_FACING_FRONT = 0; // 0x0
+    field public static final int LENS_FACING_UNKNOWN = -1; // 0xffffffff
+  }
+
+  public static final class CameraSelector.Builder {
+    ctor public CameraSelector.Builder();
+    method public androidx.camera.core.CameraSelector.Builder addCameraFilter(androidx.camera.core.CameraFilter);
+    method public androidx.camera.core.CameraSelector build();
+    method public androidx.camera.core.CameraSelector.Builder requireLensFacing(int);
+    method public androidx.camera.core.CameraSelector.Builder setPhysicalCameraId(String);
+  }
+
+  @com.google.auto.value.AutoValue public abstract class CameraState {
+    ctor public CameraState();
+    method public static androidx.camera.core.CameraState create(androidx.camera.core.CameraState.Type);
+    method public static androidx.camera.core.CameraState create(androidx.camera.core.CameraState.Type, androidx.camera.core.CameraState.StateError?);
+    method public abstract androidx.camera.core.CameraState.StateError? getError();
+    method public abstract androidx.camera.core.CameraState.Type getType();
+    field public static final int ERROR_CAMERA_DISABLED = 5; // 0x5
+    field public static final int ERROR_CAMERA_FATAL_ERROR = 6; // 0x6
+    field public static final int ERROR_CAMERA_IN_USE = 2; // 0x2
+    field public static final int ERROR_DO_NOT_DISTURB_MODE_ENABLED = 7; // 0x7
+    field public static final int ERROR_MAX_CAMERAS_IN_USE = 1; // 0x1
+    field public static final int ERROR_OTHER_RECOVERABLE_ERROR = 3; // 0x3
+    field public static final int ERROR_STREAM_CONFIG = 4; // 0x4
+  }
+
+  public enum CameraState.ErrorType {
+    enum_constant public static final androidx.camera.core.CameraState.ErrorType CRITICAL;
+    enum_constant public static final androidx.camera.core.CameraState.ErrorType RECOVERABLE;
+  }
+
+  @com.google.auto.value.AutoValue public abstract static class CameraState.StateError {
+    ctor public CameraState.StateError();
+    method public static androidx.camera.core.CameraState.StateError create(int);
+    method public static androidx.camera.core.CameraState.StateError create(int, Throwable?);
+    method public abstract Throwable? getCause();
+    method public abstract int getCode();
+    method public androidx.camera.core.CameraState.ErrorType getType();
+  }
+
+  public enum CameraState.Type {
+    enum_constant public static final androidx.camera.core.CameraState.Type CLOSED;
+    enum_constant public static final androidx.camera.core.CameraState.Type CLOSING;
+    enum_constant public static final androidx.camera.core.CameraState.Type OPEN;
+    enum_constant public static final androidx.camera.core.CameraState.Type OPENING;
+    enum_constant public static final androidx.camera.core.CameraState.Type PENDING_OPEN;
+  }
+
+  public class CameraUnavailableException extends java.lang.Exception {
+    ctor public CameraUnavailableException(int);
+    ctor public CameraUnavailableException(int, String?);
+    ctor public CameraUnavailableException(int, String?, Throwable?);
+    ctor public CameraUnavailableException(int, Throwable?);
+    method public int getReason();
+    field public static final int CAMERA_DISABLED = 1; // 0x1
+    field public static final int CAMERA_DISCONNECTED = 2; // 0x2
+    field public static final int CAMERA_ERROR = 3; // 0x3
+    field public static final int CAMERA_IN_USE = 4; // 0x4
+    field public static final int CAMERA_MAX_IN_USE = 5; // 0x5
+    field public static final int CAMERA_UNAVAILABLE_DO_NOT_DISTURB = 6; // 0x6
+    field public static final int CAMERA_UNKNOWN_ERROR = 0; // 0x0
+  }
+
+  public final class CameraXConfig {
+    method public androidx.camera.core.CameraSelector? getAvailableCamerasLimiter(androidx.camera.core.CameraSelector?);
+    method public java.util.concurrent.Executor? getCameraExecutor(java.util.concurrent.Executor?);
+    method public long getCameraOpenRetryMaxTimeoutInMillisWhileResuming();
+    method @SuppressCompatibility @androidx.camera.core.ExperimentalRetryPolicy public androidx.camera.core.RetryPolicy getCameraProviderInitRetryPolicy();
+    method public int getMinimumLoggingLevel();
+    method public android.os.Handler? getSchedulerHandler(android.os.Handler?);
+  }
+
+  public static final class CameraXConfig.Builder {
+    method public androidx.camera.core.CameraXConfig build();
+    method public static androidx.camera.core.CameraXConfig.Builder fromConfig(androidx.camera.core.CameraXConfig);
+    method public androidx.camera.core.CameraXConfig.Builder setAvailableCamerasLimiter(androidx.camera.core.CameraSelector);
+    method public androidx.camera.core.CameraXConfig.Builder setCameraExecutor(java.util.concurrent.Executor);
+    method public androidx.camera.core.CameraXConfig.Builder setCameraOpenRetryMaxTimeoutInMillisWhileResuming(long);
+    method @SuppressCompatibility @androidx.camera.core.ExperimentalRetryPolicy public androidx.camera.core.CameraXConfig.Builder setCameraProviderInitRetryPolicy(androidx.camera.core.RetryPolicy);
+    method public androidx.camera.core.CameraXConfig.Builder setMinimumLoggingLevel(@IntRange(from=android.util.Log.DEBUG, to=android.util.Log.ERROR) int);
+    method public androidx.camera.core.CameraXConfig.Builder setSchedulerHandler(android.os.Handler);
+  }
+
+  public static interface CameraXConfig.Provider {
+    method public androidx.camera.core.CameraXConfig getCameraXConfig();
+  }
+
+  public class ConcurrentCamera {
+    ctor public ConcurrentCamera(java.util.List<androidx.camera.core.Camera!>);
+    method public java.util.List<androidx.camera.core.Camera!> getCameras();
+  }
+
+  public static final class ConcurrentCamera.SingleCameraConfig {
+    ctor public ConcurrentCamera.SingleCameraConfig(androidx.camera.core.CameraSelector, androidx.camera.core.UseCaseGroup, androidx.lifecycle.LifecycleOwner);
+    method public androidx.camera.core.CameraSelector getCameraSelector();
+    method public androidx.lifecycle.LifecycleOwner getLifecycleOwner();
+    method public androidx.camera.core.UseCaseGroup getUseCaseGroup();
+  }
+
+  public final class DisplayOrientedMeteringPointFactory extends androidx.camera.core.MeteringPointFactory {
+    ctor public DisplayOrientedMeteringPointFactory(android.view.Display, androidx.camera.core.CameraInfo, float, float);
+  }
+
+  public final class DynamicRange {
+    ctor public DynamicRange(int, int);
+    method public int getBitDepth();
+    method public int getEncoding();
+    field public static final int BIT_DEPTH_10_BIT = 10; // 0xa
+    field public static final int BIT_DEPTH_8_BIT = 8; // 0x8
+    field public static final int BIT_DEPTH_UNSPECIFIED = 0; // 0x0
+    field public static final androidx.camera.core.DynamicRange DOLBY_VISION_10_BIT;
+    field public static final androidx.camera.core.DynamicRange DOLBY_VISION_8_BIT;
+    field public static final int ENCODING_DOLBY_VISION = 6; // 0x6
+    field public static final int ENCODING_HDR10 = 4; // 0x4
+    field public static final int ENCODING_HDR10_PLUS = 5; // 0x5
+    field public static final int ENCODING_HDR_UNSPECIFIED = 2; // 0x2
+    field public static final int ENCODING_HLG = 3; // 0x3
+    field public static final int ENCODING_SDR = 1; // 0x1
+    field public static final int ENCODING_UNSPECIFIED = 0; // 0x0
+    field public static final androidx.camera.core.DynamicRange HDR10_10_BIT;
+    field public static final androidx.camera.core.DynamicRange HDR10_PLUS_10_BIT;
+    field public static final androidx.camera.core.DynamicRange HDR_UNSPECIFIED_10_BIT;
+    field public static final androidx.camera.core.DynamicRange HLG_10_BIT;
+    field public static final androidx.camera.core.DynamicRange SDR;
+    field public static final androidx.camera.core.DynamicRange UNSPECIFIED;
+  }
+
+  @SuppressCompatibility @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface ExperimentalCameraInfo {
+  }
+
+  @SuppressCompatibility @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface ExperimentalGetImage {
+  }
+
+  @SuppressCompatibility @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface ExperimentalImageCaptureOutputFormat {
+  }
+
+  @SuppressCompatibility @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface ExperimentalLensFacing {
+  }
+
+  @SuppressCompatibility @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface ExperimentalMirrorMode {
+  }
+
+  @SuppressCompatibility @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface ExperimentalRetryPolicy {
+  }
+
+  @SuppressCompatibility @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface ExperimentalUseCaseApi {
+  }
+
+  @SuppressCompatibility @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface ExperimentalZeroShutterLag {
+  }
+
+  public interface ExposureState {
+    method public int getExposureCompensationIndex();
+    method public android.util.Range<java.lang.Integer!> getExposureCompensationRange();
+    method public android.util.Rational getExposureCompensationStep();
+    method public boolean isExposureCompensationSupported();
+  }
+
+  public interface ExtendableBuilder<T> {
+    method public T build();
+  }
+
+  public final class FocusMeteringAction {
+    method public long getAutoCancelDurationInMillis();
+    method public java.util.List<androidx.camera.core.MeteringPoint!> getMeteringPointsAe();
+    method public java.util.List<androidx.camera.core.MeteringPoint!> getMeteringPointsAf();
+    method public java.util.List<androidx.camera.core.MeteringPoint!> getMeteringPointsAwb();
+    method public boolean isAutoCancelEnabled();
+    field public static final int FLAG_AE = 2; // 0x2
+    field public static final int FLAG_AF = 1; // 0x1
+    field public static final int FLAG_AWB = 4; // 0x4
+  }
+
+  public static class FocusMeteringAction.Builder {
+    ctor public FocusMeteringAction.Builder(androidx.camera.core.MeteringPoint);
+    ctor public FocusMeteringAction.Builder(androidx.camera.core.MeteringPoint, int);
+    method public androidx.camera.core.FocusMeteringAction.Builder addPoint(androidx.camera.core.MeteringPoint);
+    method public androidx.camera.core.FocusMeteringAction.Builder addPoint(androidx.camera.core.MeteringPoint, int);
+    method public androidx.camera.core.FocusMeteringAction build();
+    method public androidx.camera.core.FocusMeteringAction.Builder disableAutoCancel();
+    method public androidx.camera.core.FocusMeteringAction.Builder setAutoCancelDuration(@IntRange(from=1) long, java.util.concurrent.TimeUnit);
+  }
+
+  public final class FocusMeteringResult {
+    method public boolean isFocusSuccessful();
+  }
+
+  public final class ImageAnalysis extends androidx.camera.core.UseCase {
+    method public void clearAnalyzer();
+    method @SuppressCompatibility @androidx.camera.core.ExperimentalUseCaseApi public java.util.concurrent.Executor? getBackgroundExecutor();
+    method public int getBackpressureStrategy();
+    method public int getImageQueueDepth();
+    method public int getOutputImageFormat();
+    method public androidx.camera.core.ResolutionInfo? getResolutionInfo();
+    method public androidx.camera.core.resolutionselector.ResolutionSelector? getResolutionSelector();
+    method public int getTargetRotation();
+    method public boolean isOutputImageRotationEnabled();
+    method public void setAnalyzer(java.util.concurrent.Executor, androidx.camera.core.ImageAnalysis.Analyzer);
+    method public void setTargetRotation(int);
+    field public static final int COORDINATE_SYSTEM_ORIGINAL = 0; // 0x0
+    field public static final int COORDINATE_SYSTEM_SENSOR = 2; // 0x2
+    field public static final int COORDINATE_SYSTEM_VIEW_REFERENCED = 1; // 0x1
+    field public static final int OUTPUT_IMAGE_FORMAT_RGBA_8888 = 2; // 0x2
+    field public static final int OUTPUT_IMAGE_FORMAT_YUV_420_888 = 1; // 0x1
+    field public static final int STRATEGY_BLOCK_PRODUCER = 1; // 0x1
+    field public static final int STRATEGY_KEEP_ONLY_LATEST = 0; // 0x0
+  }
+
+  public static interface ImageAnalysis.Analyzer {
+    method public void analyze(androidx.camera.core.ImageProxy);
+    method public default android.util.Size? getDefaultTargetResolution();
+    method public default int getTargetCoordinateSystem();
+    method public default void updateTransform(android.graphics.Matrix?);
+  }
+
+  public static final class ImageAnalysis.Builder implements androidx.camera.core.ExtendableBuilder<androidx.camera.core.ImageAnalysis!> {
+    ctor public ImageAnalysis.Builder();
+    method public androidx.camera.core.ImageAnalysis build();
+    method public androidx.camera.core.ImageAnalysis.Builder setBackgroundExecutor(java.util.concurrent.Executor);
+    method public androidx.camera.core.ImageAnalysis.Builder setBackpressureStrategy(int);
+    method public androidx.camera.core.ImageAnalysis.Builder setImageQueueDepth(int);
+    method public androidx.camera.core.ImageAnalysis.Builder setOutputImageFormat(int);
+    method @RequiresApi(23) public androidx.camera.core.ImageAnalysis.Builder setOutputImageRotationEnabled(boolean);
+    method public androidx.camera.core.ImageAnalysis.Builder setResolutionSelector(androidx.camera.core.resolutionselector.ResolutionSelector);
+    method @Deprecated public androidx.camera.core.ImageAnalysis.Builder setTargetAspectRatio(int);
+    method public androidx.camera.core.ImageAnalysis.Builder setTargetName(String);
+    method @Deprecated public androidx.camera.core.ImageAnalysis.Builder setTargetResolution(android.util.Size);
+    method public androidx.camera.core.ImageAnalysis.Builder setTargetRotation(int);
+  }
+
+  public final class ImageCapture extends androidx.camera.core.UseCase {
+    method public int getCaptureMode();
+    method public int getFlashMode();
+    method public static androidx.camera.core.ImageCaptureCapabilities getImageCaptureCapabilities(androidx.camera.core.CameraInfo);
+    method @IntRange(from=1, to=100) public int getJpegQuality();
+    method @SuppressCompatibility @androidx.camera.core.ExperimentalImageCaptureOutputFormat public int getOutputFormat();
+    method public androidx.camera.core.resolutionselector.ResolutionSelector? getPostviewResolutionSelector();
+    method public androidx.camera.core.ImageCaptureLatencyEstimate getRealtimeCaptureLatencyEstimate();
+    method public androidx.camera.core.ResolutionInfo? getResolutionInfo();
+    method public androidx.camera.core.resolutionselector.ResolutionSelector? getResolutionSelector();
+    method public androidx.camera.core.ImageCapture.ScreenFlash? getScreenFlash();
+    method public int getTargetRotation();
+    method public boolean isPostviewEnabled();
+    method public void setCropAspectRatio(android.util.Rational);
+    method public void setFlashMode(int);
+    method public void setScreenFlash(androidx.camera.core.ImageCapture.ScreenFlash?);
+    method public void setTargetRotation(int);
+    method public void takePicture(androidx.camera.core.ImageCapture.OutputFileOptions, java.util.concurrent.Executor, androidx.camera.core.ImageCapture.OnImageSavedCallback);
+    method public void takePicture(java.util.concurrent.Executor, androidx.camera.core.ImageCapture.OnImageCapturedCallback);
+    field public static final int CAPTURE_MODE_MAXIMIZE_QUALITY = 0; // 0x0
+    field public static final int CAPTURE_MODE_MINIMIZE_LATENCY = 1; // 0x1
+    field @SuppressCompatibility @androidx.camera.core.ExperimentalZeroShutterLag public static final int CAPTURE_MODE_ZERO_SHUTTER_LAG = 2; // 0x2
+    field public static final int ERROR_CAMERA_CLOSED = 3; // 0x3
+    field public static final int ERROR_CAPTURE_FAILED = 2; // 0x2
+    field public static final int ERROR_FILE_IO = 1; // 0x1
+    field public static final int ERROR_INVALID_CAMERA = 4; // 0x4
+    field public static final int ERROR_UNKNOWN = 0; // 0x0
+    field public static final int FLASH_MODE_AUTO = 0; // 0x0
+    field public static final int FLASH_MODE_OFF = 2; // 0x2
+    field public static final int FLASH_MODE_ON = 1; // 0x1
+    field public static final int FLASH_MODE_SCREEN = 3; // 0x3
+    field @SuppressCompatibility @androidx.camera.core.ExperimentalImageCaptureOutputFormat public static final int OUTPUT_FORMAT_JPEG = 0; // 0x0
+    field @SuppressCompatibility @androidx.camera.core.ExperimentalImageCaptureOutputFormat public static final int OUTPUT_FORMAT_JPEG_ULTRA_HDR = 1; // 0x1
+  }
+
+  public static final class ImageCapture.Builder implements androidx.camera.core.ExtendableBuilder<androidx.camera.core.ImageCapture!> {
+    ctor public ImageCapture.Builder();
+    method public androidx.camera.core.ImageCapture build();
+    method public androidx.camera.core.ImageCapture.Builder setCaptureMode(int);
+    method public androidx.camera.core.ImageCapture.Builder setFlashMode(int);
+    method public androidx.camera.core.ImageCapture.Builder setIoExecutor(java.util.concurrent.Executor);
+    method public androidx.camera.core.ImageCapture.Builder setJpegQuality(@IntRange(from=1, to=100) int);
+    method @SuppressCompatibility @androidx.camera.core.ExperimentalImageCaptureOutputFormat public androidx.camera.core.ImageCapture.Builder setOutputFormat(int);
+    method public androidx.camera.core.ImageCapture.Builder setPostviewEnabled(boolean);
+    method public androidx.camera.core.ImageCapture.Builder setPostviewResolutionSelector(androidx.camera.core.resolutionselector.ResolutionSelector);
+    method public androidx.camera.core.ImageCapture.Builder setResolutionSelector(androidx.camera.core.resolutionselector.ResolutionSelector);
+    method public androidx.camera.core.ImageCapture.Builder setScreenFlash(androidx.camera.core.ImageCapture.ScreenFlash);
+    method @Deprecated public androidx.camera.core.ImageCapture.Builder setTargetAspectRatio(int);
+    method public androidx.camera.core.ImageCapture.Builder setTargetName(String);
+    method @Deprecated public androidx.camera.core.ImageCapture.Builder setTargetResolution(android.util.Size);
+    method public androidx.camera.core.ImageCapture.Builder setTargetRotation(int);
+  }
+
+  public static final class ImageCapture.Metadata {
+    ctor public ImageCapture.Metadata();
+    method public android.location.Location? getLocation();
+    method public boolean isReversedHorizontal();
+    method public boolean isReversedVertical();
+    method public void setLocation(android.location.Location?);
+    method public void setReversedHorizontal(boolean);
+    method public void setReversedVertical(boolean);
+  }
+
+  public abstract static class ImageCapture.OnImageCapturedCallback {
+    ctor public ImageCapture.OnImageCapturedCallback();
+    method public void onCaptureProcessProgressed(int);
+    method public void onCaptureStarted();
+    method public void onCaptureSuccess(androidx.camera.core.ImageProxy);
+    method public void onError(androidx.camera.core.ImageCaptureException);
+    method public void onPostviewBitmapAvailable(android.graphics.Bitmap);
+  }
+
+  public static interface ImageCapture.OnImageSavedCallback {
+    method public default void onCaptureProcessProgressed(int);
+    method public default void onCaptureStarted();
+    method public void onError(androidx.camera.core.ImageCaptureException);
+    method public void onImageSaved(androidx.camera.core.ImageCapture.OutputFileResults);
+    method public default void onPostviewBitmapAvailable(android.graphics.Bitmap);
+  }
+
+  public static final class ImageCapture.OutputFileOptions {
+  }
+
+  public static final class ImageCapture.OutputFileOptions.Builder {
+    ctor public ImageCapture.OutputFileOptions.Builder(android.content.ContentResolver, android.net.Uri, android.content.ContentValues);
+    ctor public ImageCapture.OutputFileOptions.Builder(java.io.File);
+    ctor public ImageCapture.OutputFileOptions.Builder(java.io.OutputStream);
+    method public androidx.camera.core.ImageCapture.OutputFileOptions build();
+    method public androidx.camera.core.ImageCapture.OutputFileOptions.Builder setMetadata(androidx.camera.core.ImageCapture.Metadata);
+  }
+
+  public static class ImageCapture.OutputFileResults {
+    method public android.net.Uri? getSavedUri();
+  }
+
+  public static interface ImageCapture.ScreenFlash {
+    method @UiThread public void apply(long, androidx.camera.core.ImageCapture.ScreenFlashListener);
+    method @UiThread public void clear();
+  }
+
+  public static interface ImageCapture.ScreenFlashListener {
+    method public void onCompleted();
+  }
+
+  public interface ImageCaptureCapabilities {
+    method @SuppressCompatibility @androidx.camera.core.ExperimentalImageCaptureOutputFormat public java.util.Set<java.lang.Integer!> getSupportedOutputFormats();
+    method public boolean isCaptureProcessProgressSupported();
+    method public boolean isPostviewSupported();
+  }
+
+  public class ImageCaptureException extends java.lang.Exception {
+    ctor public ImageCaptureException(int, String, Throwable?);
+    method public int getImageCaptureError();
+  }
+
+  public final class ImageCaptureExtKt {
+    method public static suspend Object? takePicture(androidx.camera.core.ImageCapture, androidx.camera.core.ImageCapture.OutputFileOptions outputFileOptions, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onCaptureStarted, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit>? onCaptureProcessProgressed, optional kotlin.jvm.functions.Function1<? super android.graphics.Bitmap,kotlin.Unit>? onPostviewBitmapAvailable, kotlin.coroutines.Continuation<? super androidx.camera.core.ImageCapture.OutputFileResults>);
+    method public static suspend Object? takePicture(androidx.camera.core.ImageCapture, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onCaptureStarted, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit>? onCaptureProcessProgressed, optional kotlin.jvm.functions.Function1<? super android.graphics.Bitmap,kotlin.Unit>? onPostviewBitmapAvailable, kotlin.coroutines.Continuation<? super androidx.camera.core.ImageProxy>);
+  }
+
+  public class ImageCaptureLatencyEstimate {
+    ctor public ImageCaptureLatencyEstimate(long, long);
+    method public long getCaptureLatencyMillis();
+    method public long getProcessingLatencyMillis();
+    method public long getTotalCaptureLatencyMillis();
+    field public static final long UNDEFINED_CAPTURE_LATENCY = -1L; // 0xffffffffffffffffL
+    field public static final androidx.camera.core.ImageCaptureLatencyEstimate UNDEFINED_IMAGE_CAPTURE_LATENCY;
+    field public static final long UNDEFINED_PROCESSING_LATENCY = -1L; // 0xffffffffffffffffL
+  }
+
+  public interface ImageInfo {
+    method public int getRotationDegrees();
+    method public default android.graphics.Matrix getSensorToBufferTransformMatrix();
+    method public long getTimestamp();
+  }
+
+  public interface ImageProcessor {
+    method public androidx.camera.core.ImageProcessor.Response process(androidx.camera.core.ImageProcessor.Request) throws androidx.camera.core.ProcessingException;
+  }
+
+  public static interface ImageProcessor.Request {
+    method public androidx.camera.core.ImageProxy getInputImage();
+    method public int getOutputFormat();
+  }
+
+  public static interface ImageProcessor.Response {
+    method public androidx.camera.core.ImageProxy getOutputImage();
+  }
+
+  public interface ImageProxy extends java.lang.AutoCloseable {
+    method public void close();
+    method public android.graphics.Rect getCropRect();
+    method public int getFormat();
+    method public int getHeight();
+    method @SuppressCompatibility @androidx.camera.core.ExperimentalGetImage public android.media.Image? getImage();
+    method public androidx.camera.core.ImageInfo getImageInfo();
+    method public androidx.camera.core.ImageProxy.PlaneProxy![] getPlanes();
+    method public int getWidth();
+    method public void setCropRect(android.graphics.Rect?);
+    method public default android.graphics.Bitmap toBitmap();
+  }
+
+  public static interface ImageProxy.PlaneProxy {
+    method public java.nio.ByteBuffer getBuffer();
+    method public int getPixelStride();
+    method public int getRowStride();
+  }
+
+  public class InitializationException extends java.lang.Exception {
+    ctor public InitializationException(String?);
+    ctor public InitializationException(String?, Throwable?);
+    ctor public InitializationException(Throwable?);
+  }
+
+  public class MeteringPoint {
+    method public float getSize();
+  }
+
+  public abstract class MeteringPointFactory {
+    method public final androidx.camera.core.MeteringPoint createPoint(float, float);
+    method public final androidx.camera.core.MeteringPoint createPoint(float, float, float);
+    method public static float getDefaultPointSize();
+  }
+
+  public class MirrorMode {
+    field public static final int MIRROR_MODE_OFF = 0; // 0x0
+    field public static final int MIRROR_MODE_ON = 1; // 0x1
+    field public static final int MIRROR_MODE_ON_FRONT_ONLY = 2; // 0x2
+  }
+
+  public final class Preview extends androidx.camera.core.UseCase {
+    method public androidx.camera.core.DynamicRange getDynamicRange();
+    method public static androidx.camera.core.PreviewCapabilities getPreviewCapabilities(androidx.camera.core.CameraInfo);
+    method public androidx.camera.core.ResolutionInfo? getResolutionInfo();
+    method public androidx.camera.core.resolutionselector.ResolutionSelector? getResolutionSelector();
+    method public android.util.Range<java.lang.Integer!> getTargetFrameRate();
+    method public int getTargetRotation();
+    method public boolean isPreviewStabilizationEnabled();
+    method @UiThread public void setSurfaceProvider(androidx.camera.core.Preview.SurfaceProvider?);
+    method @UiThread public void setSurfaceProvider(java.util.concurrent.Executor, androidx.camera.core.Preview.SurfaceProvider?);
+    method public void setTargetRotation(int);
+  }
+
+  public static final class Preview.Builder implements androidx.camera.core.ExtendableBuilder<androidx.camera.core.Preview!> {
+    ctor public Preview.Builder();
+    method public androidx.camera.core.Preview build();
+    method public androidx.camera.core.Preview.Builder setDynamicRange(androidx.camera.core.DynamicRange);
+    method @SuppressCompatibility @androidx.camera.core.ExperimentalMirrorMode public androidx.camera.core.Preview.Builder setMirrorMode(int);
+    method public androidx.camera.core.Preview.Builder setPreviewStabilizationEnabled(boolean);
+    method public androidx.camera.core.Preview.Builder setResolutionSelector(androidx.camera.core.resolutionselector.ResolutionSelector);
+    method @Deprecated public androidx.camera.core.Preview.Builder setTargetAspectRatio(int);
+    method public androidx.camera.core.Preview.Builder setTargetFrameRate(android.util.Range<java.lang.Integer!>);
+    method public androidx.camera.core.Preview.Builder setTargetName(String);
+    method @Deprecated public androidx.camera.core.Preview.Builder setTargetResolution(android.util.Size);
+    method public androidx.camera.core.Preview.Builder setTargetRotation(int);
+  }
+
+  public static interface Preview.SurfaceProvider {
+    method public void onSurfaceRequested(androidx.camera.core.SurfaceRequest);
+  }
+
+  public interface PreviewCapabilities {
+    method public boolean isStabilizationSupported();
+  }
+
+  public class ProcessingException extends java.lang.Exception {
+    ctor public ProcessingException();
+  }
+
+  public class ResolutionInfo {
+    ctor public ResolutionInfo(android.util.Size, android.graphics.Rect, int);
+    method public android.graphics.Rect getCropRect();
+    method public android.util.Size getResolution();
+    method public int getRotationDegrees();
+  }
+
+  @SuppressCompatibility @androidx.camera.core.ExperimentalRetryPolicy public interface RetryPolicy {
+    method public static long getDefaultRetryTimeoutInMillis();
+    method public default long getTimeoutInMillis();
+    method public androidx.camera.core.RetryPolicy.RetryConfig onRetryDecisionRequested(androidx.camera.core.RetryPolicy.ExecutionState);
+    field public static final androidx.camera.core.RetryPolicy DEFAULT;
+    field public static final androidx.camera.core.RetryPolicy NEVER;
+    field public static final androidx.camera.core.RetryPolicy RETRY_UNAVAILABLE_CAMERA;
+  }
+
+  @SuppressCompatibility @androidx.camera.core.ExperimentalRetryPolicy public static final class RetryPolicy.Builder {
+    ctor public RetryPolicy.Builder(androidx.camera.core.RetryPolicy);
+    method public androidx.camera.core.RetryPolicy build();
+    method public androidx.camera.core.RetryPolicy.Builder setTimeoutInMillis(long);
+  }
+
+  @SuppressCompatibility @androidx.camera.core.ExperimentalRetryPolicy public static interface RetryPolicy.ExecutionState {
+    method public Throwable? getCause();
+    method public long getExecutedTimeInMillis();
+    method public int getNumOfAttempts();
+    method public int getStatus();
+    field public static final int STATUS_CAMERA_UNAVAILABLE = 2; // 0x2
+    field public static final int STATUS_CONFIGURATION_FAIL = 1; // 0x1
+    field public static final int STATUS_UNKNOWN_ERROR = 0; // 0x0
+  }
+
+  @SuppressCompatibility @androidx.camera.core.ExperimentalRetryPolicy public static final class RetryPolicy.RetryConfig {
+    method public static long getDefaultRetryDelayInMillis();
+    method public long getRetryDelayInMillis();
+    method public boolean shouldRetry();
+    field public static final androidx.camera.core.RetryPolicy.RetryConfig DEFAULT_DELAY_RETRY;
+    field public static final androidx.camera.core.RetryPolicy.RetryConfig MINI_DELAY_RETRY;
+    field public static final androidx.camera.core.RetryPolicy.RetryConfig NOT_RETRY;
+  }
+
+  @SuppressCompatibility @androidx.camera.core.ExperimentalRetryPolicy public static final class RetryPolicy.RetryConfig.Builder {
+    ctor public RetryPolicy.RetryConfig.Builder();
+    method public androidx.camera.core.RetryPolicy.RetryConfig build();
+    method public androidx.camera.core.RetryPolicy.RetryConfig.Builder setRetryDelayInMillis(@IntRange(from=100, to=2000) long);
+    method public androidx.camera.core.RetryPolicy.RetryConfig.Builder setShouldRetry(boolean);
+  }
+
+  public class SurfaceOrientedMeteringPointFactory extends androidx.camera.core.MeteringPointFactory {
+    ctor public SurfaceOrientedMeteringPointFactory(float, float);
+    ctor public SurfaceOrientedMeteringPointFactory(float, float, androidx.camera.core.UseCase);
+  }
+
+  public interface SurfaceOutput extends java.io.Closeable {
+    method public void close();
+    method public default android.graphics.Matrix getSensorToBufferTransform();
+    method public android.util.Size getSize();
+    method public android.view.Surface getSurface(java.util.concurrent.Executor, androidx.core.util.Consumer<androidx.camera.core.SurfaceOutput.Event!>);
+    method public int getTargets();
+    method public void updateTransformMatrix(float[], float[]);
+  }
+
+  @com.google.auto.value.AutoValue public abstract static class SurfaceOutput.Event {
+    method public abstract int getEventCode();
+    method public abstract androidx.camera.core.SurfaceOutput getSurfaceOutput();
+    field public static final int EVENT_REQUEST_CLOSE = 0; // 0x0
+  }
+
+  public interface SurfaceProcessor {
+    method public void onInputSurface(androidx.camera.core.SurfaceRequest) throws androidx.camera.core.ProcessingException;
+    method public void onOutputSurface(androidx.camera.core.SurfaceOutput) throws androidx.camera.core.ProcessingException;
+  }
+
+  public final class SurfaceRequest {
+    method public void addRequestCancellationListener(java.util.concurrent.Executor, Runnable);
+    method public void clearTransformationInfoListener();
+    method public androidx.camera.core.DynamicRange getDynamicRange();
+    method public android.util.Size getResolution();
+    method public boolean invalidate();
+    method public void provideSurface(android.view.Surface, java.util.concurrent.Executor, androidx.core.util.Consumer<androidx.camera.core.SurfaceRequest.Result!>);
+    method public void setTransformationInfoListener(java.util.concurrent.Executor, androidx.camera.core.SurfaceRequest.TransformationInfoListener);
+    method public boolean willNotProvideSurface();
+  }
+
+  @com.google.auto.value.AutoValue public abstract static class SurfaceRequest.Result {
+    method public abstract int getResultCode();
+    method public abstract android.view.Surface getSurface();
+    field public static final int RESULT_INVALID_SURFACE = 2; // 0x2
+    field public static final int RESULT_REQUEST_CANCELLED = 1; // 0x1
+    field public static final int RESULT_SURFACE_ALREADY_PROVIDED = 3; // 0x3
+    field public static final int RESULT_SURFACE_USED_SUCCESSFULLY = 0; // 0x0
+    field public static final int RESULT_WILL_NOT_PROVIDE_SURFACE = 4; // 0x4
+  }
+
+  @com.google.auto.value.AutoValue public abstract static class SurfaceRequest.TransformationInfo {
+    method public abstract android.graphics.Rect getCropRect();
+    method public abstract int getRotationDegrees();
+    method public abstract android.graphics.Matrix getSensorToBufferTransform();
+    method public abstract boolean hasCameraTransform();
+    method public abstract boolean isMirroring();
+  }
+
+  public static interface SurfaceRequest.TransformationInfoListener {
+    method public void onTransformationInfoUpdate(androidx.camera.core.SurfaceRequest.TransformationInfo);
+  }
+
+  public class TorchState {
+    field public static final int OFF = 0; // 0x0
+    field public static final int ON = 1; // 0x1
+  }
+
+  public abstract class UseCase {
+    method public static int snapToSurfaceRotation(@IntRange(from=0, to=359) int);
+  }
+
+  public final class UseCaseGroup {
+    method public java.util.List<androidx.camera.core.CameraEffect!> getEffects();
+    method public java.util.List<androidx.camera.core.UseCase!> getUseCases();
+    method public androidx.camera.core.ViewPort? getViewPort();
+  }
+
+  public static final class UseCaseGroup.Builder {
+    ctor public UseCaseGroup.Builder();
+    method public androidx.camera.core.UseCaseGroup.Builder addEffect(androidx.camera.core.CameraEffect);
+    method public androidx.camera.core.UseCaseGroup.Builder addUseCase(androidx.camera.core.UseCase);
+    method public androidx.camera.core.UseCaseGroup build();
+    method public androidx.camera.core.UseCaseGroup.Builder setViewPort(androidx.camera.core.ViewPort);
+  }
+
+  public final class ViewPort {
+    method public android.util.Rational getAspectRatio();
+    method public int getLayoutDirection();
+    method public int getRotation();
+    method public int getScaleType();
+    field public static final int FILL_CENTER = 1; // 0x1
+    field public static final int FILL_END = 2; // 0x2
+    field public static final int FILL_START = 0; // 0x0
+    field public static final int FIT = 3; // 0x3
+  }
+
+  public static final class ViewPort.Builder {
+    ctor public ViewPort.Builder(android.util.Rational, int);
+    method public androidx.camera.core.ViewPort build();
+    method public androidx.camera.core.ViewPort.Builder setLayoutDirection(int);
+    method public androidx.camera.core.ViewPort.Builder setScaleType(int);
+  }
+
+  public interface ZoomState {
+    method public float getLinearZoom();
+    method public float getMaxZoomRatio();
+    method public float getMinZoomRatio();
+    method public float getZoomRatio();
+  }
+
+}
+
+package androidx.camera.core.resolutionselector {
+
+  public final class AspectRatioStrategy {
+    ctor public AspectRatioStrategy(int, int);
+    method public int getFallbackRule();
+    method public int getPreferredAspectRatio();
+    field public static final int FALLBACK_RULE_AUTO = 1; // 0x1
+    field public static final int FALLBACK_RULE_NONE = 0; // 0x0
+    field public static final androidx.camera.core.resolutionselector.AspectRatioStrategy RATIO_16_9_FALLBACK_AUTO_STRATEGY;
+    field public static final androidx.camera.core.resolutionselector.AspectRatioStrategy RATIO_4_3_FALLBACK_AUTO_STRATEGY;
+  }
+
+  public interface ResolutionFilter {
+    method public java.util.List<android.util.Size!> filter(java.util.List<android.util.Size!>, int);
+  }
+
+  public final class ResolutionSelector {
+    method public int getAllowedResolutionMode();
+    method public androidx.camera.core.resolutionselector.AspectRatioStrategy getAspectRatioStrategy();
+    method public androidx.camera.core.resolutionselector.ResolutionFilter? getResolutionFilter();
+    method public androidx.camera.core.resolutionselector.ResolutionStrategy? getResolutionStrategy();
+    field public static final int PREFER_CAPTURE_RATE_OVER_HIGHER_RESOLUTION = 0; // 0x0
+    field public static final int PREFER_HIGHER_RESOLUTION_OVER_CAPTURE_RATE = 1; // 0x1
+  }
+
+  public static final class ResolutionSelector.Builder {
+    ctor public ResolutionSelector.Builder();
+    method public androidx.camera.core.resolutionselector.ResolutionSelector build();
+    method public androidx.camera.core.resolutionselector.ResolutionSelector.Builder setAllowedResolutionMode(int);
+    method public androidx.camera.core.resolutionselector.ResolutionSelector.Builder setAspectRatioStrategy(androidx.camera.core.resolutionselector.AspectRatioStrategy);
+    method public androidx.camera.core.resolutionselector.ResolutionSelector.Builder setResolutionFilter(androidx.camera.core.resolutionselector.ResolutionFilter);
+    method public androidx.camera.core.resolutionselector.ResolutionSelector.Builder setResolutionStrategy(androidx.camera.core.resolutionselector.ResolutionStrategy);
+  }
+
+  public final class ResolutionStrategy {
+    ctor public ResolutionStrategy(android.util.Size, int);
+    method public android.util.Size? getBoundSize();
+    method public int getFallbackRule();
+    field public static final int FALLBACK_RULE_CLOSEST_HIGHER = 2; // 0x2
+    field public static final int FALLBACK_RULE_CLOSEST_HIGHER_THEN_LOWER = 1; // 0x1
+    field public static final int FALLBACK_RULE_CLOSEST_LOWER = 4; // 0x4
+    field public static final int FALLBACK_RULE_CLOSEST_LOWER_THEN_HIGHER = 3; // 0x3
+    field public static final int FALLBACK_RULE_NONE = 0; // 0x0
+    field public static final androidx.camera.core.resolutionselector.ResolutionStrategy HIGHEST_AVAILABLE_STRATEGY;
+  }
+
+}
+
diff --git a/camera/camera-core/api/res-1.4.0-beta03.txt b/camera/camera-core/api/res-1.4.0-beta03.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/camera/camera-core/api/res-1.4.0-beta03.txt
diff --git a/camera/camera-core/api/restricted_1.4.0-beta03.txt b/camera/camera-core/api/restricted_1.4.0-beta03.txt
new file mode 100644
index 0000000..be07f31
--- /dev/null
+++ b/camera/camera-core/api/restricted_1.4.0-beta03.txt
@@ -0,0 +1,742 @@
+// Signature format: 4.0
+package androidx.camera.core {
+
+  public class AspectRatio {
+    field public static final int RATIO_16_9 = 1; // 0x1
+    field public static final int RATIO_4_3 = 0; // 0x0
+    field public static final int RATIO_DEFAULT = -1; // 0xffffffff
+  }
+
+  public interface Camera {
+    method public androidx.camera.core.CameraControl getCameraControl();
+    method public androidx.camera.core.CameraInfo getCameraInfo();
+  }
+
+  public interface CameraControl {
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> cancelFocusAndMetering();
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enableTorch(boolean);
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Integer!> setExposureCompensationIndex(int);
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setLinearZoom(@FloatRange(from=0.0f, to=1.0f) float);
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setZoomRatio(float);
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.camera.core.FocusMeteringResult!> startFocusAndMetering(androidx.camera.core.FocusMeteringAction);
+  }
+
+  public static final class CameraControl.OperationCanceledException extends java.lang.Exception {
+  }
+
+  public abstract class CameraEffect {
+    ctor protected CameraEffect(int, java.util.concurrent.Executor, androidx.camera.core.ImageProcessor, androidx.core.util.Consumer<java.lang.Throwable!>);
+    ctor protected CameraEffect(int, java.util.concurrent.Executor, androidx.camera.core.SurfaceProcessor, androidx.core.util.Consumer<java.lang.Throwable!>);
+    method public androidx.core.util.Consumer<java.lang.Throwable!> getErrorListener();
+    method public java.util.concurrent.Executor getExecutor();
+    method public androidx.camera.core.SurfaceProcessor? getSurfaceProcessor();
+    method public int getTargets();
+    field public static final int IMAGE_CAPTURE = 4; // 0x4
+    field public static final int PREVIEW = 1; // 0x1
+    field public static final int VIDEO_CAPTURE = 2; // 0x2
+  }
+
+  public interface CameraFilter {
+    method public java.util.List<androidx.camera.core.CameraInfo!> filter(java.util.List<androidx.camera.core.CameraInfo!>);
+  }
+
+  public interface CameraInfo {
+    method public androidx.camera.core.CameraSelector getCameraSelector();
+    method public androidx.lifecycle.LiveData<androidx.camera.core.CameraState!> getCameraState();
+    method public androidx.camera.core.ExposureState getExposureState();
+    method @FloatRange(from=0, fromInclusive=false) public default float getIntrinsicZoomRatio();
+    method public default int getLensFacing();
+    method public default java.util.Set<androidx.camera.core.CameraInfo!> getPhysicalCameraInfos();
+    method public int getSensorRotationDegrees();
+    method public int getSensorRotationDegrees(int);
+    method public default java.util.Set<android.util.Range<java.lang.Integer!>!> getSupportedFrameRateRanges();
+    method public androidx.lifecycle.LiveData<java.lang.Integer!> getTorchState();
+    method public androidx.lifecycle.LiveData<androidx.camera.core.ZoomState!> getZoomState();
+    method public boolean hasFlashUnit();
+    method public default boolean isFocusMeteringSupported(androidx.camera.core.FocusMeteringAction);
+    method public default boolean isLogicalMultiCameraSupported();
+    method @SuppressCompatibility @androidx.camera.core.ExperimentalZeroShutterLag public default boolean isZslSupported();
+    method public static boolean mustPlayShutterSound();
+    method public default java.util.Set<androidx.camera.core.DynamicRange!> querySupportedDynamicRanges(java.util.Set<androidx.camera.core.DynamicRange!>);
+  }
+
+  public final class CameraInfoUnavailableException extends java.lang.Exception {
+  }
+
+  public interface CameraProvider {
+    method public java.util.List<androidx.camera.core.CameraInfo!> getAvailableCameraInfos();
+    method @SuppressCompatibility @androidx.camera.core.ExperimentalCameraInfo public default androidx.camera.core.CameraInfo getCameraInfo(androidx.camera.core.CameraSelector);
+    method public boolean hasCamera(androidx.camera.core.CameraSelector) throws androidx.camera.core.CameraInfoUnavailableException;
+  }
+
+  public final class CameraSelector {
+    method public java.util.List<androidx.camera.core.CameraInfo!> filter(java.util.List<androidx.camera.core.CameraInfo!>);
+    method public String? getPhysicalCameraId();
+    field public static final androidx.camera.core.CameraSelector DEFAULT_BACK_CAMERA;
+    field public static final androidx.camera.core.CameraSelector DEFAULT_FRONT_CAMERA;
+    field public static final int LENS_FACING_BACK = 1; // 0x1
+    field @SuppressCompatibility @androidx.camera.core.ExperimentalLensFacing public static final int LENS_FACING_EXTERNAL = 2; // 0x2
+    field public static final int LENS_FACING_FRONT = 0; // 0x0
+    field public static final int LENS_FACING_UNKNOWN = -1; // 0xffffffff
+  }
+
+  public static final class CameraSelector.Builder {
+    ctor public CameraSelector.Builder();
+    method public androidx.camera.core.CameraSelector.Builder addCameraFilter(androidx.camera.core.CameraFilter);
+    method public androidx.camera.core.CameraSelector build();
+    method public androidx.camera.core.CameraSelector.Builder requireLensFacing(int);
+    method public androidx.camera.core.CameraSelector.Builder setPhysicalCameraId(String);
+  }
+
+  @com.google.auto.value.AutoValue public abstract class CameraState {
+    ctor public CameraState();
+    method public static androidx.camera.core.CameraState create(androidx.camera.core.CameraState.Type);
+    method public static androidx.camera.core.CameraState create(androidx.camera.core.CameraState.Type, androidx.camera.core.CameraState.StateError?);
+    method public abstract androidx.camera.core.CameraState.StateError? getError();
+    method public abstract androidx.camera.core.CameraState.Type getType();
+    field public static final int ERROR_CAMERA_DISABLED = 5; // 0x5
+    field public static final int ERROR_CAMERA_FATAL_ERROR = 6; // 0x6
+    field public static final int ERROR_CAMERA_IN_USE = 2; // 0x2
+    field public static final int ERROR_DO_NOT_DISTURB_MODE_ENABLED = 7; // 0x7
+    field public static final int ERROR_MAX_CAMERAS_IN_USE = 1; // 0x1
+    field public static final int ERROR_OTHER_RECOVERABLE_ERROR = 3; // 0x3
+    field public static final int ERROR_STREAM_CONFIG = 4; // 0x4
+  }
+
+  public enum CameraState.ErrorType {
+    enum_constant public static final androidx.camera.core.CameraState.ErrorType CRITICAL;
+    enum_constant public static final androidx.camera.core.CameraState.ErrorType RECOVERABLE;
+  }
+
+  @com.google.auto.value.AutoValue public abstract static class CameraState.StateError {
+    ctor public CameraState.StateError();
+    method public static androidx.camera.core.CameraState.StateError create(int);
+    method public static androidx.camera.core.CameraState.StateError create(int, Throwable?);
+    method public abstract Throwable? getCause();
+    method public abstract int getCode();
+    method public androidx.camera.core.CameraState.ErrorType getType();
+  }
+
+  public enum CameraState.Type {
+    enum_constant public static final androidx.camera.core.CameraState.Type CLOSED;
+    enum_constant public static final androidx.camera.core.CameraState.Type CLOSING;
+    enum_constant public static final androidx.camera.core.CameraState.Type OPEN;
+    enum_constant public static final androidx.camera.core.CameraState.Type OPENING;
+    enum_constant public static final androidx.camera.core.CameraState.Type PENDING_OPEN;
+  }
+
+  public class CameraUnavailableException extends java.lang.Exception {
+    ctor public CameraUnavailableException(int);
+    ctor public CameraUnavailableException(int, String?);
+    ctor public CameraUnavailableException(int, String?, Throwable?);
+    ctor public CameraUnavailableException(int, Throwable?);
+    method public int getReason();
+    field public static final int CAMERA_DISABLED = 1; // 0x1
+    field public static final int CAMERA_DISCONNECTED = 2; // 0x2
+    field public static final int CAMERA_ERROR = 3; // 0x3
+    field public static final int CAMERA_IN_USE = 4; // 0x4
+    field public static final int CAMERA_MAX_IN_USE = 5; // 0x5
+    field public static final int CAMERA_UNAVAILABLE_DO_NOT_DISTURB = 6; // 0x6
+    field public static final int CAMERA_UNKNOWN_ERROR = 0; // 0x0
+  }
+
+  public final class CameraXConfig {
+    method public androidx.camera.core.CameraSelector? getAvailableCamerasLimiter(androidx.camera.core.CameraSelector?);
+    method public java.util.concurrent.Executor? getCameraExecutor(java.util.concurrent.Executor?);
+    method public long getCameraOpenRetryMaxTimeoutInMillisWhileResuming();
+    method @SuppressCompatibility @androidx.camera.core.ExperimentalRetryPolicy public androidx.camera.core.RetryPolicy getCameraProviderInitRetryPolicy();
+    method public int getMinimumLoggingLevel();
+    method public android.os.Handler? getSchedulerHandler(android.os.Handler?);
+  }
+
+  public static final class CameraXConfig.Builder {
+    method public androidx.camera.core.CameraXConfig build();
+    method public static androidx.camera.core.CameraXConfig.Builder fromConfig(androidx.camera.core.CameraXConfig);
+    method public androidx.camera.core.CameraXConfig.Builder setAvailableCamerasLimiter(androidx.camera.core.CameraSelector);
+    method public androidx.camera.core.CameraXConfig.Builder setCameraExecutor(java.util.concurrent.Executor);
+    method public androidx.camera.core.CameraXConfig.Builder setCameraOpenRetryMaxTimeoutInMillisWhileResuming(long);
+    method @SuppressCompatibility @androidx.camera.core.ExperimentalRetryPolicy public androidx.camera.core.CameraXConfig.Builder setCameraProviderInitRetryPolicy(androidx.camera.core.RetryPolicy);
+    method public androidx.camera.core.CameraXConfig.Builder setMinimumLoggingLevel(@IntRange(from=android.util.Log.DEBUG, to=android.util.Log.ERROR) int);
+    method public androidx.camera.core.CameraXConfig.Builder setSchedulerHandler(android.os.Handler);
+  }
+
+  public static interface CameraXConfig.Provider {
+    method public androidx.camera.core.CameraXConfig getCameraXConfig();
+  }
+
+  public class ConcurrentCamera {
+    ctor public ConcurrentCamera(java.util.List<androidx.camera.core.Camera!>);
+    method public java.util.List<androidx.camera.core.Camera!> getCameras();
+  }
+
+  public static final class ConcurrentCamera.SingleCameraConfig {
+    ctor public ConcurrentCamera.SingleCameraConfig(androidx.camera.core.CameraSelector, androidx.camera.core.UseCaseGroup, androidx.lifecycle.LifecycleOwner);
+    method public androidx.camera.core.CameraSelector getCameraSelector();
+    method public androidx.lifecycle.LifecycleOwner getLifecycleOwner();
+    method public androidx.camera.core.UseCaseGroup getUseCaseGroup();
+  }
+
+  public final class DisplayOrientedMeteringPointFactory extends androidx.camera.core.MeteringPointFactory {
+    ctor public DisplayOrientedMeteringPointFactory(android.view.Display, androidx.camera.core.CameraInfo, float, float);
+  }
+
+  public final class DynamicRange {
+    ctor public DynamicRange(int, int);
+    method public int getBitDepth();
+    method public int getEncoding();
+    field public static final int BIT_DEPTH_10_BIT = 10; // 0xa
+    field public static final int BIT_DEPTH_8_BIT = 8; // 0x8
+    field public static final int BIT_DEPTH_UNSPECIFIED = 0; // 0x0
+    field public static final androidx.camera.core.DynamicRange DOLBY_VISION_10_BIT;
+    field public static final androidx.camera.core.DynamicRange DOLBY_VISION_8_BIT;
+    field public static final int ENCODING_DOLBY_VISION = 6; // 0x6
+    field public static final int ENCODING_HDR10 = 4; // 0x4
+    field public static final int ENCODING_HDR10_PLUS = 5; // 0x5
+    field public static final int ENCODING_HDR_UNSPECIFIED = 2; // 0x2
+    field public static final int ENCODING_HLG = 3; // 0x3
+    field public static final int ENCODING_SDR = 1; // 0x1
+    field public static final int ENCODING_UNSPECIFIED = 0; // 0x0
+    field public static final androidx.camera.core.DynamicRange HDR10_10_BIT;
+    field public static final androidx.camera.core.DynamicRange HDR10_PLUS_10_BIT;
+    field public static final androidx.camera.core.DynamicRange HDR_UNSPECIFIED_10_BIT;
+    field public static final androidx.camera.core.DynamicRange HLG_10_BIT;
+    field public static final androidx.camera.core.DynamicRange SDR;
+    field public static final androidx.camera.core.DynamicRange UNSPECIFIED;
+  }
+
+  @SuppressCompatibility @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface ExperimentalCameraInfo {
+  }
+
+  @SuppressCompatibility @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface ExperimentalGetImage {
+  }
+
+  @SuppressCompatibility @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface ExperimentalImageCaptureOutputFormat {
+  }
+
+  @SuppressCompatibility @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface ExperimentalLensFacing {
+  }
+
+  @SuppressCompatibility @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface ExperimentalMirrorMode {
+  }
+
+  @SuppressCompatibility @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface ExperimentalRetryPolicy {
+  }
+
+  @SuppressCompatibility @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface ExperimentalUseCaseApi {
+  }
+
+  @SuppressCompatibility @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface ExperimentalZeroShutterLag {
+  }
+
+  public interface ExposureState {
+    method public int getExposureCompensationIndex();
+    method public android.util.Range<java.lang.Integer!> getExposureCompensationRange();
+    method public android.util.Rational getExposureCompensationStep();
+    method public boolean isExposureCompensationSupported();
+  }
+
+  public interface ExtendableBuilder<T> {
+    method public T build();
+  }
+
+  public final class FocusMeteringAction {
+    method public long getAutoCancelDurationInMillis();
+    method public java.util.List<androidx.camera.core.MeteringPoint!> getMeteringPointsAe();
+    method public java.util.List<androidx.camera.core.MeteringPoint!> getMeteringPointsAf();
+    method public java.util.List<androidx.camera.core.MeteringPoint!> getMeteringPointsAwb();
+    method public boolean isAutoCancelEnabled();
+    field public static final int FLAG_AE = 2; // 0x2
+    field public static final int FLAG_AF = 1; // 0x1
+    field public static final int FLAG_AWB = 4; // 0x4
+  }
+
+  public static class FocusMeteringAction.Builder {
+    ctor public FocusMeteringAction.Builder(androidx.camera.core.MeteringPoint);
+    ctor public FocusMeteringAction.Builder(androidx.camera.core.MeteringPoint, int);
+    method public androidx.camera.core.FocusMeteringAction.Builder addPoint(androidx.camera.core.MeteringPoint);
+    method public androidx.camera.core.FocusMeteringAction.Builder addPoint(androidx.camera.core.MeteringPoint, int);
+    method public androidx.camera.core.FocusMeteringAction build();
+    method public androidx.camera.core.FocusMeteringAction.Builder disableAutoCancel();
+    method public androidx.camera.core.FocusMeteringAction.Builder setAutoCancelDuration(@IntRange(from=1) long, java.util.concurrent.TimeUnit);
+  }
+
+  public final class FocusMeteringResult {
+    method public boolean isFocusSuccessful();
+  }
+
+  public final class ImageAnalysis extends androidx.camera.core.UseCase {
+    method public void clearAnalyzer();
+    method @SuppressCompatibility @androidx.camera.core.ExperimentalUseCaseApi public java.util.concurrent.Executor? getBackgroundExecutor();
+    method public int getBackpressureStrategy();
+    method public int getImageQueueDepth();
+    method public int getOutputImageFormat();
+    method public androidx.camera.core.ResolutionInfo? getResolutionInfo();
+    method public androidx.camera.core.resolutionselector.ResolutionSelector? getResolutionSelector();
+    method public int getTargetRotation();
+    method public boolean isOutputImageRotationEnabled();
+    method public void setAnalyzer(java.util.concurrent.Executor, androidx.camera.core.ImageAnalysis.Analyzer);
+    method public void setTargetRotation(int);
+    field public static final int COORDINATE_SYSTEM_ORIGINAL = 0; // 0x0
+    field public static final int COORDINATE_SYSTEM_SENSOR = 2; // 0x2
+    field public static final int COORDINATE_SYSTEM_VIEW_REFERENCED = 1; // 0x1
+    field public static final int OUTPUT_IMAGE_FORMAT_RGBA_8888 = 2; // 0x2
+    field public static final int OUTPUT_IMAGE_FORMAT_YUV_420_888 = 1; // 0x1
+    field public static final int STRATEGY_BLOCK_PRODUCER = 1; // 0x1
+    field public static final int STRATEGY_KEEP_ONLY_LATEST = 0; // 0x0
+  }
+
+  public static interface ImageAnalysis.Analyzer {
+    method public void analyze(androidx.camera.core.ImageProxy);
+    method public default android.util.Size? getDefaultTargetResolution();
+    method public default int getTargetCoordinateSystem();
+    method public default void updateTransform(android.graphics.Matrix?);
+  }
+
+  public static final class ImageAnalysis.Builder implements androidx.camera.core.ExtendableBuilder<androidx.camera.core.ImageAnalysis!> {
+    ctor public ImageAnalysis.Builder();
+    method public androidx.camera.core.ImageAnalysis build();
+    method public androidx.camera.core.ImageAnalysis.Builder setBackgroundExecutor(java.util.concurrent.Executor);
+    method public androidx.camera.core.ImageAnalysis.Builder setBackpressureStrategy(int);
+    method public androidx.camera.core.ImageAnalysis.Builder setImageQueueDepth(int);
+    method public androidx.camera.core.ImageAnalysis.Builder setOutputImageFormat(int);
+    method @RequiresApi(23) public androidx.camera.core.ImageAnalysis.Builder setOutputImageRotationEnabled(boolean);
+    method public androidx.camera.core.ImageAnalysis.Builder setResolutionSelector(androidx.camera.core.resolutionselector.ResolutionSelector);
+    method @Deprecated public androidx.camera.core.ImageAnalysis.Builder setTargetAspectRatio(int);
+    method public androidx.camera.core.ImageAnalysis.Builder setTargetName(String);
+    method @Deprecated public androidx.camera.core.ImageAnalysis.Builder setTargetResolution(android.util.Size);
+    method public androidx.camera.core.ImageAnalysis.Builder setTargetRotation(int);
+  }
+
+  public final class ImageCapture extends androidx.camera.core.UseCase {
+    method public int getCaptureMode();
+    method public int getFlashMode();
+    method public static androidx.camera.core.ImageCaptureCapabilities getImageCaptureCapabilities(androidx.camera.core.CameraInfo);
+    method @IntRange(from=1, to=100) public int getJpegQuality();
+    method @SuppressCompatibility @androidx.camera.core.ExperimentalImageCaptureOutputFormat public int getOutputFormat();
+    method public androidx.camera.core.resolutionselector.ResolutionSelector? getPostviewResolutionSelector();
+    method public androidx.camera.core.ImageCaptureLatencyEstimate getRealtimeCaptureLatencyEstimate();
+    method public androidx.camera.core.ResolutionInfo? getResolutionInfo();
+    method public androidx.camera.core.resolutionselector.ResolutionSelector? getResolutionSelector();
+    method public androidx.camera.core.ImageCapture.ScreenFlash? getScreenFlash();
+    method public int getTargetRotation();
+    method public boolean isPostviewEnabled();
+    method public void setCropAspectRatio(android.util.Rational);
+    method public void setFlashMode(int);
+    method public void setScreenFlash(androidx.camera.core.ImageCapture.ScreenFlash?);
+    method public void setTargetRotation(int);
+    method public void takePicture(androidx.camera.core.ImageCapture.OutputFileOptions, java.util.concurrent.Executor, androidx.camera.core.ImageCapture.OnImageSavedCallback);
+    method public void takePicture(java.util.concurrent.Executor, androidx.camera.core.ImageCapture.OnImageCapturedCallback);
+    field public static final int CAPTURE_MODE_MAXIMIZE_QUALITY = 0; // 0x0
+    field public static final int CAPTURE_MODE_MINIMIZE_LATENCY = 1; // 0x1
+    field @SuppressCompatibility @androidx.camera.core.ExperimentalZeroShutterLag public static final int CAPTURE_MODE_ZERO_SHUTTER_LAG = 2; // 0x2
+    field public static final int ERROR_CAMERA_CLOSED = 3; // 0x3
+    field public static final int ERROR_CAPTURE_FAILED = 2; // 0x2
+    field public static final int ERROR_FILE_IO = 1; // 0x1
+    field public static final int ERROR_INVALID_CAMERA = 4; // 0x4
+    field public static final int ERROR_UNKNOWN = 0; // 0x0
+    field public static final int FLASH_MODE_AUTO = 0; // 0x0
+    field public static final int FLASH_MODE_OFF = 2; // 0x2
+    field public static final int FLASH_MODE_ON = 1; // 0x1
+    field public static final int FLASH_MODE_SCREEN = 3; // 0x3
+    field @SuppressCompatibility @androidx.camera.core.ExperimentalImageCaptureOutputFormat public static final int OUTPUT_FORMAT_JPEG = 0; // 0x0
+    field @SuppressCompatibility @androidx.camera.core.ExperimentalImageCaptureOutputFormat public static final int OUTPUT_FORMAT_JPEG_ULTRA_HDR = 1; // 0x1
+  }
+
+  public static final class ImageCapture.Builder implements androidx.camera.core.ExtendableBuilder<androidx.camera.core.ImageCapture!> {
+    ctor public ImageCapture.Builder();
+    method public androidx.camera.core.ImageCapture build();
+    method public androidx.camera.core.ImageCapture.Builder setCaptureMode(int);
+    method public androidx.camera.core.ImageCapture.Builder setFlashMode(int);
+    method public androidx.camera.core.ImageCapture.Builder setIoExecutor(java.util.concurrent.Executor);
+    method public androidx.camera.core.ImageCapture.Builder setJpegQuality(@IntRange(from=1, to=100) int);
+    method @SuppressCompatibility @androidx.camera.core.ExperimentalImageCaptureOutputFormat public androidx.camera.core.ImageCapture.Builder setOutputFormat(int);
+    method public androidx.camera.core.ImageCapture.Builder setPostviewEnabled(boolean);
+    method public androidx.camera.core.ImageCapture.Builder setPostviewResolutionSelector(androidx.camera.core.resolutionselector.ResolutionSelector);
+    method public androidx.camera.core.ImageCapture.Builder setResolutionSelector(androidx.camera.core.resolutionselector.ResolutionSelector);
+    method public androidx.camera.core.ImageCapture.Builder setScreenFlash(androidx.camera.core.ImageCapture.ScreenFlash);
+    method @Deprecated public androidx.camera.core.ImageCapture.Builder setTargetAspectRatio(int);
+    method public androidx.camera.core.ImageCapture.Builder setTargetName(String);
+    method @Deprecated public androidx.camera.core.ImageCapture.Builder setTargetResolution(android.util.Size);
+    method public androidx.camera.core.ImageCapture.Builder setTargetRotation(int);
+  }
+
+  public static final class ImageCapture.Metadata {
+    ctor public ImageCapture.Metadata();
+    method public android.location.Location? getLocation();
+    method public boolean isReversedHorizontal();
+    method public boolean isReversedVertical();
+    method public void setLocation(android.location.Location?);
+    method public void setReversedHorizontal(boolean);
+    method public void setReversedVertical(boolean);
+  }
+
+  public abstract static class ImageCapture.OnImageCapturedCallback {
+    ctor public ImageCapture.OnImageCapturedCallback();
+    method public void onCaptureProcessProgressed(int);
+    method public void onCaptureStarted();
+    method public void onCaptureSuccess(androidx.camera.core.ImageProxy);
+    method public void onError(androidx.camera.core.ImageCaptureException);
+    method public void onPostviewBitmapAvailable(android.graphics.Bitmap);
+  }
+
+  public static interface ImageCapture.OnImageSavedCallback {
+    method public default void onCaptureProcessProgressed(int);
+    method public default void onCaptureStarted();
+    method public void onError(androidx.camera.core.ImageCaptureException);
+    method public void onImageSaved(androidx.camera.core.ImageCapture.OutputFileResults);
+    method public default void onPostviewBitmapAvailable(android.graphics.Bitmap);
+  }
+
+  public static final class ImageCapture.OutputFileOptions {
+  }
+
+  public static final class ImageCapture.OutputFileOptions.Builder {
+    ctor public ImageCapture.OutputFileOptions.Builder(android.content.ContentResolver, android.net.Uri, android.content.ContentValues);
+    ctor public ImageCapture.OutputFileOptions.Builder(java.io.File);
+    ctor public ImageCapture.OutputFileOptions.Builder(java.io.OutputStream);
+    method public androidx.camera.core.ImageCapture.OutputFileOptions build();
+    method public androidx.camera.core.ImageCapture.OutputFileOptions.Builder setMetadata(androidx.camera.core.ImageCapture.Metadata);
+  }
+
+  public static class ImageCapture.OutputFileResults {
+    method public android.net.Uri? getSavedUri();
+  }
+
+  public static interface ImageCapture.ScreenFlash {
+    method @UiThread public void apply(long, androidx.camera.core.ImageCapture.ScreenFlashListener);
+    method @UiThread public void clear();
+  }
+
+  public static interface ImageCapture.ScreenFlashListener {
+    method public void onCompleted();
+  }
+
+  public interface ImageCaptureCapabilities {
+    method @SuppressCompatibility @androidx.camera.core.ExperimentalImageCaptureOutputFormat public java.util.Set<java.lang.Integer!> getSupportedOutputFormats();
+    method public boolean isCaptureProcessProgressSupported();
+    method public boolean isPostviewSupported();
+  }
+
+  public class ImageCaptureException extends java.lang.Exception {
+    ctor public ImageCaptureException(int, String, Throwable?);
+    method public int getImageCaptureError();
+  }
+
+  public final class ImageCaptureExtKt {
+    method public static suspend Object? takePicture(androidx.camera.core.ImageCapture, androidx.camera.core.ImageCapture.OutputFileOptions outputFileOptions, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onCaptureStarted, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit>? onCaptureProcessProgressed, optional kotlin.jvm.functions.Function1<? super android.graphics.Bitmap,kotlin.Unit>? onPostviewBitmapAvailable, kotlin.coroutines.Continuation<? super androidx.camera.core.ImageCapture.OutputFileResults>);
+    method public static suspend Object? takePicture(androidx.camera.core.ImageCapture, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onCaptureStarted, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit>? onCaptureProcessProgressed, optional kotlin.jvm.functions.Function1<? super android.graphics.Bitmap,kotlin.Unit>? onPostviewBitmapAvailable, kotlin.coroutines.Continuation<? super androidx.camera.core.ImageProxy>);
+  }
+
+  public class ImageCaptureLatencyEstimate {
+    ctor public ImageCaptureLatencyEstimate(long, long);
+    method public long getCaptureLatencyMillis();
+    method public long getProcessingLatencyMillis();
+    method public long getTotalCaptureLatencyMillis();
+    field public static final long UNDEFINED_CAPTURE_LATENCY = -1L; // 0xffffffffffffffffL
+    field public static final androidx.camera.core.ImageCaptureLatencyEstimate UNDEFINED_IMAGE_CAPTURE_LATENCY;
+    field public static final long UNDEFINED_PROCESSING_LATENCY = -1L; // 0xffffffffffffffffL
+  }
+
+  public interface ImageInfo {
+    method public int getRotationDegrees();
+    method public default android.graphics.Matrix getSensorToBufferTransformMatrix();
+    method public long getTimestamp();
+  }
+
+  public interface ImageProcessor {
+    method public androidx.camera.core.ImageProcessor.Response process(androidx.camera.core.ImageProcessor.Request) throws androidx.camera.core.ProcessingException;
+  }
+
+  public static interface ImageProcessor.Request {
+    method public androidx.camera.core.ImageProxy getInputImage();
+    method public int getOutputFormat();
+  }
+
+  public static interface ImageProcessor.Response {
+    method public androidx.camera.core.ImageProxy getOutputImage();
+  }
+
+  public interface ImageProxy extends java.lang.AutoCloseable {
+    method public void close();
+    method public android.graphics.Rect getCropRect();
+    method public int getFormat();
+    method public int getHeight();
+    method @SuppressCompatibility @androidx.camera.core.ExperimentalGetImage public android.media.Image? getImage();
+    method public androidx.camera.core.ImageInfo getImageInfo();
+    method public androidx.camera.core.ImageProxy.PlaneProxy![] getPlanes();
+    method public int getWidth();
+    method public void setCropRect(android.graphics.Rect?);
+    method public default android.graphics.Bitmap toBitmap();
+  }
+
+  public static interface ImageProxy.PlaneProxy {
+    method public java.nio.ByteBuffer getBuffer();
+    method public int getPixelStride();
+    method public int getRowStride();
+  }
+
+  public class InitializationException extends java.lang.Exception {
+    ctor public InitializationException(String?);
+    ctor public InitializationException(String?, Throwable?);
+    ctor public InitializationException(Throwable?);
+  }
+
+  public class MeteringPoint {
+    method public float getSize();
+  }
+
+  public abstract class MeteringPointFactory {
+    method public final androidx.camera.core.MeteringPoint createPoint(float, float);
+    method public final androidx.camera.core.MeteringPoint createPoint(float, float, float);
+    method public static float getDefaultPointSize();
+  }
+
+  public class MirrorMode {
+    field public static final int MIRROR_MODE_OFF = 0; // 0x0
+    field public static final int MIRROR_MODE_ON = 1; // 0x1
+    field public static final int MIRROR_MODE_ON_FRONT_ONLY = 2; // 0x2
+  }
+
+  public final class Preview extends androidx.camera.core.UseCase {
+    method public androidx.camera.core.DynamicRange getDynamicRange();
+    method public static androidx.camera.core.PreviewCapabilities getPreviewCapabilities(androidx.camera.core.CameraInfo);
+    method public androidx.camera.core.ResolutionInfo? getResolutionInfo();
+    method public androidx.camera.core.resolutionselector.ResolutionSelector? getResolutionSelector();
+    method public android.util.Range<java.lang.Integer!> getTargetFrameRate();
+    method public int getTargetRotation();
+    method public boolean isPreviewStabilizationEnabled();
+    method @UiThread public void setSurfaceProvider(androidx.camera.core.Preview.SurfaceProvider?);
+    method @UiThread public void setSurfaceProvider(java.util.concurrent.Executor, androidx.camera.core.Preview.SurfaceProvider?);
+    method public void setTargetRotation(int);
+  }
+
+  public static final class Preview.Builder implements androidx.camera.core.ExtendableBuilder<androidx.camera.core.Preview!> {
+    ctor public Preview.Builder();
+    method public androidx.camera.core.Preview build();
+    method public androidx.camera.core.Preview.Builder setDynamicRange(androidx.camera.core.DynamicRange);
+    method @SuppressCompatibility @androidx.camera.core.ExperimentalMirrorMode public androidx.camera.core.Preview.Builder setMirrorMode(int);
+    method public androidx.camera.core.Preview.Builder setPreviewStabilizationEnabled(boolean);
+    method public androidx.camera.core.Preview.Builder setResolutionSelector(androidx.camera.core.resolutionselector.ResolutionSelector);
+    method @Deprecated public androidx.camera.core.Preview.Builder setTargetAspectRatio(int);
+    method public androidx.camera.core.Preview.Builder setTargetFrameRate(android.util.Range<java.lang.Integer!>);
+    method public androidx.camera.core.Preview.Builder setTargetName(String);
+    method @Deprecated public androidx.camera.core.Preview.Builder setTargetResolution(android.util.Size);
+    method public androidx.camera.core.Preview.Builder setTargetRotation(int);
+  }
+
+  public static interface Preview.SurfaceProvider {
+    method public void onSurfaceRequested(androidx.camera.core.SurfaceRequest);
+  }
+
+  public interface PreviewCapabilities {
+    method public boolean isStabilizationSupported();
+  }
+
+  public class ProcessingException extends java.lang.Exception {
+    ctor public ProcessingException();
+  }
+
+  public class ResolutionInfo {
+    ctor public ResolutionInfo(android.util.Size, android.graphics.Rect, int);
+    method public android.graphics.Rect getCropRect();
+    method public android.util.Size getResolution();
+    method public int getRotationDegrees();
+  }
+
+  @SuppressCompatibility @androidx.camera.core.ExperimentalRetryPolicy public interface RetryPolicy {
+    method public static long getDefaultRetryTimeoutInMillis();
+    method public default long getTimeoutInMillis();
+    method public androidx.camera.core.RetryPolicy.RetryConfig onRetryDecisionRequested(androidx.camera.core.RetryPolicy.ExecutionState);
+    field public static final androidx.camera.core.RetryPolicy DEFAULT;
+    field public static final androidx.camera.core.RetryPolicy NEVER;
+    field public static final androidx.camera.core.RetryPolicy RETRY_UNAVAILABLE_CAMERA;
+  }
+
+  @SuppressCompatibility @androidx.camera.core.ExperimentalRetryPolicy public static final class RetryPolicy.Builder {
+    ctor public RetryPolicy.Builder(androidx.camera.core.RetryPolicy);
+    method public androidx.camera.core.RetryPolicy build();
+    method public androidx.camera.core.RetryPolicy.Builder setTimeoutInMillis(long);
+  }
+
+  @SuppressCompatibility @androidx.camera.core.ExperimentalRetryPolicy public static interface RetryPolicy.ExecutionState {
+    method public Throwable? getCause();
+    method public long getExecutedTimeInMillis();
+    method public int getNumOfAttempts();
+    method public int getStatus();
+    field public static final int STATUS_CAMERA_UNAVAILABLE = 2; // 0x2
+    field public static final int STATUS_CONFIGURATION_FAIL = 1; // 0x1
+    field public static final int STATUS_UNKNOWN_ERROR = 0; // 0x0
+  }
+
+  @SuppressCompatibility @androidx.camera.core.ExperimentalRetryPolicy public static final class RetryPolicy.RetryConfig {
+    method public static long getDefaultRetryDelayInMillis();
+    method public long getRetryDelayInMillis();
+    method public boolean shouldRetry();
+    field public static final androidx.camera.core.RetryPolicy.RetryConfig DEFAULT_DELAY_RETRY;
+    field public static final androidx.camera.core.RetryPolicy.RetryConfig MINI_DELAY_RETRY;
+    field public static final androidx.camera.core.RetryPolicy.RetryConfig NOT_RETRY;
+  }
+
+  @SuppressCompatibility @androidx.camera.core.ExperimentalRetryPolicy public static final class RetryPolicy.RetryConfig.Builder {
+    ctor public RetryPolicy.RetryConfig.Builder();
+    method public androidx.camera.core.RetryPolicy.RetryConfig build();
+    method public androidx.camera.core.RetryPolicy.RetryConfig.Builder setRetryDelayInMillis(@IntRange(from=100, to=2000) long);
+    method public androidx.camera.core.RetryPolicy.RetryConfig.Builder setShouldRetry(boolean);
+  }
+
+  public class SurfaceOrientedMeteringPointFactory extends androidx.camera.core.MeteringPointFactory {
+    ctor public SurfaceOrientedMeteringPointFactory(float, float);
+    ctor public SurfaceOrientedMeteringPointFactory(float, float, androidx.camera.core.UseCase);
+  }
+
+  public interface SurfaceOutput extends java.io.Closeable {
+    method public void close();
+    method public default android.graphics.Matrix getSensorToBufferTransform();
+    method public android.util.Size getSize();
+    method public android.view.Surface getSurface(java.util.concurrent.Executor, androidx.core.util.Consumer<androidx.camera.core.SurfaceOutput.Event!>);
+    method public int getTargets();
+    method public void updateTransformMatrix(float[], float[]);
+  }
+
+  @com.google.auto.value.AutoValue public abstract static class SurfaceOutput.Event {
+    method public abstract int getEventCode();
+    method public abstract androidx.camera.core.SurfaceOutput getSurfaceOutput();
+    field public static final int EVENT_REQUEST_CLOSE = 0; // 0x0
+  }
+
+  public interface SurfaceProcessor {
+    method public void onInputSurface(androidx.camera.core.SurfaceRequest) throws androidx.camera.core.ProcessingException;
+    method public void onOutputSurface(androidx.camera.core.SurfaceOutput) throws androidx.camera.core.ProcessingException;
+  }
+
+  public final class SurfaceRequest {
+    method public void addRequestCancellationListener(java.util.concurrent.Executor, Runnable);
+    method public void clearTransformationInfoListener();
+    method public androidx.camera.core.DynamicRange getDynamicRange();
+    method public android.util.Size getResolution();
+    method public boolean invalidate();
+    method public void provideSurface(android.view.Surface, java.util.concurrent.Executor, androidx.core.util.Consumer<androidx.camera.core.SurfaceRequest.Result!>);
+    method public void setTransformationInfoListener(java.util.concurrent.Executor, androidx.camera.core.SurfaceRequest.TransformationInfoListener);
+    method public boolean willNotProvideSurface();
+  }
+
+  @com.google.auto.value.AutoValue public abstract static class SurfaceRequest.Result {
+    method public abstract int getResultCode();
+    method public abstract android.view.Surface getSurface();
+    field public static final int RESULT_INVALID_SURFACE = 2; // 0x2
+    field public static final int RESULT_REQUEST_CANCELLED = 1; // 0x1
+    field public static final int RESULT_SURFACE_ALREADY_PROVIDED = 3; // 0x3
+    field public static final int RESULT_SURFACE_USED_SUCCESSFULLY = 0; // 0x0
+    field public static final int RESULT_WILL_NOT_PROVIDE_SURFACE = 4; // 0x4
+  }
+
+  @com.google.auto.value.AutoValue public abstract static class SurfaceRequest.TransformationInfo {
+    method public abstract android.graphics.Rect getCropRect();
+    method public abstract int getRotationDegrees();
+    method public abstract android.graphics.Matrix getSensorToBufferTransform();
+    method public abstract boolean hasCameraTransform();
+    method public abstract boolean isMirroring();
+  }
+
+  public static interface SurfaceRequest.TransformationInfoListener {
+    method public void onTransformationInfoUpdate(androidx.camera.core.SurfaceRequest.TransformationInfo);
+  }
+
+  public class TorchState {
+    field public static final int OFF = 0; // 0x0
+    field public static final int ON = 1; // 0x1
+  }
+
+  public abstract class UseCase {
+    method public static int snapToSurfaceRotation(@IntRange(from=0, to=359) int);
+  }
+
+  public final class UseCaseGroup {
+    method public java.util.List<androidx.camera.core.CameraEffect!> getEffects();
+    method public java.util.List<androidx.camera.core.UseCase!> getUseCases();
+    method public androidx.camera.core.ViewPort? getViewPort();
+  }
+
+  public static final class UseCaseGroup.Builder {
+    ctor public UseCaseGroup.Builder();
+    method public androidx.camera.core.UseCaseGroup.Builder addEffect(androidx.camera.core.CameraEffect);
+    method public androidx.camera.core.UseCaseGroup.Builder addUseCase(androidx.camera.core.UseCase);
+    method public androidx.camera.core.UseCaseGroup build();
+    method public androidx.camera.core.UseCaseGroup.Builder setViewPort(androidx.camera.core.ViewPort);
+  }
+
+  public final class ViewPort {
+    method public android.util.Rational getAspectRatio();
+    method public int getLayoutDirection();
+    method public int getRotation();
+    method public int getScaleType();
+    field public static final int FILL_CENTER = 1; // 0x1
+    field public static final int FILL_END = 2; // 0x2
+    field public static final int FILL_START = 0; // 0x0
+    field public static final int FIT = 3; // 0x3
+  }
+
+  public static final class ViewPort.Builder {
+    ctor public ViewPort.Builder(android.util.Rational, int);
+    method public androidx.camera.core.ViewPort build();
+    method public androidx.camera.core.ViewPort.Builder setLayoutDirection(int);
+    method public androidx.camera.core.ViewPort.Builder setScaleType(int);
+  }
+
+  public interface ZoomState {
+    method public float getLinearZoom();
+    method public float getMaxZoomRatio();
+    method public float getMinZoomRatio();
+    method public float getZoomRatio();
+  }
+
+}
+
+package androidx.camera.core.resolutionselector {
+
+  public final class AspectRatioStrategy {
+    ctor public AspectRatioStrategy(int, int);
+    method public int getFallbackRule();
+    method public int getPreferredAspectRatio();
+    field public static final int FALLBACK_RULE_AUTO = 1; // 0x1
+    field public static final int FALLBACK_RULE_NONE = 0; // 0x0
+    field public static final androidx.camera.core.resolutionselector.AspectRatioStrategy RATIO_16_9_FALLBACK_AUTO_STRATEGY;
+    field public static final androidx.camera.core.resolutionselector.AspectRatioStrategy RATIO_4_3_FALLBACK_AUTO_STRATEGY;
+  }
+
+  public interface ResolutionFilter {
+    method public java.util.List<android.util.Size!> filter(java.util.List<android.util.Size!>, int);
+  }
+
+  public final class ResolutionSelector {
+    method public int getAllowedResolutionMode();
+    method public androidx.camera.core.resolutionselector.AspectRatioStrategy getAspectRatioStrategy();
+    method public androidx.camera.core.resolutionselector.ResolutionFilter? getResolutionFilter();
+    method public androidx.camera.core.resolutionselector.ResolutionStrategy? getResolutionStrategy();
+    field public static final int PREFER_CAPTURE_RATE_OVER_HIGHER_RESOLUTION = 0; // 0x0
+    field public static final int PREFER_HIGHER_RESOLUTION_OVER_CAPTURE_RATE = 1; // 0x1
+  }
+
+  public static final class ResolutionSelector.Builder {
+    ctor public ResolutionSelector.Builder();
+    method public androidx.camera.core.resolutionselector.ResolutionSelector build();
+    method public androidx.camera.core.resolutionselector.ResolutionSelector.Builder setAllowedResolutionMode(int);
+    method public androidx.camera.core.resolutionselector.ResolutionSelector.Builder setAspectRatioStrategy(androidx.camera.core.resolutionselector.AspectRatioStrategy);
+    method public androidx.camera.core.resolutionselector.ResolutionSelector.Builder setResolutionFilter(androidx.camera.core.resolutionselector.ResolutionFilter);
+    method public androidx.camera.core.resolutionselector.ResolutionSelector.Builder setResolutionStrategy(androidx.camera.core.resolutionselector.ResolutionStrategy);
+  }
+
+  public final class ResolutionStrategy {
+    ctor public ResolutionStrategy(android.util.Size, int);
+    method public android.util.Size? getBoundSize();
+    method public int getFallbackRule();
+    field public static final int FALLBACK_RULE_CLOSEST_HIGHER = 2; // 0x2
+    field public static final int FALLBACK_RULE_CLOSEST_HIGHER_THEN_LOWER = 1; // 0x1
+    field public static final int FALLBACK_RULE_CLOSEST_LOWER = 4; // 0x4
+    field public static final int FALLBACK_RULE_CLOSEST_LOWER_THEN_HIGHER = 3; // 0x3
+    field public static final int FALLBACK_RULE_NONE = 0; // 0x0
+    field public static final androidx.camera.core.resolutionselector.ResolutionStrategy HIGHEST_AVAILABLE_STRATEGY;
+  }
+
+}
+
diff --git a/camera/camera-core/build.gradle b/camera/camera-core/build.gradle
index de6ce16..8349b71 100644
--- a/camera/camera-core/build.gradle
+++ b/camera/camera-core/build.gradle
@@ -41,6 +41,7 @@
     implementation("androidx.concurrent:concurrent-futures:1.1.0")
     implementation("androidx.concurrent:concurrent-futures-ktx:1.1.0")
     implementation("androidx.lifecycle:lifecycle-common:2.1.0")
+    implementation("androidx.tracing:tracing:1.2.0")
     implementation(libs.autoValueAnnotations)
     androidTestImplementation project(path: ':camera:camera-camera2')
     compileOnly(project(":external:libyuv"))
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/FakeOtherUseCase.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/FakeOtherUseCase.java
index 80e6ea3..daea541 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/FakeOtherUseCase.java
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/FakeOtherUseCase.java
@@ -75,8 +75,10 @@
 
     @Override
     @NonNull
-    protected StreamSpec onSuggestedStreamSpecUpdated(@NonNull StreamSpec suggestedStreamSpec) {
-        return suggestedStreamSpec;
+    protected StreamSpec onSuggestedStreamSpecUpdated(
+            @NonNull StreamSpec primaryStreamSpec,
+            @Nullable StreamSpec secondaryStreamSpec) {
+        return primaryStreamSpec;
     }
 
     /** Returns true if {@link #onUnbind()} has been called previously. */
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageAnalysisDeviceTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageAnalysisDeviceTest.java
index 2b4f2ff..955e0de 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageAnalysisDeviceTest.java
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageAnalysisDeviceTest.java
@@ -49,7 +49,7 @@
         ImageAnalysis useCase = new ImageAnalysis.Builder().setBackpressureStrategy(
                 STRATEGY_KEEP_ONLY_LATEST).build();
 
-        useCase.bindToCamera(mMockCameraInternal, null, null);
+        useCase.bindToCamera(mMockCameraInternal, null, null, null);
 
         useCase.setAnalyzer(CameraXExecutors.mainThreadExecutor(), mMockAnalyzer);
 
@@ -63,7 +63,7 @@
         ImageAnalysis useCase = new ImageAnalysis.Builder().setBackpressureStrategy(
                 STRATEGY_KEEP_ONLY_LATEST).build();
 
-        useCase.bindToCamera(mMockCameraInternal, null, null);
+        useCase.bindToCamera(mMockCameraInternal, null, null, null);
         useCase.setAnalyzer(CameraXExecutors.mainThreadExecutor(), mMockAnalyzer);
         useCase.clearAnalyzer();
 
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageCaptureTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageCaptureTest.java
index f452482..263b7a5 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageCaptureTest.java
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageCaptureTest.java
@@ -520,6 +520,63 @@
         assertThat(resolutionInfo.getCropRect()).isEqualTo(new Rect(0, 60, 640, 420));
     }
 
+    @SdkSuppress(minSdkVersion = 23)
+    @Test
+    public void streamSpecZslNotDisabled_zslConfigAdded() {
+        ImageCapture imageCapture = new ImageCapture.Builder().setCaptureMode(
+                ImageCapture.CAPTURE_MODE_ZERO_SHUTTER_LAG).build();
+
+        mInstrumentation.runOnMainSync(() -> {
+                    try {
+                        mCameraUseCaseAdapter.addUseCases(Collections.singletonList(imageCapture));
+                    } catch (CameraUseCaseAdapter.CameraException e) {
+                    }
+                }
+        );
+
+        FakeCameraControl fakeCameraControl =
+                getCameraControlImplementation(mCameraUseCaseAdapter.getCameraControl());
+
+        assertThat(fakeCameraControl.isZslConfigAdded()).isTrue();
+    }
+
+    @SdkSuppress(minSdkVersion = 23)
+    @Test
+    public void streamSpecZslDisabled_zslConfigNotAdded() {
+        FakeCamera fakeCamera = new FakeCamera("fakeCameraId");
+
+        FakeCameraDeviceSurfaceManager fakeCameraDeviceSurfaceManager =
+                new FakeCameraDeviceSurfaceManager();
+        fakeCameraDeviceSurfaceManager.setSuggestedStreamSpec("fakeCameraId",
+                ImageCaptureConfig.class,
+                StreamSpec.builder(new Size(640, 480))
+                        .setZslDisabled(true)
+                        .build());
+
+        UseCaseConfigFactory useCaseConfigFactory = new FakeUseCaseConfigFactory();
+        mCameraUseCaseAdapter = new CameraUseCaseAdapter(
+                fakeCamera,
+                new FakeCameraCoordinator(),
+                fakeCameraDeviceSurfaceManager,
+                useCaseConfigFactory);
+
+        ImageCapture imageCapture = new ImageCapture.Builder().setCaptureMode(
+                ImageCapture.CAPTURE_MODE_ZERO_SHUTTER_LAG).build();
+
+        mInstrumentation.runOnMainSync(() -> {
+                    try {
+                        mCameraUseCaseAdapter.addUseCases(Collections.singletonList(imageCapture));
+                    } catch (CameraUseCaseAdapter.CameraException e) {
+                    }
+                }
+        );
+
+        FakeCameraControl fakeCameraControl =
+                getCameraControlImplementation(mCameraUseCaseAdapter.getCameraControl());
+
+        assertThat(fakeCameraControl.isZslConfigAdded()).isFalse();
+    }
+
     private boolean hasJpegQuality(List<CaptureConfig> captureConfigs, int jpegQuality) {
         for (CaptureConfig captureConfig : captureConfigs) {
             if (jpegQuality == captureConfig.getImplementationOptions().retrieveOption(
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseTest.kt b/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseTest.kt
index 2271b6f..eb99fa1d 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseTest.kt
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseTest.kt
@@ -89,7 +89,7 @@
     fun getAttachedSessionConfig() {
         val testUseCase = createFakeUseCase()
         val sessionToAttach = SessionConfig.Builder().build()
-        testUseCase.updateSessionConfig(sessionToAttach)
+        testUseCase.updateSessionConfig(listOf(sessionToAttach))
         val attachedSession = testUseCase.sessionConfig
         assertThat(attachedSession).isEqualTo(sessionToAttach)
     }
@@ -97,7 +97,7 @@
     @Test
     fun removeListener() {
         val testUseCase = createFakeUseCase()
-        testUseCase.bindToCamera(fakeCamera, null, null)
+        testUseCase.bindToCamera(fakeCamera, null, null, null)
         testUseCase.unbindFromCamera(fakeCamera)
         testUseCase.notifyActive()
         assertThat(fakeCamera.useCaseActiveHistory).isEmpty()
@@ -106,7 +106,7 @@
     @Test
     fun notifyActiveState() {
         val testUseCase = createFakeUseCase()
-        testUseCase.bindToCamera(fakeCamera, null, null)
+        testUseCase.bindToCamera(fakeCamera, null, null, null)
         testUseCase.notifyActive()
         assertThat(fakeCamera.useCaseActiveHistory[0]).isEqualTo(testUseCase)
     }
@@ -114,7 +114,7 @@
     @Test
     fun notifyInactiveState() {
         val testUseCase = createFakeUseCase()
-        testUseCase.bindToCamera(fakeCamera, null, null)
+        testUseCase.bindToCamera(fakeCamera, null, null, null)
         testUseCase.notifyInactive()
         assertThat(fakeCamera.useCaseInactiveHistory[0]).isEqualTo(testUseCase)
     }
@@ -122,7 +122,7 @@
     @Test
     fun notifyUpdatedSettings() {
         val testUseCase = FakeUseCase()
-        testUseCase.bindToCamera(fakeCamera, null, null)
+        testUseCase.bindToCamera(fakeCamera, null, null, null)
         testUseCase.notifyUpdated()
         assertThat(fakeCamera.useCaseUpdateHistory[0]).isEqualTo(testUseCase)
     }
@@ -130,7 +130,7 @@
     @Test
     fun notifyResetUseCase() {
         val testUseCase = FakeUseCase()
-        testUseCase.bindToCamera(fakeCamera, null, null)
+        testUseCase.bindToCamera(fakeCamera, null, null, null)
         testUseCase.notifyReset()
         assertThat(fakeCamera.useCaseResetHistory[0]).isEqualTo(testUseCase)
     }
@@ -149,9 +149,9 @@
     @Test
     fun attachedSurfaceResolutionCanBeReset_whenOnDetach() {
         val testUseCase = FakeUseCase()
-        testUseCase.updateSuggestedStreamSpec(TEST_STREAM_SPEC)
+        testUseCase.updateSuggestedStreamSpec(TEST_STREAM_SPEC, null)
         assertThat(testUseCase.attachedSurfaceResolution).isNotNull()
-        testUseCase.bindToCamera(fakeCamera, null, null)
+        testUseCase.bindToCamera(fakeCamera, null, null, null)
         testUseCase.unbindFromCamera(fakeCamera)
         assertThat(testUseCase.attachedSurfaceResolution).isNull()
     }
@@ -159,9 +159,9 @@
     @Test
     fun attachedStreamSpecCanBeReset_whenOnDetach() {
         val testUseCase = FakeUseCase()
-        testUseCase.updateSuggestedStreamSpec(TEST_STREAM_SPEC)
+        testUseCase.updateSuggestedStreamSpec(TEST_STREAM_SPEC, null)
         assertThat(testUseCase.attachedStreamSpec).isNotNull()
-        testUseCase.bindToCamera(fakeCamera, null, null)
+        testUseCase.bindToCamera(fakeCamera, null, null, null)
         testUseCase.unbindFromCamera(fakeCamera)
         assertThat(testUseCase.attachedStreamSpec).isNull()
     }
@@ -171,7 +171,7 @@
         val testUseCase = FakeUseCase()
         testUseCase.setViewPortCropRect(Rect(0, 0, 640, 480))
         assertThat(testUseCase.viewPortCropRect).isNotNull()
-        testUseCase.bindToCamera(fakeCamera, null, null)
+        testUseCase.bindToCamera(fakeCamera, null, null, null)
         testUseCase.unbindFromCamera(fakeCamera)
         assertThat(testUseCase.viewPortCropRect).isNull()
     }
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/processing/DefaultSurfaceProcessorTest.kt b/camera/camera-core/src/androidTest/java/androidx/camera/core/processing/DefaultSurfaceProcessorTest.kt
index 29ca6b2..c70ec60 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/processing/DefaultSurfaceProcessorTest.kt
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/processing/DefaultSurfaceProcessorTest.kt
@@ -28,6 +28,7 @@
 import androidx.camera.core.DynamicRange
 import androidx.camera.core.ImageProxy
 import androidx.camera.core.ImageReaderProxys
+import androidx.camera.core.SurfaceOutput
 import androidx.camera.core.SurfaceRequest
 import androidx.camera.core.impl.DeferrableSurface
 import androidx.camera.core.impl.ImageFormatConstants.INTERNAL_DEFINED_IMAGE_FORMAT_PRIVATE
@@ -78,13 +79,15 @@
         #extension GL_OES_EGL_image_external : require
         precision mediump float;
         uniform samplerExternalOES %s;
+        uniform float uAlphaScale;
         varying vec2 %s;
         void main() {
           vec4 sampleColor = texture2D(%s, %s);
-          gl_FragColor = vec4(sampleColor.r * 0.493 + sampleColor. g * 0.769 +
+          vec4 src = vec4(sampleColor.r * 0.493 + sampleColor. g * 0.769 +
              sampleColor.b * 0.289, sampleColor.r * 0.449 + sampleColor.g * 0.686 +
              sampleColor.b * 0.268, sampleColor.r * 0.272 + sampleColor.g * 0.534 +
              sampleColor.b * 0.131, 1.0);
+          gl_FragColor = vec4(src.rgb, src.a * uAlphaScale);
         }
         """
 
@@ -411,11 +414,14 @@
             target,
             format,
             Size(WIDTH, HEIGHT),
-            Size(WIDTH, HEIGHT),
-            Rect(0, 0, WIDTH, HEIGHT),
-            /*rotationDegrees=*/ 0,
-            /*mirroring=*/ false,
-            FakeCamera(),
+            SurfaceOutput.CameraInputInfo.of(
+                Size(WIDTH, HEIGHT),
+                Rect(0, 0, WIDTH, HEIGHT),
+                FakeCamera(),
+                /*rotationDegrees=*/ 0,
+                /*mirroring=*/ false
+            ),
+            /*secondaryCameraInputInfo=*/ null,
             Matrix()
         )
 
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/processing/OpenGlRendererTest.kt b/camera/camera-core/src/androidTest/java/androidx/camera/core/processing/OpenGlRendererTest.kt
index c45cdb0..54a2af9 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/processing/OpenGlRendererTest.kt
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/processing/OpenGlRendererTest.kt
@@ -74,13 +74,15 @@
         #extension GL_OES_EGL_image_external : require
         precision mediump float;
         uniform samplerExternalOES %s;
+        uniform float uAlphaScale;
         varying vec2 %s;
         void main() {
           vec4 sampleColor = texture2D(%s, %s);
-          gl_FragColor = vec4(sampleColor.r * 0.493 + sampleColor. g * 0.769 +
+          vec4 src = vec4(sampleColor.r * 0.493 + sampleColor. g * 0.769 +
              sampleColor.b * 0.289, sampleColor.r * 0.449 + sampleColor.g * 0.686 +
              sampleColor.b * 0.268, sampleColor.r * 0.272 + sampleColor.g * 0.534 +
              sampleColor.b * 0.131, 1.0);
+          gl_FragColor = vec4(src.rgb, src.a * uAlphaScale);
         }
         """
 
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/CameraX.java b/camera/camera-core/src/main/java/androidx/camera/core/CameraX.java
index bf8e6216..ce31f3e 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/CameraX.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/CameraX.java
@@ -51,6 +51,7 @@
 import androidx.concurrent.futures.CallbackToFutureAdapter;
 import androidx.core.os.HandlerCompat;
 import androidx.core.util.Preconditions;
+import androidx.tracing.Trace;
 
 import com.google.common.util.concurrent.ListenableFuture;
 
@@ -284,6 +285,7 @@
             @NonNull Context context,
             @NonNull CallbackToFutureAdapter.Completer<Void> completer) {
         cameraExecutor.execute(() -> {
+            Trace.beginSection("CX:initAndRetryRecursively");
             Context appContext = ContextUtil.getApplicationContext(context);
             try {
                 CameraFactory.Provider cameraFactoryProvider =
@@ -336,12 +338,19 @@
                 validateCameras(appContext, mCameraRepository, availableCamerasLimiter);
 
                 // Set completer to null if the init was successful.
+                if (attemptCount > 1) {
+                    // Reset execution trace status on success
+                    traceExecutionState(null);
+                }
                 setStateToInitialized();
                 completer.set(null);
             } catch (CameraIdListIncorrectException | InitializationException
                      | RuntimeException e) {
+                RetryPolicy.ExecutionState executionState =
+                        new CameraProviderExecutionState(startMs, attemptCount, e);
                 RetryPolicy.RetryConfig retryConfig = mRetryPolicy.onRetryDecisionRequested(
-                        new CameraProviderExecutionState(startMs, attemptCount, e));
+                        executionState);
+                traceExecutionState(executionState);
                 if (retryConfig.shouldRetry() && attemptCount < Integer.MAX_VALUE) {
                     Logger.w(TAG, "Retry init. Start time " + startMs + " current time "
                             + SystemClock.elapsedRealtime(), e);
@@ -375,6 +384,8 @@
                         completer.setException(new InitializationException(e));
                     }
                 }
+            } finally {
+                Trace.endSection();
             }
         });
     }
@@ -522,4 +533,11 @@
          */
         SHUTDOWN
     }
+
+    private void traceExecutionState(@Nullable RetryPolicy.ExecutionState state) {
+        if (Trace.isEnabled()) {
+            int status = state != null ? state.getStatus() : -1;
+            Trace.setCounter("CX:CameraProvider-RetryStatus", status);
+        }
+    }
 }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java
index 2bb4661..2fe4b2e 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java
@@ -222,6 +222,8 @@
 
     @Nullable
     private DeferrableSurface mDeferrableSurface;
+    @Nullable
+    private SessionConfig.CloseableErrorListener mCloseableErrorListener;
 
     /**
      * Creates a new image analysis use case from the given configuration.
@@ -427,22 +429,28 @@
                 null,
                 MirrorMode.MIRROR_MODE_UNSPECIFIED);
 
-        sessionConfigBuilder.addErrorListener((sessionConfig, error) -> {
-            clearPipeline();
-            // Clear cache so app won't get a outdated image.
-            mImageAnalysisAbstractAnalyzer.clearCache();
-            // Ensure the attached camera has not changed before resetting.
-            // TODO(b/143915543): Ensure this never gets called by a camera that is not attached
-            //  to this use case so we don't need to do this check.
-            if (isCurrentCamera(cameraId)) {
-                // Only reset the pipeline when the bound camera is the same.
-                SessionConfig.Builder errorSessionConfigBuilder = createPipeline(cameraId, config,
-                        streamSpec);
-                updateSessionConfig(errorSessionConfigBuilder.build());
+        if (mCloseableErrorListener != null) {
+            mCloseableErrorListener.close();
+        }
+        mCloseableErrorListener = new SessionConfig.CloseableErrorListener(
+                (sessionConfig, error) -> {
+                    // Do nothing when the use case has been unbound.
+                    if (getCamera() == null) {
+                        return;
+                    }
 
-                notifyReset();
-            }
-        });
+                    clearPipeline();
+                    // Clear cache so app won't get a outdated image.
+                    mImageAnalysisAbstractAnalyzer.clearCache();
+                    // Only reset the pipeline when the bound camera is the same.
+                    mSessionConfigBuilder = createPipeline(getCameraId(),
+                            (ImageAnalysisConfig) getCurrentConfig(),
+                            Preconditions.checkNotNull(getAttachedStreamSpec()));
+                    updateSessionConfig(List.of(mSessionConfigBuilder.build()));
+                    notifyReset();
+                });
+
+        sessionConfigBuilder.setErrorListener(mCloseableErrorListener);
 
         return sessionConfigBuilder;
     }
@@ -453,6 +461,13 @@
     @SuppressWarnings("WeakerAccess") /* synthetic accessor */
     void clearPipeline() {
         Threads.checkMainThread();
+
+        // Closes the old error listener
+        if (mCloseableErrorListener != null) {
+            mCloseableErrorListener.close();
+            mCloseableErrorListener = null;
+        }
+
         if (mDeferrableSurface != null) {
             mDeferrableSurface.close();
             mDeferrableSurface = null;
@@ -770,14 +785,16 @@
     @Override
     @RestrictTo(Scope.LIBRARY_GROUP)
     @NonNull
-    protected StreamSpec onSuggestedStreamSpecUpdated(@NonNull StreamSpec suggestedStreamSpec) {
+    protected StreamSpec onSuggestedStreamSpecUpdated(
+            @NonNull StreamSpec primaryStreamSpec,
+            @Nullable StreamSpec secondaryStreamSpec) {
         final ImageAnalysisConfig config = (ImageAnalysisConfig) getCurrentConfig();
 
         mSessionConfigBuilder = createPipeline(getCameraId(), config,
-                suggestedStreamSpec);
-        updateSessionConfig(mSessionConfigBuilder.build());
+                primaryStreamSpec);
+        updateSessionConfig(List.of(mSessionConfigBuilder.build()));
 
-        return suggestedStreamSpec;
+        return primaryStreamSpec;
     }
 
     /**
@@ -788,7 +805,7 @@
     @RestrictTo(Scope.LIBRARY_GROUP)
     protected StreamSpec onSuggestedStreamSpecImplementationOptionsUpdated(@NonNull Config config) {
         mSessionConfigBuilder.addImplementationOptions(config);
-        updateSessionConfig(mSessionConfigBuilder.build());
+        updateSessionConfig(List.of(mSessionConfigBuilder.build()));
         return getAttachedStreamSpec().toBuilder().setImplementationOptions(config).build();
     }
 
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
index d470745..5c15ced 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
@@ -371,6 +371,8 @@
     private ImagePipeline mImagePipeline;
     @Nullable
     private TakePictureManager mTakePictureManager;
+    @Nullable
+    private SessionConfig.CloseableErrorListener mCloseableErrorListener;
 
     /**
      * Creates a new image capture use case from the given configuration.
@@ -1186,16 +1188,18 @@
     @NonNull
     @Override
     @RestrictTo(Scope.LIBRARY_GROUP)
-    protected StreamSpec onSuggestedStreamSpecUpdated(@NonNull StreamSpec suggestedStreamSpec) {
+    protected StreamSpec onSuggestedStreamSpecUpdated(
+            @NonNull StreamSpec primaryStreamSpec,
+            @Nullable StreamSpec secondaryStreamSpec) {
         mSessionConfigBuilder = createPipeline(getCameraId(),
-                (ImageCaptureConfig) getCurrentConfig(), suggestedStreamSpec);
+                (ImageCaptureConfig) getCurrentConfig(), primaryStreamSpec);
 
-        updateSessionConfig(mSessionConfigBuilder.build());
+        updateSessionConfig(List.of(mSessionConfigBuilder.build()));
 
         // In order to speed up the take picture process, notifyActive at an early stage to
         // attach the session capture callback to repeating and get capture result all the time.
         notifyActive();
-        return suggestedStreamSpec;
+        return primaryStreamSpec;
     }
 
     /**
@@ -1206,7 +1210,7 @@
     @RestrictTo(Scope.LIBRARY_GROUP)
     protected StreamSpec onSuggestedStreamSpecImplementationOptionsUpdated(@NonNull Config config) {
         mSessionConfigBuilder.addImplementationOptions(config);
-        updateSessionConfig(mSessionConfigBuilder.build());
+        updateSessionConfig(List.of(mSessionConfigBuilder.build()));
         return getAttachedStreamSpec().toBuilder().setImplementationOptions(config).build();
     }
 
@@ -1315,27 +1319,35 @@
 
         SessionConfig.Builder sessionConfigBuilder =
                 mImagePipeline.createSessionConfigBuilder(streamSpec.getResolution());
-        if (Build.VERSION.SDK_INT >= 23 && getCaptureMode() == CAPTURE_MODE_ZERO_SHUTTER_LAG) {
+        if (Build.VERSION.SDK_INT >= 23
+                && getCaptureMode() == CAPTURE_MODE_ZERO_SHUTTER_LAG
+                && !streamSpec.getZslDisabled()) {
             getCameraControl().addZslConfig(sessionConfigBuilder);
         }
         if (streamSpec.getImplementationOptions() != null) {
             sessionConfigBuilder.addImplementationOptions(streamSpec.getImplementationOptions());
         }
-        sessionConfigBuilder.addErrorListener((sessionConfig, error) -> {
-            // TODO(b/143915543): Ensure this never gets called by a camera that is not attached
-            //  to this use case so we don't need to do this check.
-            if (isCurrentCamera(cameraId)) {
-                mTakePictureManager.pause();
-                clearPipeline(/*keepTakePictureManager=*/ true);
-                mSessionConfigBuilder = createPipeline(cameraId, config, streamSpec);
-                updateSessionConfig(mSessionConfigBuilder.build());
-                notifyReset();
-                mTakePictureManager.resume();
-            } else {
-                clearPipeline();
-            }
-        });
+        // Close the old error listener
+        if (mCloseableErrorListener != null) {
+            mCloseableErrorListener.close();
+        }
+        mCloseableErrorListener = new SessionConfig.CloseableErrorListener(
+                (sessionConfig, error) -> {
+                    // Do nothing when the use case has been unbound.
+                    if (getCamera() == null) {
+                        return;
+                    }
 
+                    mTakePictureManager.pause();
+                    clearPipeline(/*keepTakePictureManager=*/ true);
+                    mSessionConfigBuilder = createPipeline(getCameraId(),
+                            (ImageCaptureConfig) getCurrentConfig(),
+                            Preconditions.checkNotNull(getAttachedStreamSpec()));
+                    updateSessionConfig(List.of(mSessionConfigBuilder.build()));
+                    notifyReset();
+                    mTakePictureManager.resume();
+                });
+        sessionConfigBuilder.setErrorListener(mCloseableErrorListener);
         return sessionConfigBuilder;
     }
 
@@ -1409,7 +1421,6 @@
         return new Rect(0, 0, resolution.getWidth(), resolution.getHeight());
     }
 
-
     /**
      * Clears the pipeline without keeping the {@link TakePictureManager}.
      */
@@ -1425,6 +1436,13 @@
     private void clearPipeline(boolean keepTakePictureManager) {
         Log.d(TAG, "clearPipeline");
         checkMainThread();
+
+        // Close the old error listener
+        if (mCloseableErrorListener != null) {
+            mCloseableErrorListener.close();
+            mCloseableErrorListener = null;
+        }
+
         if (mImagePipeline != null) {
             mImagePipeline.close();
             mImagePipeline = null;
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/Logger.java b/camera/camera-core/src/main/java/androidx/camera/core/Logger.java
index 64b6110..ef4a3efa 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/Logger.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/Logger.java
@@ -97,6 +97,16 @@
     }
 
     /**
+     * Returns {@code true} if logging with the tag {@code tag} is enabled at the
+     * {@link Log#VERBOSE} level. This is true when the minimum logging level is less than or equal
+     * to {@link Log#VERBOSE}, or if the log level of {@code tag} was explicitly set to
+     * {@link Log#VERBOSE} at least.
+     */
+    public static boolean isVerboseEnabled(@NonNull String tag) {
+        return isLogLevelEnabled(truncateTag(tag), Log.VERBOSE);
+    }
+
+    /**
      * Returns {@code true} if logging with the tag {@code tag} is enabled at the {@link Log#DEBUG}
      * level. This is true when the minimum logging level is less than or equal to
      * {@link Log#DEBUG}, or if the log level of {@code tag} was explicitly set to
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/Preview.java b/camera/camera-core/src/main/java/androidx/camera/core/Preview.java
index 01e547e..a7393f9 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/Preview.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/Preview.java
@@ -199,6 +199,8 @@
 
     @Nullable
     private SurfaceProcessorNode mNode;
+    @Nullable
+    private SessionConfig.CloseableErrorListener mCloseableErrorListener;
 
     /**
      * Creates a new preview use case from the given configuration.
@@ -220,7 +222,6 @@
     @NonNull
     @MainThread
     private SessionConfig.Builder createPipeline(
-            @NonNull String cameraId,
             @NonNull PreviewConfig config,
             @NonNull StreamSpec streamSpec) {
         // Check arguments
@@ -252,7 +253,7 @@
                     singletonList(outConfig));
             SurfaceProcessorNode.Out nodeOutput = mNode.transform(nodeInput);
             SurfaceEdge appEdge = requireNonNull(nodeOutput.get(outConfig));
-            appEdge.addOnInvalidatedListener(() -> onAppEdgeInvalidated(appEdge, camera));
+            appEdge.addOnInvalidatedListener(() -> onAppEdgeInvalidated(mCameraEdge, camera));
             mCurrentSurfaceRequest = appEdge.createSurfaceRequest(camera);
             mSessionDeferrableSurface = mCameraEdge.getDeferrableSurface();
         } else {
@@ -274,17 +275,16 @@
         if (streamSpec.getImplementationOptions() != null) {
             sessionConfigBuilder.addImplementationOptions(streamSpec.getImplementationOptions());
         }
-        addCameraSurfaceAndErrorListener(sessionConfigBuilder, cameraId, config, streamSpec);
+        addCameraSurfaceAndErrorListener(sessionConfigBuilder, streamSpec);
         return sessionConfigBuilder;
     }
 
     @MainThread
-    private void onAppEdgeInvalidated(@NonNull SurfaceEdge appEdge,
+    private void onAppEdgeInvalidated(@NonNull SurfaceEdge cameraEdge,
             @NonNull CameraInternal camera) {
         checkMainThread();
         if (camera == getCamera()) {
-            mCurrentSurfaceRequest = appEdge.createSurfaceRequest(camera);
-            sendSurfaceRequest();
+            cameraEdge.invalidate();
         }
     }
 
@@ -299,6 +299,12 @@
      * Creates previously allocated {@link DeferrableSurface} include those allocated by nodes.
      */
     private void clearPipeline() {
+        // Closes the old error listener
+        if (mCloseableErrorListener != null) {
+            mCloseableErrorListener.close();
+            mCloseableErrorListener = null;
+        }
+
         DeferrableSurface cameraSurface = mSessionDeferrableSurface;
         if (cameraSurface != null) {
             cameraSurface.close();
@@ -319,8 +325,6 @@
 
     private void addCameraSurfaceAndErrorListener(
             @NonNull SessionConfig.Builder sessionConfigBuilder,
-            @NonNull String cameraId,
-            @NonNull PreviewConfig config,
             @NonNull StreamSpec streamSpec) {
         // TODO(b/245309800): Add the Surface if post-processing pipeline is used. Post-processing
         //  pipeline always provide a Surface.
@@ -336,19 +340,22 @@
                     getMirrorModeInternal());
         }
 
-        sessionConfigBuilder.addErrorListener((sessionConfig, error) -> {
-            // Ensure the attached camera has not changed before resetting.
-            // TODO(b/143915543): Ensure this never gets called by a camera that is not attached
-            //  to this use case so we don't need to do this check.
-            if (isCurrentCamera(cameraId)) {
-                // Only reset the pipeline when the bound camera is the same.
-                SessionConfig.Builder sessionConfigBuilder1 = createPipeline(cameraId, config,
-                        streamSpec);
+        if (mCloseableErrorListener != null) {
+            mCloseableErrorListener.close();
+        }
+        mCloseableErrorListener = new SessionConfig.CloseableErrorListener(
+                (sessionConfig, error) -> {
+                    // Do nothing when the use case has been unbound.
+                    if (getCamera() == null) {
+                        return;
+                    }
 
-                updateSessionConfig(sessionConfigBuilder1.build());
-                notifyReset();
-            }
-        });
+                    updateConfigAndOutput((PreviewConfig) getCurrentConfig(),
+                            getAttachedStreamSpec());
+                    notifyReset();
+                });
+
+        sessionConfigBuilder.setErrorListener(mCloseableErrorListener);
     }
 
     /**
@@ -436,7 +443,7 @@
             // case may have been detached from the camera. Either way, try updating session
             // config and let createPipeline() sends a new SurfaceRequest.
             if (getAttachedSurfaceResolution() != null) {
-                updateConfigAndOutput(getCameraId(), (PreviewConfig) getCurrentConfig(),
+                updateConfigAndOutput((PreviewConfig) getCurrentConfig(),
                         getAttachedStreamSpec());
                 notifyReset();
             }
@@ -482,10 +489,10 @@
         setSurfaceProvider(DEFAULT_SURFACE_PROVIDER_EXECUTOR, surfaceProvider);
     }
 
-    private void updateConfigAndOutput(@NonNull String cameraId, @NonNull PreviewConfig config,
+    private void updateConfigAndOutput(@NonNull PreviewConfig config,
             @NonNull StreamSpec streamSpec) {
-        mSessionConfigBuilder = createPipeline(cameraId, config, streamSpec);
-        updateSessionConfig(mSessionConfigBuilder.build());
+        mSessionConfigBuilder = createPipeline(config, streamSpec);
+        updateSessionConfig(List.of(mSessionConfigBuilder.build()));
     }
 
     /**
@@ -602,10 +609,11 @@
     @Override
     @RestrictTo(Scope.LIBRARY_GROUP)
     @NonNull
-    protected StreamSpec onSuggestedStreamSpecUpdated(@NonNull StreamSpec suggestedStreamSpec) {
-        updateConfigAndOutput(getCameraId(), (PreviewConfig) getCurrentConfig(),
-                suggestedStreamSpec);
-        return suggestedStreamSpec;
+    protected StreamSpec onSuggestedStreamSpecUpdated(
+            @NonNull StreamSpec primaryStreamSpec,
+            @Nullable StreamSpec secondaryStreamSpec) {
+        updateConfigAndOutput((PreviewConfig) getCurrentConfig(), primaryStreamSpec);
+        return primaryStreamSpec;
     }
 
     /**
@@ -616,7 +624,7 @@
     @RestrictTo(Scope.LIBRARY_GROUP)
     protected StreamSpec onSuggestedStreamSpecImplementationOptionsUpdated(@NonNull Config config) {
         mSessionConfigBuilder.addImplementationOptions(config);
-        updateSessionConfig(mSessionConfigBuilder.build());
+        updateSessionConfig(List.of(mSessionConfigBuilder.build()));
         return getAttachedStreamSpec().toBuilder().setImplementationOptions(config).build();
     }
 
@@ -687,7 +695,6 @@
      * {@link DynamicRange#UNSPECIFIED}
      *
      * @return the dynamic range set for this {@code Preview} use case.
-     *
      * @see Preview.Builder#setDynamicRange(DynamicRange)
      */
     // Internal implementation note: this method should not be used to retrieve the dynamic range
@@ -1349,7 +1356,6 @@
          *
          * @param enabled True if enable, otherwise false.
          * @return the current Builder.
-         *
          * @see PreviewCapabilities#isStabilizationSupported()
          */
         @NonNull
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/SurfaceOutput.java b/camera/camera-core/src/main/java/androidx/camera/core/SurfaceOutput.java
index 943b069..19e3143 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/SurfaceOutput.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/SurfaceOutput.java
@@ -19,6 +19,7 @@
 import static androidx.camera.core.impl.ImageFormatConstants.INTERNAL_DEFINED_IMAGE_FORMAT_PRIVATE;
 
 import android.graphics.Matrix;
+import android.graphics.Rect;
 import android.graphics.SurfaceTexture;
 import android.hardware.camera2.CameraCharacteristics;
 import android.util.Size;
@@ -26,7 +27,9 @@
 
 import androidx.annotation.IntDef;
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
+import androidx.camera.core.impl.CameraInternal;
 import androidx.core.util.Consumer;
 
 import com.google.auto.value.AutoValue;
@@ -152,6 +155,14 @@
     void updateTransformMatrix(@NonNull float[] updated, @NonNull float[] original);
 
     /**
+     * Applies an additional 4x4 transformation on the original matrix, in dual concurrent cameras.
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    default void updateTransformMatrix(
+            @NonNull float[] updated, @NonNull float[] original, boolean isPrimary) {
+    }
+
+    /**
      * Returns the sensor to image buffer transform matrix.
      *
      * <p>The value is a mapping from sensor coordinates to buffer coordinates, which is,
@@ -232,4 +243,55 @@
             return new AutoValue_SurfaceOutput_Event(code, surfaceOutput);
         }
     }
+
+    /**
+     * Camera input information for transformation matrix calculation in {@link SurfaceOutput}.
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    @AutoValue
+    abstract class CameraInputInfo {
+
+        /**
+         * Gets input size.
+         */
+        @NonNull
+        public abstract Size getInputSize();
+
+        /**
+         * Gets input crop rect.
+         */
+        @NonNull
+        public abstract Rect getInputCropRect();
+
+        /**
+         * Gets {@link CameraInternal}.
+         */
+        @Nullable
+        public abstract CameraInternal getCameraInternal();
+
+        /**
+         * Gets input rotation degrees.
+         */
+        public abstract int getRotationDegrees();
+
+        /**
+         * Gets input mirroring state.
+         */
+        public abstract boolean getMirroring();
+
+        /**
+         * Creates a {@link CameraInputInfo}.
+         */
+        @NonNull
+        public static SurfaceOutput.CameraInputInfo of(
+                @NonNull Size inputSize,
+                @NonNull Rect inputCropRect,
+                @Nullable CameraInternal cameraInternal,
+                int rotationDegrees,
+                boolean mirroring) {
+            return new AutoValue_SurfaceOutput_CameraInputInfo(
+                    inputSize, inputCropRect, cameraInternal,
+                    rotationDegrees, mirroring);
+        }
+    }
 }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/SurfaceRequest.java b/camera/camera-core/src/main/java/androidx/camera/core/SurfaceRequest.java
index b1e1431..9f33bb6 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/SurfaceRequest.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/SurfaceRequest.java
@@ -104,6 +104,7 @@
 
     private final Range<Integer> mExpectedFrameRate;
     private final CameraInternal mCamera;
+    private final boolean mIsPrimary;
 
     // For the camera to retrieve the surface from the user
     @SuppressWarnings("WeakerAccess") /*synthetic accessor */
@@ -157,9 +158,26 @@
             @NonNull DynamicRange dynamicRange,
             @NonNull Range<Integer> expectedFrameRate,
             @NonNull Runnable onInvalidated) {
+        this(resolution, camera, true, dynamicRange,
+                expectedFrameRate, onInvalidated);
+    }
+
+    /**
+     * Creates a new surface request with the given resolution, {@link Camera}, dynamic range, and
+     * expected frame rate and whether it's primary or secondary camera.
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public SurfaceRequest(
+            @NonNull Size resolution,
+            @NonNull CameraInternal camera,
+            boolean isPrimary,
+            @NonNull DynamicRange dynamicRange,
+            @NonNull Range<Integer> expectedFrameRate,
+            @NonNull Runnable onInvalidated) {
         super();
         mResolution = resolution;
         mCamera = camera;
+        mIsPrimary = isPrimary;
         mDynamicRange = dynamicRange;
         mExpectedFrameRate = expectedFrameRate;
 
@@ -373,6 +391,15 @@
     }
 
     /**
+     * Returns whether the {@link Camera} is primary or secondary in dual camera case.
+     * The value is always true for single camera case.
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public boolean isPrimary() {
+        return mIsPrimary;
+    }
+
+    /**
      * Completes the request for a {@link Surface} if it has not already been
      * completed or cancelled.
      *
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java b/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java
index 08554aaa..db40959 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java
@@ -66,6 +66,7 @@
 
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Objects;
 import java.util.Set;
 
@@ -148,6 +149,10 @@
     @GuardedBy("mCameraLock")
     private CameraInternal mCamera;
 
+    @GuardedBy("mCameraLock")
+    @Nullable
+    private CameraInternal mSecondaryCamera;
+
     @Nullable
     private CameraEffect mEffect;
 
@@ -162,6 +167,11 @@
     @NonNull
     private SessionConfig mAttachedSessionConfig = SessionConfig.defaultEmptySessionConfig();
 
+    // The currently attached session config for secondary camera in dual camera case
+    @NonNull
+    private SessionConfig mAttachedSecondarySessionConfig =
+            SessionConfig.defaultEmptySessionConfig();
+
     /**
      * Creates a named instance of the use case.
      *
@@ -512,11 +522,21 @@
      *
      */
     @RestrictTo(Scope.LIBRARY_GROUP)
-    protected void updateSessionConfig(@NonNull SessionConfig sessionConfig) {
-        mAttachedSessionConfig = sessionConfig;
-        for (DeferrableSurface surface : sessionConfig.getSurfaces()) {
-            if (surface.getContainerClass() == null) {
-                surface.setContainerClass(this.getClass());
+    protected void updateSessionConfig(@NonNull List<SessionConfig> sessionConfigs) {
+        if (sessionConfigs.isEmpty()) {
+            return;
+        }
+
+        mAttachedSessionConfig = sessionConfigs.get(0);
+        if (sessionConfigs.size() > 1) {
+            mAttachedSecondarySessionConfig = sessionConfigs.get(1);
+        }
+
+        for (SessionConfig sessionConfig : sessionConfigs) {
+            for (DeferrableSurface surface : sessionConfig.getSurfaces()) {
+                if (surface.getContainerClass() == null) {
+                    surface.setContainerClass(this.getClass());
+                }
             }
         }
     }
@@ -550,6 +570,16 @@
     }
 
     /**
+     * Get the current {@link SessionConfig} of the secondary camera in dual camera case.
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    public SessionConfig getSecondarySessionConfig() {
+        return mAttachedSecondarySessionConfig;
+    }
+
+    /**
      * Notify all {@link StateChangeCallback} that are listening to this UseCase that it has
      * transitioned to an active state.
      *
@@ -629,6 +659,18 @@
     }
 
     /**
+     * Returns the camera ID for the currently attached secondary camera, or throws an exception if
+     * no camera is attached.
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @Nullable
+    protected String getSecondaryCameraId() {
+        return getSecondaryCamera() == null ? null : getSecondaryCamera()
+                .getCameraInfoInternal().getCameraId();
+    }
+
+    /**
      * Checks whether the provided camera ID is the currently attached camera ID.
      *
      */
@@ -680,6 +722,18 @@
     }
 
     /**
+     * Returns the currently attached secondary {@link Camera} or {@code null} if none is attached.
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @Nullable
+    public CameraInternal getSecondaryCamera() {
+        synchronized (mCameraLock) {
+            return mSecondaryCamera;
+        }
+    }
+
+    /**
      * Retrieves the currently attached surface resolution.
      *
      * @return the currently attached surface resolution for the given camera id.
@@ -706,26 +760,33 @@
      *
      */
     @RestrictTo(Scope.LIBRARY_GROUP)
-    public void updateSuggestedStreamSpec(@NonNull StreamSpec suggestedStreamSpec) {
-        mAttachedStreamSpec = onSuggestedStreamSpecUpdated(suggestedStreamSpec);
+    public void updateSuggestedStreamSpec(
+            @NonNull StreamSpec primaryStreamSpec,
+            @Nullable StreamSpec secondaryStreamSpec) {
+        mAttachedStreamSpec = onSuggestedStreamSpecUpdated(
+                primaryStreamSpec, secondaryStreamSpec);
     }
 
     /**
      * Called when binding new use cases via {@code CameraX#bindToLifecycle(LifecycleOwner,
-     * CameraSelector, UseCase...)}.
+     * CameraSelector, UseCase...)} with additional information for dual cameras.
      *
      * <p>Override to create necessary objects like {@link ImageReader} depending
      * on the stream specification.
      *
-     * @param suggestedStreamSpec The suggested stream specification that depends on camera device
+     * @param primaryStreamSpec The suggested stream specification that depends on camera device
      *                            capability and what and how many use cases will be bound.
+     * @param secondaryStreamSpec The suggested stream specification for secondary camera in
+     *                            dual camera case.
      * @return The stream specification that finally used to create the SessionConfig to
      * attach to the camera device.
      */
     @RestrictTo(Scope.LIBRARY_GROUP)
     @NonNull
-    protected StreamSpec onSuggestedStreamSpecUpdated(@NonNull StreamSpec suggestedStreamSpec) {
-        return suggestedStreamSpec;
+    protected StreamSpec onSuggestedStreamSpecUpdated(
+            @NonNull StreamSpec primaryStreamSpec,
+            @Nullable StreamSpec secondaryStreamSpec) {
+        return primaryStreamSpec;
     }
 
     /**
@@ -734,6 +795,8 @@
      */
     @RestrictTo(Scope.LIBRARY_GROUP)
     public void updateSuggestedStreamSpecImplementationOptions(@NonNull Config config) {
+        // TODO(b/349823704): investigate whether we need mAttachedSecondaryStreamSpec for
+        //  StreamSharing
         mAttachedStreamSpec = onSuggestedStreamSpecImplementationOptionsUpdated(config);
     }
 
@@ -770,9 +833,9 @@
      * <p>Before a use case can receive frame data, it needs to establish association with the
      * target camera first. An implementation of {@link CameraInternal} (e.g. a lifecycle camera
      * or lifecycle-less camera) is provided when
-     * {@link #bindToCamera(CameraInternal, UseCaseConfig, UseCaseConfig)} is invoked, so that the
-     * use case can retrieve the necessary information from the camera to calculate and set up
-     * the configs.
+     * {@link #bindToCamera(CameraInternal, CameraInternal, UseCaseConfig, UseCaseConfig)} is
+     * invoked, so that the use case can retrieve the necessary information from the camera
+     * to calculate and set up the configs.
      *
      * <p>The default, extended and camera config settings are also applied to the use case config
      * in this stage. Subclasses can override {@link #onMergeConfig} to update the use case
@@ -786,11 +849,16 @@
     @SuppressLint("WrongConstant")
     @RestrictTo(Scope.LIBRARY_GROUP)
     public final void bindToCamera(@NonNull CameraInternal camera,
+            @Nullable CameraInternal secondaryCamera,
             @Nullable UseCaseConfig<?> extendedConfig,
             @Nullable UseCaseConfig<?> cameraConfig) {
         synchronized (mCameraLock) {
             mCamera = camera;
+            mSecondaryCamera = secondaryCamera;
             addStateChangeCallback(camera);
+            if (secondaryCamera != null) {
+                addStateChangeCallback(secondaryCamera);
+            }
         }
 
         mExtendedConfig = extendedConfig;
@@ -835,9 +903,15 @@
         onUnbind();
 
         synchronized (mCameraLock) {
-            checkArgument(camera == mCamera);
-            removeStateChangeCallback(mCamera);
-            mCamera = null;
+            if (camera == mCamera) {
+                removeStateChangeCallback(mCamera);
+                mCamera = null;
+            }
+
+            if (camera == mSecondaryCamera) {
+                removeStateChangeCallback(mSecondaryCamera);
+                mSecondaryCamera = null;
+            }
         }
 
         mAttachedStreamSpec = null;
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/imagecapture/ProcessingRequest.java b/camera/camera-core/src/main/java/androidx/camera/core/imagecapture/ProcessingRequest.java
index fdfb44f..35a7fc0 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/imagecapture/ProcessingRequest.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/imagecapture/ProcessingRequest.java
@@ -57,6 +57,8 @@
     private final List<Integer> mStageIds;
 
     @NonNull final ListenableFuture<Void> mCaptureFuture;
+    static final int PROGRESS_NOT_RECEIVED = -1;
+    private int mLastCaptureProcessProgressed = PROGRESS_NOT_RECEIVED;
 
     ProcessingRequest(
             @NonNull CaptureBundle captureBundle,
@@ -146,7 +148,10 @@
 
     @MainThread
     void onCaptureProcessProgressed(int progress) {
-        mCallback.onCaptureProcessProgressed(progress);
+        if (mLastCaptureProcessProgressed != progress) {
+            mLastCaptureProcessProgressed = progress;
+            mCallback.onCaptureProcessProgressed(progress);
+        }
     }
 
     /**
@@ -154,6 +159,11 @@
      */
     @MainThread
     void onImageCaptured() {
+        // If process progress has ever been sent, ensure progress 100 is sent before image sent.
+        if (mLastCaptureProcessProgressed != PROGRESS_NOT_RECEIVED) {
+            onCaptureProcessProgressed(100);
+        }
+
         mCallback.onImageCaptured();
     }
 
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraDeviceSurfaceManager.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraDeviceSurfaceManager.java
index ceed873..5788082 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraDeviceSurfaceManager.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraDeviceSurfaceManager.java
@@ -82,6 +82,7 @@
      *                                          supported output sizes list that will be given a
      *                                          suggested stream specification
      * @param isPreviewStabilizationOn          whether the preview stabilization is enabled.
+     * @param hasVideoCapture                   whether the use cases has video capture.
      * @return map of suggested stream specifications for given use cases
      * @throws IllegalStateException    if not initialized
      * @throws IllegalArgumentException if {@code newUseCaseConfigs} is an empty list, if
@@ -96,5 +97,6 @@
             @NonNull String cameraId,
             @NonNull List<AttachedSurfaceInfo> existingSurfaces,
             @NonNull Map<UseCaseConfig<?>, List<Size>> newUseCaseConfigsSupportedSizeMap,
-            boolean isPreviewStabilizationOn);
+            boolean isPreviewStabilizationOn,
+            boolean hasVideoCapture);
 }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraInternal.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraInternal.java
index 5849232..900a316 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraInternal.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraInternal.java
@@ -46,6 +46,23 @@
      */
     enum State {
         /**
+         * Camera has been closed and has released all held resources.
+         */
+        RELEASED(/*holdsCameraSlot=*/false),
+        /**
+         * Camera is in the process of being released and cannot be reopened.
+         *
+         * <p>This is a transient state. Note that this state holds a camera slot even though the
+         * implementation may not actually hold camera resources.
+         */
+        // TODO: Check if this needs to be split up into multiple RELEASING states to
+        //  differentiate between when the camera slot is being held or not.
+        RELEASING(/*holdsCameraSlot=*/true),
+        /**
+         * Camera has been closed and should not be producing data.
+         */
+        CLOSED(/*holdsCameraSlot=*/false),
+        /**
          * Camera is waiting for resources to become available before opening.
          *
          * <p>The camera will automatically transition to an {@link #OPENING} state once resources
@@ -53,6 +70,12 @@
          */
         PENDING_OPEN(/*holdsCameraSlot=*/false),
         /**
+         * Camera is in the process of closing.
+         *
+         * <p>This is a transient state.
+         */
+        CLOSING(/*holdsCameraSlot=*/true),
+        /**
          * Camera is in the process of opening.
          *
          * <p>This is a transient state.
@@ -71,30 +94,7 @@
          * capture session is not configured yet. External users will only see OPEN state, no
          * matter the internal state is CONFIGURED or OPEN.
          */
-        CONFIGURED(/*holdsCameraSlot=*/true),
-        /**
-         * Camera is in the process of closing.
-         *
-         * <p>This is a transient state.
-         */
-        CLOSING(/*holdsCameraSlot=*/true),
-        /**
-         * Camera has been closed and should not be producing data.
-         */
-        CLOSED(/*holdsCameraSlot=*/false),
-        /**
-         * Camera is in the process of being released and cannot be reopened.
-         *
-         * <p>This is a transient state. Note that this state holds a camera slot even though the
-         * implementation may not actually hold camera resources.
-         */
-        // TODO: Check if this needs to be split up into multiple RELEASING states to
-        //  differentiate between when the camera slot is being held or not.
-        RELEASING(/*holdsCameraSlot=*/true),
-        /**
-         * Camera has been closed and has released all held resources.
-         */
-        RELEASED(/*holdsCameraSlot=*/false);
+        CONFIGURED(/*holdsCameraSlot=*/true);
 
         private final boolean mHoldsCameraSlot;
 
@@ -135,7 +135,7 @@
      * resume regardless of the camera availability if the camera is interrupted in
      * OPEN/OPENING/PENDING_OPEN state.
      *
-     * When not in active resuming mode, it will retry opening camera only when camera
+     * <p>When not in active resuming mode, it will retry opening camera only when camera
      * becomes available.
      */
     default void setActiveResumingMode(boolean enabled) {
@@ -212,6 +212,18 @@
     }
 
     /**
+     * Sets the flag in camera instance as primary or secondary camera.
+     *
+     * <p> In dual camera case, the flag will be used to pick up the corresponding
+     * {@link SessionConfig} in {@link UseCase}.
+     *
+     * <p> In single camera case, the flag will always be set to true.
+     *
+     * @param isPrimary whether the camera is primary or secondary.
+     */
+    default void setPrimary(boolean isPrimary) {}
+
+    /**
      * Returns the current {@link CameraConfig}.
      */
     @NonNull
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraStateRegistry.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraStateRegistry.java
index fc484f760..64883dd 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraStateRegistry.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraStateRegistry.java
@@ -27,6 +27,7 @@
 import androidx.camera.core.concurrent.CameraCoordinator;
 import androidx.camera.core.concurrent.CameraCoordinator.CameraOperatingMode;
 import androidx.core.util.Preconditions;
+import androidx.tracing.Trace;
 
 import java.util.HashMap;
 import java.util.Locale;
@@ -143,6 +144,7 @@
             if (mAvailableCameras > 0 || isOpen(registration.getState())) {
                 // Set state directly to OPENING.
                 registration.setState(CameraInternal.State.OPENING);
+                traceState(camera, CameraInternal.State.OPENING);
                 success = true;
             }
 
@@ -177,11 +179,12 @@
             if (mCameraCoordinator.getCameraOperatingMode() != CAMERA_OPERATING_MODE_CONCURRENT) {
                 return true;
             }
-            CameraInternal.State selfState = getCameraRegistration(cameraId) != null
-                    ? getCameraRegistration(cameraId).getState() : null;
+            CameraRegistration registration = getCameraRegistration(cameraId);
+            CameraInternal.State selfState = registration != null ? registration.getState() : null;
+            CameraRegistration pairedRegistration =
+                    pairedCameraId != null ? getCameraRegistration(pairedCameraId) : null;
             CameraInternal.State pairedState =
-                    (pairedCameraId != null && getCameraRegistration(pairedCameraId) != null)
-                            ? getCameraRegistration(pairedCameraId).getState() : null;
+                    (pairedRegistration != null) ? pairedRegistration.getState() : null;
             boolean isSelfAvailable = CameraInternal.State.OPEN.equals(selfState)
                     || CameraInternal.State.CONFIGURED.equals(selfState);
             boolean isPairAvailable = CameraInternal.State.OPEN.equals(pairedState)
@@ -228,7 +231,7 @@
         Map<Camera, CameraRegistration> camerasToNotifyOpen = null;
         CameraRegistration cameraToNotifyConfigure = null;
         synchronized (mLock) {
-            CameraInternal.State previousState = null;
+            CameraInternal.State previousState;
             int previousAvailableCameras = mAvailableCameras;
             if (state == CameraInternal.State.RELEASED) {
                 previousState = unregisterCamera(camera);
@@ -338,6 +341,7 @@
 
         // Only update the available camera count if the camera state has changed.
         if (previousState != state) {
+            traceState(camera, state);
             recalculateAvailableCameras();
         }
 
@@ -483,4 +487,11 @@
             }
         }
     }
+
+    private static void traceState(Camera camera, CameraInternal.State state) {
+        if (Trace.isEnabled()) {
+            String counterName = "CX:State[" + camera + "]";
+            Trace.setCounter(counterName, state.ordinal());
+        }
+    }
 }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/SessionConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/SessionConfig.java
index 518779a..f8c9c6c 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/SessionConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/SessionConfig.java
@@ -42,6 +42,7 @@
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * Configurations needed for a capture session.
@@ -71,7 +72,7 @@
     private final List<CameraCaptureSession.StateCallback> mSessionStateCallbacks;
     /** The callbacks used in single requests. */
     private final List<CameraCaptureCallback> mSingleCameraCaptureCallbacks;
-    private final List<ErrorListener> mErrorListeners;
+    private final ErrorListener mErrorListener;
     /** The configuration for building the {@link CaptureRequest} used for repeating requests. */
     private final CaptureConfig mRepeatingCaptureConfig;
     /** The type of the session */
@@ -237,8 +238,8 @@
             List<StateCallback> deviceStateCallbacks,
             List<CameraCaptureSession.StateCallback> sessionStateCallbacks,
             List<CameraCaptureCallback> singleCameraCaptureCallbacks,
-            List<ErrorListener> errorListeners,
             CaptureConfig repeatingCaptureConfig,
+            @Nullable ErrorListener errorListener,
             @Nullable InputConfiguration inputConfiguration,
             int sessionType,
             @Nullable OutputConfig postviewOutputConfig) {
@@ -247,7 +248,7 @@
         mSessionStateCallbacks = Collections.unmodifiableList(sessionStateCallbacks);
         mSingleCameraCaptureCallbacks =
                 Collections.unmodifiableList(singleCameraCaptureCallbacks);
-        mErrorListeners = Collections.unmodifiableList(errorListeners);
+        mErrorListener = errorListener;
         mRepeatingCaptureConfig = repeatingCaptureConfig;
         mInputConfiguration = inputConfiguration;
         mSessionType = sessionType;
@@ -262,8 +263,8 @@
                 new ArrayList<CameraDevice.StateCallback>(0),
                 new ArrayList<CameraCaptureSession.StateCallback>(0),
                 new ArrayList<CameraCaptureCallback>(0),
-                new ArrayList<>(0),
                 new CaptureConfig.Builder().build(),
+                /* errorListener */ null,
                 /* inputConfiguration */ null,
                 DEFAULT_SESSION_TYPE,
                 /* postviewOutputConfig */ null);
@@ -337,10 +338,10 @@
         return mRepeatingCaptureConfig.getCameraCaptureCallbacks();
     }
 
-    /** Obtains all registered {@link ErrorListener} callbacks. */
-    @NonNull
-    public List<ErrorListener> getErrorListeners() {
-        return mErrorListeners;
+    /** Obtains the registered {@link ErrorListener} callback. */
+    @Nullable
+    public ErrorListener getErrorListener() {
+        return mErrorListener;
     }
 
     /** Obtains all registered {@link CameraCaptureCallback} callbacks for single requests. */
@@ -385,6 +386,32 @@
     }
 
     /**
+     * A closeable ErrorListener that onError callback won't be invoked after it is closed.
+     */
+    public static final class CloseableErrorListener implements ErrorListener {
+        private final AtomicBoolean mIsClosed = new AtomicBoolean(false);
+        private final ErrorListener mErrorListener;
+
+        public CloseableErrorListener(@NonNull ErrorListener errorListener) {
+            mErrorListener = errorListener;
+        }
+
+        @Override
+        public void onError(@NonNull SessionConfig sessionConfig, @NonNull SessionError error) {
+            if (!mIsClosed.get()) {
+                mErrorListener.onError(sessionConfig, error);
+            }
+        }
+
+        /**
+         * Closes the ErrorListener to not invoke the onError callback function.
+         */
+        public void close() {
+            mIsClosed.set(true);
+        }
+    }
+
+    /**
      * Interface for unpacking a configuration into a SessionConfig.Builder
      *
      * <p>TODO(b/120949879): This will likely be removed once SessionConfig is refactored to
@@ -414,9 +441,10 @@
         final CaptureConfig.Builder mCaptureConfigBuilder = new CaptureConfig.Builder();
         final List<CameraDevice.StateCallback> mDeviceStateCallbacks = new ArrayList<>();
         final List<CameraCaptureSession.StateCallback> mSessionStateCallbacks = new ArrayList<>();
-        final List<ErrorListener> mErrorListeners = new ArrayList<>();
         final List<CameraCaptureCallback> mSingleCameraCaptureCallbacks = new ArrayList<>();
         @Nullable
+        ErrorListener mErrorListener;
+        @Nullable
         InputConfiguration mInputConfiguration;
         int mSessionType = DEFAULT_SESSION_TYPE;
         @Nullable
@@ -664,8 +692,8 @@
          * Adds all {@link ErrorListener} listeners repeating requests.
          */
         @NonNull
-        public Builder addErrorListener(@NonNull ErrorListener errorListener) {
-            mErrorListeners.add(errorListener);
+        public Builder setErrorListener(@NonNull ErrorListener errorListener) {
+            mErrorListener = errorListener;
             return this;
         }
 
@@ -802,8 +830,8 @@
                     new ArrayList<>(mDeviceStateCallbacks),
                     new ArrayList<>(mSessionStateCallbacks),
                     new ArrayList<>(mSingleCameraCaptureCallbacks),
-                    new ArrayList<>(mErrorListeners),
                     mCaptureConfigBuilder.build(),
+                    mErrorListener,
                     mInputConfiguration,
                     mSessionType,
                     mPostviewOutputConfig);
@@ -819,6 +847,7 @@
         private final SurfaceSorter mSurfaceSorter = new SurfaceSorter();
         private boolean mValid = true;
         private boolean mTemplateSet = false;
+        private List<ErrorListener> mErrorListeners = new ArrayList<>();
 
         /**
          * Add an implementation option to the ValidatingBuilder's CaptureConfigBuilder. If it
@@ -864,7 +893,9 @@
             // Check camera capture callbacks for single requests.
             mSingleCameraCaptureCallbacks.addAll(sessionConfig.getSingleCameraCaptureCallbacks());
 
-            mErrorListeners.addAll(sessionConfig.getErrorListeners());
+            if (sessionConfig.getErrorListener() != null) {
+                mErrorListeners.add(sessionConfig.getErrorListener());
+            }
 
             // Check input configuration for reprocessable capture session.
             if (sessionConfig.getInputConfiguration() != null) {
@@ -982,13 +1013,23 @@
             List<OutputConfig> outputConfigs = new ArrayList<>(mOutputConfigs);
             mSurfaceSorter.sort(outputConfigs);
 
+            ErrorListener errorListener = null;
+            // Creates an error listener to notify errors to the underlying error listeners.
+            if (!mErrorListeners.isEmpty()) {
+                errorListener = (sessionConfig, error) -> {
+                    for (ErrorListener listener: mErrorListeners) {
+                        listener.onError(sessionConfig, error);
+                    }
+                };
+            }
+
             return new SessionConfig(
                     outputConfigs,
                     new ArrayList<>(mDeviceStateCallbacks),
                     new ArrayList<>(mSessionStateCallbacks),
                     new ArrayList<>(mSingleCameraCaptureCallbacks),
-                    new ArrayList<>(mErrorListeners),
                     mCaptureConfigBuilder.build(),
+                    errorListener,
                     mInputConfiguration,
                     mSessionType,
                     mPostviewOutputConfig);
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/StreamSpec.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/StreamSpec.java
index 62f0c09..e6eab05 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/StreamSpec.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/StreamSpec.java
@@ -68,13 +68,19 @@
     @Nullable
     public abstract Config getImplementationOptions();
 
+    /**
+     * Returns the flag if zero-shutter lag needs to be disabled by user case combinations.
+     */
+    public abstract boolean getZslDisabled();
+
     /** Returns a build for a stream configuration that takes a required resolution. */
     @NonNull
     public static Builder builder(@NonNull Size resolution) {
         return new AutoValue_StreamSpec.Builder()
                 .setResolution(resolution)
                 .setExpectedFrameRateRange(FRAME_RATE_RANGE_UNSPECIFIED)
-                .setDynamicRange(DynamicRange.SDR);
+                .setDynamicRange(DynamicRange.SDR)
+                .setZslDisabled(false);
     }
 
     /** Returns a builder pre-populated with the current specification. */
@@ -118,6 +124,12 @@
         @NonNull
         public abstract Builder setImplementationOptions(@NonNull Config config);
 
+        /**
+         * Sets the flag if zero-shutter lag needs to be disabled by user case combinations.
+         */
+        @NonNull
+        public abstract Builder setZslDisabled(boolean disabled);
+
         /** Builds the stream specification */
         @NonNull
         public abstract StreamSpec build();
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/utils/CameraOrientationUtil.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/utils/CameraOrientationUtil.java
index cc39e50..ce77a2c 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/utils/CameraOrientationUtil.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/utils/CameraOrientationUtil.java
@@ -52,7 +52,7 @@
         } else {
             result = (sourceRotationDegrees + destRotationDegrees) % 360;
         }
-        if (Logger.isDebugEnabled(TAG)) {
+        if (Logger.isVerboseEnabled(TAG)) {
             Logger.d(
                     TAG,
                     String.format(
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/internal/CameraUseCaseAdapter.java b/camera/camera-core/src/main/java/androidx/camera/core/internal/CameraUseCaseAdapter.java
index 1274d68..37910ae 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/internal/CameraUseCaseAdapter.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/internal/CameraUseCaseAdapter.java
@@ -57,6 +57,7 @@
 import androidx.camera.core.CameraSelector;
 import androidx.camera.core.DynamicRange;
 import androidx.camera.core.ImageCapture;
+import androidx.camera.core.LayoutSettings;
 import androidx.camera.core.Logger;
 import androidx.camera.core.Preview;
 import androidx.camera.core.UseCase;
@@ -93,6 +94,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
@@ -108,6 +110,8 @@
 public final class CameraUseCaseAdapter implements Camera {
     @NonNull
     private final CameraInternal mCameraInternal;
+    @Nullable
+    private final CameraInternal mSecondaryCameraInternal;
     private final CameraDeviceSurfaceManager mCameraDeviceSurfaceManager;
     private final UseCaseConfigFactory mUseCaseConfigFactory;
 
@@ -164,6 +168,12 @@
     private final RestrictedCameraControl mAdapterCameraControl;
     @NonNull
     private final RestrictedCameraInfo mAdapterCameraInfo;
+
+    @NonNull
+    private final LayoutSettings mLayoutSettings;
+    @NonNull
+    private final LayoutSettings mSecondaryLayoutSettings;
+
     /**
      * Create a new {@link CameraUseCaseAdapter} instance.
      *
@@ -179,8 +189,12 @@
             @NonNull CameraDeviceSurfaceManager cameraDeviceSurfaceManager,
             @NonNull UseCaseConfigFactory useCaseConfigFactory) {
         this(camera,
+                null,
                 new RestrictedCameraInfo(camera.getCameraInfoInternal(),
                         CameraConfigs.defaultConfig()),
+                null,
+                LayoutSettings.DEFAULT,
+                LayoutSettings.DEFAULT,
                 cameraCoordinator,
                 cameraDeviceSurfaceManager,
                 useCaseConfigFactory);
@@ -190,21 +204,35 @@
      * Create a new {@link CameraUseCaseAdapter} instance.
      *
      * @param camera                     The camera that is wrapped.
+     * @param secondaryCamera            The secondary camera that is wrapped.
      * @param restrictedCameraInfo       The {@link RestrictedCameraInfo} that contains the extra
      *                                   information to configure the {@link CameraInternal} when
      *                                   attaching the uses cases of this adapter to the camera.
+     * @param secondaryRestrictedCameraInfo The {@link RestrictedCameraInfo} of secondary camera.
+     * @param layoutSettings             The layout settings that will be used to configure the
+     *                                   camera.
+     * @param secondaryLayoutSettings    The layout settings that will be used to configure the
+     *                                   secondary camera.
      * @param cameraCoordinator          Camera coordinator that exposes concurrent camera mode.
      * @param cameraDeviceSurfaceManager A class that checks for whether a specific camera
      *                                   can support the set of Surface with set resolutions.
      * @param useCaseConfigFactory       UseCase config factory that exposes configuration for
      *                                   each UseCase.
      */
-    public CameraUseCaseAdapter(@NonNull CameraInternal camera,
+    public CameraUseCaseAdapter(
+            @NonNull CameraInternal camera,
+            @Nullable CameraInternal secondaryCamera,
             @NonNull RestrictedCameraInfo restrictedCameraInfo,
+            @Nullable RestrictedCameraInfo secondaryRestrictedCameraInfo,
+            @NonNull LayoutSettings layoutSettings,
+            @NonNull LayoutSettings secondaryLayoutSettings,
             @NonNull CameraCoordinator cameraCoordinator,
             @NonNull CameraDeviceSurfaceManager cameraDeviceSurfaceManager,
             @NonNull UseCaseConfigFactory useCaseConfigFactory) {
         mCameraInternal = camera;
+        mSecondaryCameraInternal = secondaryCamera;
+        mLayoutSettings = layoutSettings;
+        mSecondaryLayoutSettings = secondaryLayoutSettings;
         mCameraCoordinator = cameraCoordinator;
         mCameraDeviceSurfaceManager = cameraDeviceSurfaceManager;
         mUseCaseConfigFactory = useCaseConfigFactory;
@@ -214,16 +242,20 @@
         mAdapterCameraControl = new RestrictedCameraControl(
                 mCameraInternal.getCameraControlInternal(), sessionProcessor);
         mAdapterCameraInfo = restrictedCameraInfo;
-        mId = generateCameraId(mAdapterCameraInfo);
+        mId = generateCameraId(restrictedCameraInfo, secondaryRestrictedCameraInfo);
     }
 
     /**
      * Generate a identifier for the {@link RestrictedCameraInfo}.
      */
     @NonNull
-    public static CameraId generateCameraId(@NonNull RestrictedCameraInfo cameraInfo) {
-        return CameraId.create(cameraInfo.getCameraId(),
-                cameraInfo.getCameraConfig().getCompatibilityId());
+    public static CameraId generateCameraId(
+            @NonNull RestrictedCameraInfo primaryCameraInfo,
+            @Nullable RestrictedCameraInfo secondaryCameraInfo) {
+        return CameraId.create(
+                primaryCameraInfo.getCameraId()
+                        + (secondaryCameraInfo == null ? "" : secondaryCameraInfo.getCameraId()),
+                primaryCameraInfo.getCameraConfig().getCompatibilityId());
     }
 
     /**
@@ -260,7 +292,7 @@
     }
 
     /**
-     * Add the specified collection of {@link UseCase} to the adapter.
+     * Add the specified collection of {@link UseCase} to the adapter with dual camera support.
      *
      * @throws CameraException Thrown if the combination of newly added UseCases and the
      *                         currently added UseCases exceed the capability of the camera.
@@ -269,12 +301,16 @@
         synchronized (mLock) {
             // Configure the CameraConfig when binding
             mCameraInternal.setExtendedConfig(mCameraConfig);
+            if (mSecondaryCameraInternal != null) {
+                mSecondaryCameraInternal.setExtendedConfig(mCameraConfig);
+            }
             Set<UseCase> appUseCases = new LinkedHashSet<>(mAppUseCases);
             //TODO(b/266641900): must be LinkedHashSet otherwise ExistingActivityLifecycleTest
             // fails due to a camera-pipe integration bug.
             appUseCases.addAll(appUseCasesToAdd);
             try {
-                updateUseCases(appUseCases);
+                updateUseCases(appUseCases,
+                        mSecondaryCameraInternal != null, mSecondaryCameraInternal != null);
             } catch (IllegalArgumentException e) {
                 throw new CameraException(e);
             }
@@ -288,7 +324,8 @@
         synchronized (mLock) {
             Set<UseCase> appUseCases = new LinkedHashSet<>(mAppUseCases);
             appUseCases.removeAll(useCasesToRemove);
-            updateUseCases(appUseCases);
+            updateUseCases(appUseCases,
+                    mSecondaryCameraInternal != null, mSecondaryCameraInternal != null);
         }
     }
 
@@ -296,7 +333,7 @@
      * Updates the states based the new app UseCases.
      */
     void updateUseCases(@NonNull Collection<UseCase> appUseCases) {
-        updateUseCases(appUseCases, /*applyStreamSharing*/false);
+        updateUseCases(appUseCases, /*applyStreamSharing*/false, /*isDualCamera*/false);
     }
 
     /**
@@ -309,7 +346,9 @@
      * @throws IllegalArgumentException if the UseCase combination is not supported. In that case,
      *                                  it will not update the internal states.
      */
-    void updateUseCases(@NonNull Collection<UseCase> appUseCases, boolean applyStreamSharing) {
+    void updateUseCases(@NonNull Collection<UseCase> appUseCases,
+            boolean applyStreamSharing,
+            boolean isDualCamera) {
         synchronized (mLock) {
             checkUnsupportedFeatureCombinationAndThrow(appUseCases);
 
@@ -317,7 +356,7 @@
             // applyStreamSharing is set to true when the use case combination contains
             // VideoCapture and Extensions is enabled.
             if (!applyStreamSharing && hasExtension() && hasVideoCapture(appUseCases)) {
-                updateUseCases(appUseCases, /*applyStreamSharing*/true);
+                updateUseCases(appUseCases, /*applyStreamSharing*/true, isDualCamera);
                 return;
             }
 
@@ -343,12 +382,20 @@
             Map<UseCase, ConfigPair> configs = getConfigs(cameraUseCasesToAttach,
                     mCameraConfig.getUseCaseConfigFactory(), mUseCaseConfigFactory);
 
-            Map<UseCase, StreamSpec> suggestedStreamSpecMap;
+            Map<UseCase, StreamSpec> primaryStreamSpecMap;
+            Map<UseCase, StreamSpec> secondaryStreamSpecMap = Collections.emptyMap();
             try {
-                suggestedStreamSpecMap = calculateSuggestedStreamSpecs(
+                primaryStreamSpecMap = calculateSuggestedStreamSpecs(
                         getCameraMode(),
                         mCameraInternal.getCameraInfoInternal(), cameraUseCasesToAttach,
                         cameraUseCasesToKeep, configs);
+                if (mSecondaryCameraInternal != null) {
+                    secondaryStreamSpecMap = calculateSuggestedStreamSpecs(
+                            getCameraMode(),
+                            requireNonNull(mSecondaryCameraInternal).getCameraInfoInternal(),
+                            cameraUseCasesToAttach,
+                            cameraUseCasesToKeep, configs);
+                }
                 // TODO(b/265704882): enable stream sharing for LEVEL_3 and high preview
                 //  resolution. Throw exception here if (applyStreamSharing == false), both video
                 //  and preview are used and preview resolution is lower than user configuration.
@@ -362,7 +409,7 @@
                         && mCameraCoordinator.getCameraOperatingMode()
                         != CameraCoordinator.CAMERA_OPERATING_MODE_CONCURRENT) {
                     // Try again and see if StreamSharing resolves the issue.
-                    updateUseCases(appUseCases, /*applyStreamSharing*/true);
+                    updateUseCases(appUseCases, /*applyStreamSharing*/true, isDualCamera);
                     return;
                 } else {
                     // If StreamSharing already on or not enabled, throw exception.
@@ -371,7 +418,7 @@
             }
 
             // Update properties.
-            updateViewPort(suggestedStreamSpecMap, cameraUseCases);
+            updateViewPort(primaryStreamSpecMap, cameraUseCases);
             updateEffects(mEffects, cameraUseCases, appUseCases);
 
             // Detach unused UseCases.
@@ -380,20 +427,34 @@
             }
             mCameraInternal.detachUseCases(cameraUseCasesToDetach);
 
+            // Detach unused UseCases for secondary camera.
+            if (mSecondaryCameraInternal != null) {
+                for (UseCase useCase : cameraUseCasesToDetach) {
+                    useCase.unbindFromCamera(requireNonNull(mSecondaryCameraInternal));
+                }
+                requireNonNull(mSecondaryCameraInternal)
+                        .detachUseCases(cameraUseCasesToDetach);
+            }
+
             // Update StreamSpec for UseCases to keep.
             if (cameraUseCasesToDetach.isEmpty()) {
                 // Only do this if we are not removing UseCase, because updating SessionConfig
                 // when removing UseCases may lead to flickering.
                 for (UseCase useCase : cameraUseCasesToKeep) {
-                    if (suggestedStreamSpecMap.containsKey(useCase)) {
-                        StreamSpec newStreamSpec = suggestedStreamSpecMap.get(useCase);
+                    // Assume secondary camera will not have implementation options in dual camera.
+                    if (primaryStreamSpecMap.containsKey(useCase)) {
+                        StreamSpec newStreamSpec = primaryStreamSpecMap.get(useCase);
                         Config config = newStreamSpec.getImplementationOptions();
                         if (config != null && hasImplementationOptionChanged(newStreamSpec,
                                 useCase.getSessionConfig())) {
                             useCase.updateSuggestedStreamSpecImplementationOptions(config);
-                        }
-                        if (mAttached) {
-                            mCameraInternal.onUseCaseUpdated(useCase);
+                            if (mAttached) {
+                                mCameraInternal.onUseCaseUpdated(useCase);
+                                if (mSecondaryCameraInternal != null) {
+                                    requireNonNull(mSecondaryCameraInternal)
+                                            .onUseCaseUpdated(useCase);
+                                }
+                            }
                         }
                     }
                 }
@@ -402,13 +463,30 @@
             // Attach new UseCases.
             for (UseCase useCase : cameraUseCasesToAttach) {
                 ConfigPair configPair = requireNonNull(configs.get(useCase));
-                useCase.bindToCamera(mCameraInternal, configPair.mExtendedConfig,
-                        configPair.mCameraConfig);
-                useCase.updateSuggestedStreamSpec(
-                        Preconditions.checkNotNull(suggestedStreamSpecMap.get(useCase)));
+                if (mSecondaryCameraInternal != null) {
+                    useCase.bindToCamera(mCameraInternal,
+                            requireNonNull(mSecondaryCameraInternal),
+                            configPair.mExtendedConfig,
+                            configPair.mCameraConfig);
+                    useCase.updateSuggestedStreamSpec(
+                            Preconditions.checkNotNull(primaryStreamSpecMap.get(useCase)),
+                            secondaryStreamSpecMap.get(useCase));
+                } else {
+                    useCase.bindToCamera(mCameraInternal,
+                            null,
+                            configPair.mExtendedConfig,
+                            configPair.mCameraConfig);
+                    useCase.updateSuggestedStreamSpec(
+                            Preconditions.checkNotNull(primaryStreamSpecMap.get(useCase)),
+                            null);
+                }
             }
             if (mAttached) {
                 mCameraInternal.attachUseCases(cameraUseCasesToAttach);
+                if (mSecondaryCameraInternal != null) {
+                    requireNonNull(mSecondaryCameraInternal)
+                            .attachUseCases(cameraUseCasesToAttach);
+                }
             }
 
             // Once UseCases are detached/attached, notify the camera.
@@ -538,7 +616,12 @@
                 return null;
             }
 
-            return new StreamSharing(mCameraInternal, newChildren, mUseCaseConfigFactory);
+            return new StreamSharing(mCameraInternal,
+                    mSecondaryCameraInternal,
+                    mLayoutSettings,
+                    mSecondaryLayoutSettings,
+                    newChildren,
+                    mUseCaseConfigFactory);
         }
     }
 
@@ -596,7 +679,7 @@
 
     @VisibleForTesting
     @NonNull
-    Collection<UseCase> getCameraUseCases() {
+    public Collection<UseCase> getCameraUseCases() {
         synchronized (mLock) {
             return new ArrayList<>(mCameraUseCases);
         }
@@ -616,8 +699,14 @@
                 // Ensure the current opening camera has the right camera config.
                 if (!mCameraUseCases.isEmpty()) {
                     mCameraInternal.setExtendedConfig(mCameraConfig);
+                    if (mSecondaryCameraInternal != null) {
+                        mSecondaryCameraInternal.setExtendedConfig(mCameraConfig);
+                    }
                 }
                 mCameraInternal.attachUseCases(mCameraUseCases);
+                if (mSecondaryCameraInternal != null) {
+                    mSecondaryCameraInternal.attachUseCases(mCameraUseCases);
+                }
                 restoreInteropConfig();
 
                 // Notify to update the use case's active state because it may be cleared if the
@@ -654,6 +743,9 @@
         synchronized (mLock) {
             if (mAttached) {
                 mCameraInternal.detachUseCases(new ArrayList<>(mCameraUseCases));
+                if (mSecondaryCameraInternal != null) {
+                    mSecondaryCameraInternal.detachUseCases(new ArrayList<>(mCameraUseCases));
+                }
                 cacheInteropConfig();
                 mAttached = false;
             }
@@ -754,7 +846,8 @@
                             cameraMode,
                             cameraId, existingSurfaces,
                             configToSupportedSizesMap,
-                            isPreviewStabilizationOn);
+                            isPreviewStabilizationOn,
+                            hasVideoCapture(newUseCases));
 
             for (Map.Entry<UseCaseConfig<?>, UseCase> entry : configToUseCaseMap.entrySet()) {
                 suggestedStreamSpecs.put(entry.getValue(),
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/processing/OpenGlRenderer.java b/camera/camera-core/src/main/java/androidx/camera/core/processing/OpenGlRenderer.java
index 45bd1c0..63e29226 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/processing/OpenGlRenderer.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/processing/OpenGlRenderer.java
@@ -33,6 +33,7 @@
 import static androidx.camera.core.processing.util.GLUtils.checkInitializedOrThrow;
 import static androidx.camera.core.processing.util.GLUtils.checkLocationOrThrow;
 import static androidx.camera.core.processing.util.GLUtils.chooseSurfaceAttrib;
+import static androidx.camera.core.processing.util.GLUtils.create4x4IdentityMatrix;
 import static androidx.camera.core.processing.util.GLUtils.createPBufferSurface;
 import static androidx.camera.core.processing.util.GLUtils.createProgram;
 import static androidx.camera.core.processing.util.GLUtils.createTexture;
@@ -62,7 +63,6 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
 import androidx.annotation.WorkerThread;
 import androidx.camera.core.DynamicRange;
 import androidx.camera.core.Logger;
@@ -89,38 +89,41 @@
  * {@link IllegalStateException} will be thrown when other methods are called.
  */
 @WorkerThread
-public final class OpenGlRenderer {
+public class OpenGlRenderer {
 
     private static final String TAG = "OpenGlRenderer";
 
-    private final AtomicBoolean mInitialized = new AtomicBoolean(false);
-    @VisibleForTesting
-    final Map<Surface, OutputSurface> mOutputSurfaceMap = new HashMap<>();
+    protected final AtomicBoolean mInitialized = new AtomicBoolean(false);
+    protected final Map<Surface, OutputSurface> mOutputSurfaceMap = new HashMap<>();
     @Nullable
-    private Thread mGlThread;
+    protected Thread mGlThread;
     @NonNull
-    private EGLDisplay mEglDisplay = EGL14.EGL_NO_DISPLAY;
+    protected EGLDisplay mEglDisplay = EGL14.EGL_NO_DISPLAY;
     @NonNull
-    private EGLContext mEglContext = EGL14.EGL_NO_CONTEXT;
+    protected EGLContext mEglContext = EGL14.EGL_NO_CONTEXT;
     @NonNull
-    private int[] mSurfaceAttrib = EMPTY_ATTRIBS;
+    protected int[] mSurfaceAttrib = EMPTY_ATTRIBS;
     @Nullable
-    private EGLConfig mEglConfig;
+    protected EGLConfig mEglConfig;
     @NonNull
-    private EGLSurface mTempSurface = EGL14.EGL_NO_SURFACE;
+    protected EGLSurface mTempSurface = EGL14.EGL_NO_SURFACE;
     @Nullable
-    private Surface mCurrentSurface;
+    protected Surface mCurrentSurface;
+    protected int mProgramHandle = -1;
+    protected int mTexMatrixLoc = -1;
+    protected int mTransMatrixLoc = -1;
+    protected int mAlphaScaleLoc = -1;
+    protected int mPositionLoc = -1;
+    protected int mTexCoordLoc = -1;
+    protected int mSamplerDefaultLoc = -1;
+    protected int mSamplerYuvLoc = -1;
+    protected int mSamplerSelectorLoc = -1;
+    protected int mExternalTexNumUnits = -1;
+    protected boolean mIsDefaultHdrShader = false;
+    @NonNull
+    protected InputFormat mCurrentInputformat = InputFormat.UNKNOWN;
+
     private int mExternalTextureId = -1;
-    private int mProgramHandle = -1;
-    private int mTexMatrixLoc = -1;
-    private int mPositionLoc = -1;
-    private int mTexCoordLoc = -1;
-    private int mSamplerDefaultLoc = -1;
-    private int mSamplerYuvLoc = -1;
-    private int mSamplerSelectorLoc = -1;
-    private int mExternalTexNumUnits = -1;
-    private boolean mIsDefaultHdrShader = false;
-    private InputFormat mCurrentInputformat = InputFormat.UNKNOWN;
 
     /**
      * Initializes the OpenGLRenderer
@@ -163,7 +166,7 @@
             loadLocations();
             mExternalTextureId = createTexture();
             mExternalTexNumUnits = getTexNumUnits();
-            useAndConfigureProgram();
+            useAndConfigureProgram(mExternalTextureId);
         } catch (IllegalStateException | IllegalArgumentException e) {
             releaseInternal();
             throw e;
@@ -243,11 +246,11 @@
 
         if (mCurrentInputformat != inputFormat) {
             mCurrentInputformat = inputFormat;
-            activateExternalTexture();
+            activateExternalTexture(mExternalTextureId);
         }
     }
 
-    private void activateExternalTexture() {
+    private void activateExternalTexture(int externalTextureId) {
         GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
 
         int texUnit = GLES20.GL_TEXTURE0;
@@ -262,7 +265,7 @@
         GLES20.glActiveTexture(texUnit);
         checkGlErrorOrThrow("glActiveTexture");
 
-        GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, mExternalTextureId);
+        GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, externalTextureId);
         checkGlErrorOrThrow("glBindTexture");
     }
 
@@ -414,7 +417,7 @@
         deleteTexture(texture);
         deleteFbo(fbo);
         // Set the external texture to be active.
-        activateExternalTexture();
+        activateExternalTexture(mExternalTextureId);
     }
 
     // Returns a pair of GL extension (first) and EGL extension (second) strings.
@@ -504,7 +507,7 @@
                 /*height=*/1);
     }
 
-    private void makeCurrent(@NonNull EGLSurface eglSurface) {
+    protected void makeCurrent(@NonNull EGLSurface eglSurface) {
         Preconditions.checkNotNull(mEglDisplay);
         Preconditions.checkNotNull(mEglContext);
         if (!EGL14.eglMakeCurrent(mEglDisplay, eglSurface, eglSurface, mEglContext)) {
@@ -512,7 +515,7 @@
         }
     }
 
-    private void useAndConfigureProgram() {
+    protected void useAndConfigureProgram(int textureId) {
         // Select the program.
         GLES20.glUseProgram(mProgramHandle);
         checkGlErrorOrThrow("glUseProgram");
@@ -545,8 +548,17 @@
                 /*normalized=*/false, texStride, TEX_BUF);
         checkGlErrorOrThrow("glVertexAttribPointer");
 
+        // Set to default value for single camera case
+        GLES20.glUniformMatrix4fv(mTransMatrixLoc,
+                /*count=*/1, /*transpose=*/false, create4x4IdentityMatrix(),
+                /*offset=*/0);
+        checkGlErrorOrThrow("glUniformMatrix4fv");
+
+        GLES20.glUniform1f(mAlphaScaleLoc, 1.0f);
+        checkGlErrorOrThrow("glUniform1f");
+
         // Activate the texture
-        activateExternalTexture();
+        activateExternalTexture(textureId);
     }
 
     private void loadLocations() {
@@ -556,6 +568,10 @@
         checkLocationOrThrow(mTexCoordLoc, "aTextureCoord");
         mTexMatrixLoc = GLES20.glGetUniformLocation(mProgramHandle, "uTexMatrix");
         checkLocationOrThrow(mTexMatrixLoc, "uTexMatrix");
+        mTransMatrixLoc = GLES20.glGetUniformLocation(mProgramHandle, "uTransMatrix");
+        checkLocationOrThrow(mTransMatrixLoc, "uTransMatrix");
+        mAlphaScaleLoc = GLES20.glGetUniformLocation(mProgramHandle, "uAlphaScale");
+        checkLocationOrThrow(mAlphaScaleLoc, "uAlphaScale");
         mSamplerDefaultLoc = GLES20.glGetUniformLocation(mProgramHandle, VAR_TEXTURE);
         checkLocationOrThrow(mSamplerDefaultLoc, VAR_TEXTURE);
         if (mIsDefaultHdrShader) {
@@ -609,6 +625,8 @@
         mTexMatrixLoc = -1;
         mPositionLoc = -1;
         mTexCoordLoc = -1;
+        mTransMatrixLoc = -1;
+        mAlphaScaleLoc = -1;
         mSamplerDefaultLoc = -1;
         mSamplerYuvLoc = -1;
         mSamplerSelectorLoc = -1;
@@ -621,7 +639,7 @@
     }
 
     @NonNull
-    private OutputSurface getOutSurfaceOrThrow(@NonNull Surface surface) {
+    protected OutputSurface getOutSurfaceOrThrow(@NonNull Surface surface) {
         Preconditions.checkState(mOutputSurfaceMap.containsKey(surface),
                 "The surface is not registered.");
 
@@ -629,7 +647,7 @@
     }
 
     @Nullable
-    private OutputSurface createOutputSurfaceInternal(@NonNull Surface surface) {
+    protected OutputSurface createOutputSurfaceInternal(@NonNull Surface surface) {
         EGLSurface eglSurface;
         try {
             eglSurface = createWindowSurface(mEglDisplay, requireNonNull(mEglConfig), surface,
@@ -643,7 +661,7 @@
         return OutputSurface.of(eglSurface, size.getWidth(), size.getHeight());
     }
 
-    private void removeOutputSurfaceInternal(@NonNull Surface surface, boolean unregister) {
+    protected void removeOutputSurfaceInternal(@NonNull Surface surface, boolean unregister) {
         // Unmake current surface.
         if (mCurrentSurface == surface) {
             mCurrentSurface = null;
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/processing/SurfaceEdge.java b/camera/camera-core/src/main/java/androidx/camera/core/processing/SurfaceEdge.java
index 26d1f14..816ad83 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/processing/SurfaceEdge.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/processing/SurfaceEdge.java
@@ -43,6 +43,7 @@
 import androidx.camera.core.CameraEffect;
 import androidx.camera.core.Preview;
 import androidx.camera.core.SurfaceOutput;
+import androidx.camera.core.SurfaceOutput.CameraInputInfo;
 import androidx.camera.core.SurfaceProcessor;
 import androidx.camera.core.SurfaceRequest;
 import androidx.camera.core.SurfaceRequest.TransformationInfo;
@@ -249,12 +250,25 @@
     @MainThread
     @NonNull
     public SurfaceRequest createSurfaceRequest(@NonNull CameraInternal cameraInternal) {
+        return createSurfaceRequest(cameraInternal, true);
+    }
+
+    /**
+     * Creates a {@link SurfaceRequest} that is linked to this {@link SurfaceEdge}
+     * with the additional information whether camera is primary or secondary in dual camera case.
+     */
+    @MainThread
+    @NonNull
+    public SurfaceRequest createSurfaceRequest(
+            @NonNull CameraInternal cameraInternal,
+            boolean isPrimary) {
         checkMainThread();
         checkNotClosed();
         // TODO(b/238230154) figure out how to support HDR.
         SurfaceRequest surfaceRequest = new SurfaceRequest(
                 mStreamSpec.getResolution(),
                 cameraInternal,
+                isPrimary,
                 mStreamSpec.getDynamicRange(),
                 mStreamSpec.getExpectedFrameRateRange(),
                 () -> mainThreadExecutor().execute(() -> {
@@ -302,16 +316,16 @@
      * already has a Surface consumer. To remove the current Surface consumer, call
      * {@link #invalidate()} to reset the connection.
      *
-     * @param inputSize       resolution of input image buffer
-     * @param cropRect        crop rect of input image buffer
-     * @param rotationDegrees expected rotation to the input image buffer
-     * @param mirroring       expected mirroring to the input image buffer
+     * @param format output buffer format
+     * @param cameraInputInfo primary camera {@link CameraInputInfo}
+     * @param secondaryCameraInputInfo secondary camera {@link CameraInputInfo}
      */
     @MainThread
     @NonNull
-    public ListenableFuture<SurfaceOutput> createSurfaceOutputFuture(@NonNull Size inputSize,
-            @CameraEffect.Formats int format, @NonNull Rect cropRect, int rotationDegrees,
-            boolean mirroring, @Nullable CameraInternal cameraInternal) {
+    public ListenableFuture<SurfaceOutput> createSurfaceOutputFuture(
+            @CameraEffect.Formats int format,
+            @NonNull CameraInputInfo cameraInputInfo,
+            @Nullable CameraInputInfo secondaryCameraInputInfo) {
         checkMainThread();
         checkNotClosed();
         checkAndSetHasConsumer();
@@ -325,8 +339,9 @@
                         return immediateFailedFuture(e);
                     }
                     SurfaceOutputImpl surfaceOutputImpl = new SurfaceOutputImpl(surface,
-                            getTargets(), format, mStreamSpec.getResolution(), inputSize, cropRect,
-                            rotationDegrees, mirroring, cameraInternal, mSensorToBufferTransform);
+                            getTargets(), format, mStreamSpec.getResolution(),
+                            cameraInputInfo, secondaryCameraInputInfo,
+                            mSensorToBufferTransform);
                     surfaceOutputImpl.getCloseFuture().addListener(
                             settableSurface::decrementUseCount,
                             directExecutor());
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/processing/SurfaceOutputImpl.java b/camera/camera-core/src/main/java/androidx/camera/core/processing/SurfaceOutputImpl.java
index 3a2c782..e4c3628 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/processing/SurfaceOutputImpl.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/processing/SurfaceOutputImpl.java
@@ -66,17 +66,26 @@
     private final int mFormat;
     @NonNull
     private final Size mSize;
-    private final Size mInputSize;
-    private final Rect mInputCropRect;
-    private final int mRotationDegrees;
-    private final boolean mMirroring;
+
+    @NonNull
+    private final SurfaceOutput.CameraInputInfo mCameraInputInfo;
+    @Nullable
+    private final SurfaceOutput.CameraInputInfo mSecondaryCameraInputInfo;
 
     // The additional transform to be applied on top of SurfaceTexture#getTransformMatrix()
     @NonNull
     private final float[] mAdditionalTransform = new float[16];
+    // The additional transform for secondary camera
+    @NonNull
+    private final float[] mSecondaryAdditionalTransform = new float[16];
+
     // The inverted value of SurfaceTexture#getTransformMatrix()
     @NonNull
     private final float[] mInvertedTextureTransform = new float[16];
+    // The inverted texture transform for secondary camera
+    @NonNull
+    private final float[] mSecondaryInvertedTextureTransform = new float[16];
+
     @GuardedBy("mLock")
     @Nullable
     private Consumer<Event> mEventListener;
@@ -91,8 +100,6 @@
     @NonNull
     private final ListenableFuture<Void> mCloseFuture;
     private CallbackToFutureAdapter.Completer<Void> mCloseFutureCompleter;
-    @Nullable
-    private CameraInternal mCameraInternal;
     @NonNull
     private android.graphics.Matrix mSensorToBufferTransform;
 
@@ -101,23 +108,22 @@
             @CameraEffect.Targets int targets,
             @CameraEffect.Formats int format,
             @NonNull Size size,
-            @NonNull Size inputSize,
-            @NonNull Rect inputCropRect,
-            int rotationDegree,
-            boolean mirroring,
-            @Nullable CameraInternal cameraInternal,
+            @NonNull CameraInputInfo primaryCameraInputInfo,
+            @Nullable CameraInputInfo secondaryCameraInputInfo,
             @NonNull android.graphics.Matrix sensorToBufferTransform) {
         mSurface = surface;
         mTargets = targets;
         mFormat = format;
         mSize = size;
-        mInputSize = inputSize;
-        mInputCropRect = new Rect(inputCropRect);
-        mMirroring = mirroring;
-        mRotationDegrees = rotationDegree;
-        mCameraInternal = cameraInternal;
+        mCameraInputInfo = primaryCameraInputInfo;
+        mSecondaryCameraInputInfo = secondaryCameraInputInfo;
         mSensorToBufferTransform = sensorToBufferTransform;
-        calculateAdditionalTransform();
+        calculateAdditionalTransform(mAdditionalTransform,
+                mInvertedTextureTransform,
+                mCameraInputInfo);
+        calculateAdditionalTransform(mSecondaryAdditionalTransform,
+                mSecondaryInvertedTextureTransform,
+                mSecondaryCameraInputInfo);
         mCloseFuture = CallbackToFutureAdapter.getFuture(
                 completer -> {
                     mCloseFutureCompleter = completer;
@@ -199,27 +205,28 @@
 
     @VisibleForTesting
     public Rect getInputCropRect() {
-        return mInputCropRect;
+        return mCameraInputInfo.getInputCropRect();
     }
 
     @VisibleForTesting
     public Size getInputSize() {
-        return mInputSize;
+        return mCameraInputInfo.getInputSize();
     }
 
     @VisibleForTesting
     public int getRotationDegrees() {
-        return mRotationDegrees;
+        return mCameraInputInfo.getRotationDegrees();
     }
 
     @VisibleForTesting
     public boolean isMirroring() {
-        return mMirroring;
+        return mCameraInputInfo.getMirroring();
     }
 
     @VisibleForTesting
+    @Nullable
     public CameraInternal getCamera() {
-        return mCameraInternal;
+        return mCameraInputInfo.getCameraInternal();
     }
 
     /**
@@ -262,7 +269,19 @@
     @AnyThread
     @Override
     public void updateTransformMatrix(@NonNull float[] output, @NonNull float[] input) {
-        Matrix.multiplyMM(output, 0, input, 0, mAdditionalTransform, 0);
+        updateTransformMatrix(output, input, true);
+    }
+
+    /**
+     * This method can be invoked by the processor implementation on any thread
+     * with additional information whether camera is primary or secondary in dual camera case.
+     */
+    @AnyThread
+    @Override
+    public void updateTransformMatrix(@NonNull float[] output, @NonNull float[] input,
+            boolean isPrimary) {
+        Matrix.multiplyMM(output, 0, input, 0,
+                isPrimary ? mAdditionalTransform : mSecondaryAdditionalTransform, 0);
     }
 
     /**
@@ -275,7 +294,7 @@
     }
 
     /**
-     * Calculates the additional GL transform and saves it to {@link #mAdditionalTransform}.
+     * Calculates the additional GL transform and saves it to additionalTransform.
      *
      * <p>The effect implementation needs to apply this value on top of texture transform obtained
      * from {@link SurfaceTexture#getTransformMatrix}.
@@ -292,8 +311,15 @@
      * <li>3. Calculate B by multiplying A^-1 * A * B.
      * </ol>
      */
-    private void calculateAdditionalTransform() {
-        Matrix.setIdentityM(mAdditionalTransform, 0);
+    private static void calculateAdditionalTransform(
+            @NonNull float[] additionalTransform,
+            @NonNull float[] invertedTransform,
+            @Nullable CameraInputInfo cameraInputInfo) {
+        Matrix.setIdentityM(additionalTransform, 0);
+
+        if (cameraInputInfo == null) {
+            return;
+        }
 
         // Step 1, calculate the overall transformation(A * B) with the following steps:
         // - Flip compensate the GL coordinates v.s. image coordinates
@@ -302,23 +328,27 @@
         // - Apply the crop rect
 
         // Flipping for GL.
-        MatrixExt.preVerticalFlip(mAdditionalTransform, 0.5f);
+        MatrixExt.preVerticalFlip(additionalTransform, 0.5f);
 
         // Rotation
-        preRotate(mAdditionalTransform, mRotationDegrees, 0.5f, 0.5f);
+        preRotate(additionalTransform, cameraInputInfo.getRotationDegrees(), 0.5f, 0.5f);
 
         // Mirroring
-        if (mMirroring) {
-            Matrix.translateM(mAdditionalTransform, 0, 1, 0f, 0f);
-            Matrix.scaleM(mAdditionalTransform, 0, -1, 1f, 1f);
+        if (cameraInputInfo.getMirroring()) {
+            Matrix.translateM(additionalTransform, 0, 1, 0f, 0f);
+            Matrix.scaleM(additionalTransform, 0, -1, 1f, 1f);
         }
 
         // Crop
         // Rotate the size and cropRect, and mirror the cropRect.
-        Size rotatedSize = rotateSize(mInputSize, mRotationDegrees);
-        android.graphics.Matrix imageTransform = getRectToRect(sizeToRectF(mInputSize),
-                sizeToRectF(rotatedSize), mRotationDegrees, mMirroring);
-        RectF rotatedCroppedRect = new RectF(mInputCropRect);
+        Size rotatedSize = rotateSize(cameraInputInfo.getInputSize(),
+                cameraInputInfo.getRotationDegrees());
+        android.graphics.Matrix imageTransform = getRectToRect(sizeToRectF(
+                cameraInputInfo.getInputSize()),
+                sizeToRectF(rotatedSize),
+                cameraInputInfo.getRotationDegrees(),
+                cameraInputInfo.getMirroring());
+        RectF rotatedCroppedRect = new RectF(cameraInputInfo.getInputCropRect());
         imageTransform.mapRect(rotatedCroppedRect);
         // According to the rotated size and cropRect, compute the normalized offset and the scale
         // of X and Y.
@@ -328,50 +358,51 @@
         float scaleX = rotatedCroppedRect.width() / rotatedSize.getWidth();
         float scaleY = rotatedCroppedRect.height() / rotatedSize.getHeight();
         // Move to the new left-bottom position and apply the scale.
-        Matrix.translateM(mAdditionalTransform, 0, offsetX, offsetY, 0f);
-        Matrix.scaleM(mAdditionalTransform, 0, scaleX, scaleY, 1f);
+        Matrix.translateM(additionalTransform, 0, offsetX, offsetY, 0f);
+        Matrix.scaleM(additionalTransform, 0, scaleX, scaleY, 1f);
 
         // Step 2: calculate the inverted texture transform: A^-1
-        calculateInvertedTextureTransform();
+        calculateInvertedTextureTransform(invertedTransform, cameraInputInfo.getCameraInternal());
 
         // Step 3: calculate the additional transform: B = A^-1 * A * B
-        Matrix.multiplyMM(mAdditionalTransform, 0, mInvertedTextureTransform, 0,
-                mAdditionalTransform, 0);
+        Matrix.multiplyMM(additionalTransform, 0, invertedTransform, 0,
+                additionalTransform, 0);
     }
 
     /**
-     * Calculates the inverted texture transform and saves it to
-     * {@link #mInvertedTextureTransform}.
+     * Calculates the inverted texture transform and saves it to invertedTextureTransform.
      *
      * <p>This method predicts the value of {@link SurfaceTexture#getTransformMatrix} based on
      * camera characteristics then invert it. The result is used to remove the texture transform
      * from overall transformation.
      */
-    private void calculateInvertedTextureTransform() {
-        Matrix.setIdentityM(mInvertedTextureTransform, 0);
+    private static void calculateInvertedTextureTransform(
+            @NonNull float[] invertedTextureTransform,
+            @Nullable CameraInternal cameraInternal) {
+        Matrix.setIdentityM(invertedTextureTransform, 0);
 
         // Flip for GL. SurfaceTexture#getTransformMatrix always contains this flipping regardless
         // of whether it has the camera transform.
-        MatrixExt.preVerticalFlip(mInvertedTextureTransform, 0.5f);
+        MatrixExt.preVerticalFlip(invertedTextureTransform, 0.5f);
 
         // Applies the camera sensor orientation if the input surface contains camera transform.
-        if (mCameraInternal != null) {
-            checkState(mCameraInternal.getHasTransform(), "Camera has no transform.");
+        if (cameraInternal != null) {
+            checkState(cameraInternal.getHasTransform(), "Camera has no transform.");
 
             // Rotation
-            preRotate(mInvertedTextureTransform,
-                    mCameraInternal.getCameraInfo().getSensorRotationDegrees(),
+            preRotate(invertedTextureTransform,
+                    cameraInternal.getCameraInfo().getSensorRotationDegrees(),
                     0.5f,
                     0.5f);
 
             // Mirroring
-            if (mCameraInternal.isFrontFacing()) {
-                Matrix.translateM(mInvertedTextureTransform, 0, 1, 0f, 0f);
-                Matrix.scaleM(mInvertedTextureTransform, 0, -1, 1f, 1f);
+            if (cameraInternal.isFrontFacing()) {
+                Matrix.translateM(invertedTextureTransform, 0, 1, 0f, 0f);
+                Matrix.scaleM(invertedTextureTransform, 0, -1, 1f, 1f);
             }
         }
 
         // Invert the matrix so it can be used to "undo" the SurfaceTexture#getTransformMatrix.
-        Matrix.invertM(mInvertedTextureTransform, 0, mInvertedTextureTransform, 0);
+        Matrix.invertM(invertedTextureTransform, 0, invertedTextureTransform, 0);
     }
 }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/processing/SurfaceProcessorNode.java b/camera/camera-core/src/main/java/androidx/camera/core/processing/SurfaceProcessorNode.java
index ba2d31e..9bf6d75 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/processing/SurfaceProcessorNode.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/processing/SurfaceProcessorNode.java
@@ -208,13 +208,16 @@
     private void createAndSendSurfaceOutput(@NonNull SurfaceEdge input,
             Map.Entry<OutConfig, SurfaceEdge> output) {
         SurfaceEdge outputEdge = output.getValue();
-        ListenableFuture<SurfaceOutput> future = outputEdge.createSurfaceOutputFuture(
+        SurfaceOutput.CameraInputInfo cameraInputInfo = SurfaceOutput.CameraInputInfo.of(
                 input.getStreamSpec().getResolution(),
-                output.getKey().getFormat(),
                 output.getKey().getCropRect(),
+                input.hasCameraTransform() ? mCameraInternal : null,
                 output.getKey().getRotationDegrees(),
-                output.getKey().isMirroring(),
-                input.hasCameraTransform() ? mCameraInternal : null);
+                output.getKey().isMirroring());
+        ListenableFuture<SurfaceOutput> future = outputEdge.createSurfaceOutputFuture(
+                output.getKey().getFormat(),
+                cameraInputInfo,
+                null);
         Futures.addCallback(future, new FutureCallback<SurfaceOutput>() {
             @Override
             public void onSuccess(@Nullable SurfaceOutput output) {
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/processing/concurrent/DualOpenGlRenderer.java b/camera/camera-core/src/main/java/androidx/camera/core/processing/concurrent/DualOpenGlRenderer.java
new file mode 100644
index 0000000..8576549
--- /dev/null
+++ b/camera/camera-core/src/main/java/androidx/camera/core/processing/concurrent/DualOpenGlRenderer.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.core.processing.concurrent;
+
+import static androidx.camera.core.processing.util.GLUtils.NO_OUTPUT_SURFACE;
+import static androidx.camera.core.processing.util.GLUtils.checkGlErrorOrThrow;
+import static androidx.camera.core.processing.util.GLUtils.checkGlThreadOrThrow;
+import static androidx.camera.core.processing.util.GLUtils.checkInitializedOrThrow;
+import static androidx.camera.core.processing.util.GLUtils.create4x4IdentityMatrix;
+import static androidx.camera.core.processing.util.GLUtils.createTexture;
+
+import android.graphics.SurfaceTexture;
+import android.opengl.EGL14;
+import android.opengl.EGLExt;
+import android.opengl.GLES20;
+import android.opengl.GLES30;
+import android.opengl.Matrix;
+import android.util.Size;
+import android.view.Surface;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.WorkerThread;
+import androidx.camera.core.DynamicRange;
+import androidx.camera.core.LayoutSettings;
+import androidx.camera.core.Logger;
+import androidx.camera.core.SurfaceOutput;
+import androidx.camera.core.processing.OpenGlRenderer;
+import androidx.camera.core.processing.ShaderProvider;
+import androidx.camera.core.processing.util.GraphicDeviceInfo;
+import androidx.camera.core.processing.util.OutputSurface;
+
+/**
+ * An internal augmented {@link OpenGlRenderer} for dual concurrent cameras.
+ */
+@WorkerThread
+public final class DualOpenGlRenderer extends OpenGlRenderer {
+
+    private static final String TAG = "DualOpenGlRenderer";
+
+    private int mPrimaryExternalTextureId = -1;
+    private int mSecondaryExternalTextureId = -1;
+
+    @NonNull
+    private final LayoutSettings mPrimaryLayoutSettings;
+    @NonNull
+    private final LayoutSettings mSecondaryLayoutSettings;
+
+    public DualOpenGlRenderer(
+            @NonNull LayoutSettings primaryLayoutSettings,
+            @NonNull LayoutSettings secondaryLayoutSettings) {
+        mPrimaryLayoutSettings = primaryLayoutSettings;
+        mSecondaryLayoutSettings = secondaryLayoutSettings;
+    }
+
+    @NonNull
+    @Override
+    public GraphicDeviceInfo init(@NonNull DynamicRange dynamicRange,
+            @NonNull ShaderProvider shaderProvider) {
+        GraphicDeviceInfo graphicDeviceInfo = super.init(dynamicRange, shaderProvider);
+        mPrimaryExternalTextureId = createTexture();
+        mSecondaryExternalTextureId = createTexture();
+        return graphicDeviceInfo;
+    }
+
+    @Override
+    public void release() {
+        super.release();
+        mPrimaryExternalTextureId = -1;
+        mSecondaryExternalTextureId = -1;
+    }
+
+    /**
+     * Gets the texture name.
+     *
+     * @return the texture name
+     * @throws IllegalStateException if the renderer is not initialized or the caller doesn't run
+     *                               on the GL thread.
+     */
+    public int getTextureName(boolean isPrimary) {
+        checkInitializedOrThrow(mInitialized, true);
+        checkGlThreadOrThrow(mGlThread);
+
+        return isPrimary ? mPrimaryExternalTextureId : mSecondaryExternalTextureId;
+    }
+
+    /**
+     * Renders the texture image to the output surface.
+     *
+     * @throws IllegalStateException if the renderer is not initialized, the caller doesn't run
+     *                               on the GL thread or the surface is not registered by
+     *                               {@link #registerOutputSurface(Surface)}.
+     */
+    public void render(long timestampNs,
+            @NonNull Surface surface,
+            @NonNull SurfaceOutput surfaceOutput,
+            @NonNull SurfaceTexture primarySurfaceTexture,
+            @NonNull SurfaceTexture secondarySurfaceTexture) {
+        checkInitializedOrThrow(mInitialized, true);
+        checkGlThreadOrThrow(mGlThread);
+
+        OutputSurface outputSurface = getOutSurfaceOrThrow(surface);
+
+        if (outputSurface == NO_OUTPUT_SURFACE) {
+            outputSurface = createOutputSurfaceInternal(surface);
+            if (outputSurface == null) {
+                return;
+            }
+
+            mOutputSurfaceMap.put(surface, outputSurface);
+        }
+
+        if (surface != mCurrentSurface) {
+            makeCurrent(outputSurface.getEglSurface());
+            mCurrentSurface = surface;
+        }
+
+        GLES30.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
+        // Primary Camera
+        renderInternal(outputSurface, surfaceOutput, primarySurfaceTexture,
+                mPrimaryLayoutSettings, mPrimaryExternalTextureId, true);
+        // Secondary Camera
+        // Only use primary camera info for output surface
+        renderInternal(outputSurface, surfaceOutput, secondarySurfaceTexture,
+                mSecondaryLayoutSettings, mSecondaryExternalTextureId, true);
+
+        EGLExt.eglPresentationTimeANDROID(mEglDisplay, outputSurface.getEglSurface(), timestampNs);
+
+        if (!EGL14.eglSwapBuffers(mEglDisplay, outputSurface.getEglSurface())) {
+            Logger.w(TAG, "Failed to swap buffers with EGL error: 0x" + Integer.toHexString(
+                    EGL14.eglGetError()));
+            removeOutputSurfaceInternal(surface, false);
+        }
+    }
+
+    private void renderInternal(
+            @NonNull OutputSurface outputSurface,
+            @NonNull SurfaceOutput surfaceOutput,
+            @NonNull SurfaceTexture surfaceTexture,
+            @NonNull LayoutSettings layoutSettings,
+            int externalTextureId,
+            boolean isPrimary) {
+        useAndConfigureProgram(externalTextureId);
+        GLES20.glViewport(0, 0, outputSurface.getWidth(),
+                outputSurface.getHeight());
+        GLES20.glScissor(0, 0, outputSurface.getWidth(),
+                outputSurface.getHeight());
+
+        float[] textureTransform = new float[16];
+        surfaceTexture.getTransformMatrix(textureTransform);
+
+        float[] surfaceOutputMatrix = new float[16];
+        surfaceOutput.updateTransformMatrix(
+                surfaceOutputMatrix, textureTransform, isPrimary);
+
+        GLES20.glUniformMatrix4fv(mTexMatrixLoc,
+                /*count=*/1, /*transpose=*/false, surfaceOutputMatrix,
+                /*offset=*/0);
+        checkGlErrorOrThrow("glUniformMatrix4fv");
+
+        float[] transTransform = getTransformMatrix(
+                new Size((int) (outputSurface.getWidth() * layoutSettings.getWidth()),
+                        (int) (outputSurface.getHeight() * layoutSettings.getHeight())),
+                new Size(outputSurface.getWidth(), outputSurface.getHeight()),
+                layoutSettings);
+        GLES20.glUniformMatrix4fv(mTransMatrixLoc,
+                /*count=*/1, /*transpose=*/false, transTransform,
+                /*offset=*/0);
+
+        GLES20.glUniform1f(mAlphaScaleLoc, layoutSettings.getAlpha());
+        checkGlErrorOrThrow("glUniform1f");
+
+        GLES20.glEnable(GLES20.GL_BLEND);
+        GLES20.glBlendFuncSeparate(
+                /* srcRGB= */ GLES20.GL_SRC_ALPHA,
+                /* dstRGB= */ GLES20.GL_ONE_MINUS_SRC_ALPHA,
+                /* srcAlpha= */ GLES20.GL_ONE,
+                /* dstAlpha= */ GLES20.GL_ONE_MINUS_SRC_ALPHA);
+
+        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, /*firstVertex=*/0, /*vertexCount=*/4);
+        checkGlErrorOrThrow("glDrawArrays");
+
+        GLES20.glDisable(GLES20.GL_BLEND);
+    }
+
+    @NonNull
+    private static float[] getTransformMatrix(
+            @NonNull Size overlaySize,
+            @NonNull Size backgroundSize,
+            @NonNull LayoutSettings layoutSettings) {
+        float[] aspectRatioMatrix = create4x4IdentityMatrix();
+        float[] overlayFrameAnchorMatrix = create4x4IdentityMatrix();
+        float[] transformationMatrix = create4x4IdentityMatrix();
+
+        Matrix.scaleM(
+                aspectRatioMatrix,
+                /* mOffset= */ 0,
+                (float) overlaySize.getWidth() / backgroundSize.getWidth(),
+                (float) overlaySize.getHeight() / backgroundSize.getHeight(),
+                /* z= */ 1.0f);
+
+        // Translate the image.
+        Matrix.translateM(
+                overlayFrameAnchorMatrix,
+                /* mOffset= */ 0,
+                layoutSettings.getOffsetX() / layoutSettings.getWidth(),
+                layoutSettings.getOffsetY()  / layoutSettings.getHeight(),
+                /* z= */ 0.0f);
+
+        // Correct for aspect ratio of image in output frame.
+        Matrix.multiplyMM(
+                transformationMatrix,
+                /* resultOffset= */ 0,
+                aspectRatioMatrix,
+                /* lhsOffset= */ 0,
+                overlayFrameAnchorMatrix,
+                /* rhsOffset= */ 0);
+
+        return transformationMatrix;
+    }
+}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/processing/concurrent/DualOutConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/processing/concurrent/DualOutConfig.java
new file mode 100644
index 0000000..773c637
--- /dev/null
+++ b/camera/camera-core/src/main/java/androidx/camera/core/processing/concurrent/DualOutConfig.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.core.processing.concurrent;
+
+import androidx.annotation.NonNull;
+import androidx.camera.core.processing.util.OutConfig;
+
+import com.google.auto.value.AutoValue;
+
+/**
+ * An internal augmented {@link OutConfig} for dual concurrent cameras.
+ */
+@AutoValue
+public abstract class DualOutConfig {
+
+    /**
+     * Primary camera {@link OutConfig}.
+     */
+    @NonNull
+    public abstract OutConfig getPrimaryOutConfig();
+
+    /**
+     * Secondary camera {@link OutConfig}.
+     */
+    @NonNull
+    public abstract OutConfig getSecondaryOutConfig();
+
+    /**
+     * Creates {@link DualOutConfig}.
+     */
+    @NonNull
+    public static DualOutConfig of(
+            @NonNull OutConfig primaryOutConfig,
+            @NonNull OutConfig secondaryOutConfig) {
+        return new AutoValue_DualOutConfig(
+                primaryOutConfig, secondaryOutConfig);
+    }
+}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/processing/concurrent/DualSurfaceProcessor.java b/camera/camera-core/src/main/java/androidx/camera/core/processing/concurrent/DualSurfaceProcessor.java
new file mode 100644
index 0000000..d7fd7b7
--- /dev/null
+++ b/camera/camera-core/src/main/java/androidx/camera/core/processing/concurrent/DualSurfaceProcessor.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.core.processing.concurrent;
+
+import static androidx.camera.core.impl.ImageFormatConstants.INTERNAL_DEFINED_IMAGE_FORMAT_PRIVATE;
+
+import android.graphics.SurfaceTexture;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.view.Surface;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import androidx.annotation.WorkerThread;
+import androidx.camera.core.DynamicRange;
+import androidx.camera.core.LayoutSettings;
+import androidx.camera.core.Logger;
+import androidx.camera.core.ProcessingException;
+import androidx.camera.core.SurfaceOutput;
+import androidx.camera.core.SurfaceProcessor;
+import androidx.camera.core.SurfaceRequest;
+import androidx.camera.core.impl.utils.executor.CameraXExecutors;
+import androidx.camera.core.processing.DefaultSurfaceProcessor;
+import androidx.camera.core.processing.ShaderProvider;
+import androidx.camera.core.processing.SurfaceProcessorInternal;
+import androidx.concurrent.futures.CallbackToFutureAdapter;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+import kotlin.jvm.functions.Function3;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Dual camera's implementation of {@link SurfaceProcessor}.
+ *
+ * <p>It wraps two {@link SurfaceTexture} for both primary and secondary cameras.
+ */
+public class DualSurfaceProcessor implements SurfaceProcessorInternal,
+        SurfaceTexture.OnFrameAvailableListener {
+
+    private static final String TAG = "DualSurfaceProcessor";
+    private final DualOpenGlRenderer mGlRenderer;
+    @VisibleForTesting
+    final HandlerThread mGlThread;
+    private final Executor mGlExecutor;
+    @VisibleForTesting
+    final Handler mGlHandler;
+    private int mInputSurfaceCount = 0;
+    private boolean mIsReleased = false;
+    private final AtomicBoolean mIsReleaseRequested = new AtomicBoolean(false);
+    // Map of current set of available outputs. Only access this on GL thread.
+    @SuppressWarnings("WeakerAccess") /* synthetic access */
+    final Map<SurfaceOutput, Surface> mOutputSurfaces = new LinkedHashMap<>();
+
+    @Nullable
+    private SurfaceTexture mPrimarySurfaceTexture;
+    @Nullable
+    private SurfaceTexture mSecondarySurfaceTexture;
+
+    DualSurfaceProcessor(@NonNull DynamicRange dynamicRange,
+            @NonNull LayoutSettings primaryLayoutSettings,
+            @NonNull LayoutSettings secondaryLayoutSettings) {
+        this(dynamicRange, ShaderProvider.DEFAULT, primaryLayoutSettings, secondaryLayoutSettings);
+    }
+
+    DualSurfaceProcessor(
+            @NonNull DynamicRange dynamicRange,
+            @NonNull ShaderProvider shaderProvider,
+            @NonNull LayoutSettings primaryLayoutSettings,
+            @NonNull LayoutSettings secondaryLayoutSettings) {
+        mGlThread = new HandlerThread("GL Thread");
+        mGlThread.start();
+        mGlHandler = new Handler(mGlThread.getLooper());
+        mGlExecutor = CameraXExecutors.newHandlerExecutor(mGlHandler);
+        mGlRenderer = new DualOpenGlRenderer(primaryLayoutSettings, secondaryLayoutSettings);
+        try {
+            initGlRenderer(dynamicRange, shaderProvider);
+        } catch (RuntimeException e) {
+            release();
+            throw e;
+        }
+    }
+
+    @Override
+    public void onInputSurface(@NonNull SurfaceRequest surfaceRequest)
+            throws ProcessingException {
+        if (mIsReleaseRequested.get()) {
+            surfaceRequest.willNotProvideSurface();
+            return;
+        }
+        executeSafely(() -> {
+            mInputSurfaceCount++;
+            SurfaceTexture surfaceTexture = new SurfaceTexture(
+                    mGlRenderer.getTextureName(surfaceRequest.isPrimary()));
+            surfaceTexture.setDefaultBufferSize(surfaceRequest.getResolution().getWidth(),
+                    surfaceRequest.getResolution().getHeight());
+            Surface surface = new Surface(surfaceTexture);
+            surfaceRequest.provideSurface(surface, mGlExecutor, result -> {
+                surfaceTexture.setOnFrameAvailableListener(null);
+                surfaceTexture.release();
+                surface.release();
+                mInputSurfaceCount--;
+                checkReadyToRelease();
+            });
+            if (surfaceRequest.isPrimary()) {
+                mPrimarySurfaceTexture = surfaceTexture;
+                // Only render when primary camera frames come in
+                surfaceTexture.setOnFrameAvailableListener(this, mGlHandler);
+            } else {
+                mSecondarySurfaceTexture = surfaceTexture;
+            }
+        }, surfaceRequest::willNotProvideSurface);
+    }
+
+    @Override
+    public void onOutputSurface(@NonNull SurfaceOutput surfaceOutput) throws ProcessingException {
+        if (mIsReleaseRequested.get()) {
+            surfaceOutput.close();
+            return;
+        }
+        executeSafely(() -> {
+            Surface surface = surfaceOutput.getSurface(mGlExecutor, event -> {
+                surfaceOutput.close();
+                Surface removedSurface = mOutputSurfaces.remove(surfaceOutput);
+                if (removedSurface != null) {
+                    mGlRenderer.unregisterOutputSurface(removedSurface);
+                }
+            });
+            mGlRenderer.registerOutputSurface(surface);
+            mOutputSurfaces.put(surfaceOutput, surface);
+        }, surfaceOutput::close);
+    }
+
+    @Override
+    public void release() {
+        if (mIsReleaseRequested.getAndSet(true)) {
+            return;
+        }
+        executeSafely(() -> {
+            mIsReleased = true;
+            checkReadyToRelease();
+        });
+    }
+
+    @Override
+    public void onFrameAvailable(SurfaceTexture surfaceTexture) {
+        if (mIsReleaseRequested.get()) {
+            // Ignore frame update if released.
+            return;
+        }
+        if (mPrimarySurfaceTexture == null || mSecondarySurfaceTexture == null) {
+            return;
+        }
+        mPrimarySurfaceTexture.updateTexImage();
+        mSecondarySurfaceTexture.updateTexImage();
+        for (Map.Entry<SurfaceOutput, Surface> entry : mOutputSurfaces.entrySet()) {
+            Surface surface = entry.getValue();
+            SurfaceOutput surfaceOutput = entry.getKey();
+            if (surfaceOutput.getFormat() == INTERNAL_DEFINED_IMAGE_FORMAT_PRIVATE) {
+                // Render GPU output directly.
+                try {
+                    mGlRenderer.render(
+                            surfaceTexture.getTimestamp(),
+                            surface,
+                            surfaceOutput,
+                            mPrimarySurfaceTexture,
+                            mSecondarySurfaceTexture);
+                } catch (RuntimeException e) {
+                    // This should not happen. However, when it happens, we catch the exception
+                    // to prevent the crash.
+                    Logger.e(TAG, "Failed to render with OpenGL.", e);
+                }
+            }
+        }
+    }
+
+    private void initGlRenderer(
+            @NonNull DynamicRange dynamicRange,
+            @NonNull ShaderProvider shaderProvider) {
+        ListenableFuture<Void> initFuture = CallbackToFutureAdapter.getFuture(completer -> {
+            executeSafely(() -> {
+                try {
+                    mGlRenderer.init(dynamicRange, shaderProvider);
+                    completer.set(null);
+                } catch (RuntimeException e) {
+                    completer.setException(e);
+                }
+            });
+            return "Init GlRenderer";
+        });
+        try {
+            initFuture.get();
+        } catch (ExecutionException | InterruptedException e) {
+            // If the cause is a runtime exception, throw it directly. Otherwise convert to runtime
+            // exception and throw.
+            Throwable cause = e instanceof ExecutionException ? e.getCause() : e;
+            if (cause instanceof RuntimeException) {
+                throw (RuntimeException) cause;
+            } else {
+                throw new IllegalStateException("Failed to create DefaultSurfaceProcessor", cause);
+            }
+        }
+    }
+
+    private void executeSafely(@NonNull Runnable runnable) {
+        executeSafely(runnable, () -> {
+            // Do nothing.
+        });
+    }
+
+    private void executeSafely(@NonNull Runnable runnable, @NonNull Runnable onFailure) {
+        try {
+            mGlExecutor.execute(() -> {
+                if (mIsReleased) {
+                    onFailure.run();
+                } else {
+                    runnable.run();
+                }
+            });
+        } catch (RejectedExecutionException e) {
+            Logger.w(TAG, "Unable to executor runnable", e);
+            onFailure.run();
+        }
+    }
+
+    @WorkerThread
+    private void checkReadyToRelease() {
+        if (mIsReleased && mInputSurfaceCount == 0) {
+            // Once release is called, we can stop sending frame to output surfaces.
+            for (SurfaceOutput surfaceOutput : mOutputSurfaces.keySet()) {
+                surfaceOutput.close();
+            }
+            mOutputSurfaces.clear();
+            mGlRenderer.release();
+            mGlThread.quit();
+        }
+    }
+
+    public static class Factory {
+        private Factory() {
+        }
+
+        private static Function3<DynamicRange, LayoutSettings,
+                LayoutSettings, SurfaceProcessorInternal> sSupplier = DualSurfaceProcessor::new;
+
+        /**
+         * Creates a new {@link DefaultSurfaceProcessor} with no-op shader.
+         */
+        @NonNull
+        public static SurfaceProcessorInternal newInstance(
+                @NonNull DynamicRange dynamicRange,
+                @NonNull LayoutSettings primaryLayoutSettings,
+                @NonNull LayoutSettings secondaryLayoutSettings) {
+            return sSupplier.invoke(dynamicRange, primaryLayoutSettings, secondaryLayoutSettings);
+        }
+
+        /**
+         * Overrides the {@link DefaultSurfaceProcessor} supplier for testing.
+         */
+        @VisibleForTesting
+        public static void setSupplier(
+                @NonNull Function3<DynamicRange,
+                        LayoutSettings,
+                        LayoutSettings,
+                        SurfaceProcessorInternal> supplier) {
+            sSupplier = supplier;
+        }
+    }
+}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/processing/concurrent/DualSurfaceProcessorNode.java b/camera/camera-core/src/main/java/androidx/camera/core/processing/concurrent/DualSurfaceProcessorNode.java
new file mode 100644
index 0000000..f082492
--- /dev/null
+++ b/camera/camera-core/src/main/java/androidx/camera/core/processing/concurrent/DualSurfaceProcessorNode.java
@@ -0,0 +1,325 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.core.processing.concurrent;
+
+import static androidx.camera.core.impl.ImageOutputConfig.ROTATION_NOT_SPECIFIED;
+import static androidx.camera.core.impl.utils.Threads.runOnMain;
+import static androidx.camera.core.impl.utils.TransformUtils.getRotatedSize;
+import static androidx.camera.core.impl.utils.TransformUtils.isAspectRatioMatchingWithRoundingError;
+import static androidx.camera.core.impl.utils.TransformUtils.sizeToRect;
+import static androidx.camera.core.impl.utils.executor.CameraXExecutors.mainThreadExecutor;
+import static androidx.camera.core.processing.TargetUtils.getHumanReadableName;
+import static androidx.core.util.Preconditions.checkArgument;
+
+import android.graphics.Rect;
+import android.util.Size;
+
+import androidx.annotation.MainThread;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.camera.core.CameraEffect;
+import androidx.camera.core.Logger;
+import androidx.camera.core.ProcessingException;
+import androidx.camera.core.SurfaceOutput;
+import androidx.camera.core.SurfaceProcessor;
+import androidx.camera.core.SurfaceRequest;
+import androidx.camera.core.impl.CameraInternal;
+import androidx.camera.core.impl.StreamSpec;
+import androidx.camera.core.impl.utils.Threads;
+import androidx.camera.core.impl.utils.futures.FutureCallback;
+import androidx.camera.core.impl.utils.futures.Futures;
+import androidx.camera.core.processing.Node;
+import androidx.camera.core.processing.SurfaceEdge;
+import androidx.camera.core.processing.SurfaceProcessorInternal;
+import androidx.camera.core.processing.SurfaceProcessorNode;
+import androidx.camera.core.processing.util.OutConfig;
+import androidx.core.util.Preconditions;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.util.concurrent.ListenableFuture;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CancellationException;
+
+/**
+ * An internal augmented {@link SurfaceProcessorNode} for dual concurrent cameras.
+ */
+@SuppressWarnings("UnusedVariable")
+public class DualSurfaceProcessorNode implements
+        Node<DualSurfaceProcessorNode.In, DualSurfaceProcessorNode.Out> {
+
+    private static final String TAG = "DualSurfaceProcessorNode";
+
+    @NonNull
+    final SurfaceProcessorInternal mSurfaceProcessor;
+    @NonNull
+    final CameraInternal mPrimaryCameraInternal;
+    @NonNull
+    final CameraInternal mSecondaryCameraInternal;
+    // Guarded by main thread.
+    @Nullable
+    private Out mOutput;
+    @Nullable
+    private In mInput;
+
+    /**
+     * Constructs the {@link DualSurfaceProcessorNode}.
+     *
+     * @param primaryCameraInternal the associated primary camera instance.
+     * @param secondaryCameraInternal the associated secondary camera instance.
+     * @param surfaceProcessor the interface to wrap around.
+     */
+    public DualSurfaceProcessorNode(
+            @NonNull CameraInternal primaryCameraInternal,
+            @NonNull CameraInternal secondaryCameraInternal,
+            @NonNull SurfaceProcessorInternal surfaceProcessor) {
+        mPrimaryCameraInternal = primaryCameraInternal;
+        mSecondaryCameraInternal = secondaryCameraInternal;
+        mSurfaceProcessor = surfaceProcessor;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    @NonNull
+    @MainThread
+    public Out transform(@NonNull In in) {
+        Threads.checkMainThread();
+        mInput = in;
+        mOutput = new Out();
+
+        SurfaceEdge primaryInputSurfaceEdge = mInput.getPrimarySurfaceEdge();
+        SurfaceEdge secondaryInputSurfaceEdge = mInput.getSecondarySurfaceEdge();
+
+        for (DualOutConfig config : mInput.getOutConfigs()) {
+            mOutput.put(config, transformSingleOutput(
+                    primaryInputSurfaceEdge,
+                    config.getPrimaryOutConfig()));
+        }
+        sendSurfaceRequest(mPrimaryCameraInternal, primaryInputSurfaceEdge, mOutput, true);
+        sendSurfaceRequest(mSecondaryCameraInternal, secondaryInputSurfaceEdge, mOutput, false);
+
+        sendSurfaceOutputs(mPrimaryCameraInternal, mSecondaryCameraInternal,
+                primaryInputSurfaceEdge, secondaryInputSurfaceEdge, mOutput);
+        return mOutput;
+    }
+
+    @NonNull
+    private SurfaceEdge transformSingleOutput(@NonNull SurfaceEdge input,
+            @NonNull OutConfig outConfig) {
+        SurfaceEdge outputSurface;
+        Rect cropRect = outConfig.getCropRect();
+        int rotationDegrees = outConfig.getRotationDegrees();
+        boolean mirroring = outConfig.isMirroring();
+
+        // Calculate sensorToBufferTransform
+        android.graphics.Matrix sensorToBufferTransform =
+                new android.graphics.Matrix();
+
+        // The aspect ratio of the output must match the aspect ratio of the crop rect. Otherwise
+        // the output will be stretched.
+        Size rotatedCropSize = getRotatedSize(cropRect, rotationDegrees);
+        checkArgument(isAspectRatioMatchingWithRoundingError(rotatedCropSize, outConfig.getSize()));
+
+        // Calculate the crop rect.
+        Rect newCropRect = sizeToRect(outConfig.getSize());
+
+        // Copy the stream spec from the input to the output, except for the resolution.
+        StreamSpec streamSpec = input.getStreamSpec().toBuilder().setResolution(
+                outConfig.getSize()).build();
+
+        outputSurface = new SurfaceEdge(
+                outConfig.getTargets(),
+                outConfig.getFormat(),
+                streamSpec,
+                sensorToBufferTransform,
+                // The Surface transform cannot be carried over during buffer copy.
+                /*hasCameraTransform=*/false,
+                newCropRect,
+                /*rotationDegrees=*/input.getRotationDegrees() - rotationDegrees,
+                // Once copied, the target rotation is no longer useful.
+                /*targetRotation*/ ROTATION_NOT_SPECIFIED,
+                /*mirroring=*/input.isMirroring() != mirroring);
+
+        return outputSurface;
+    }
+
+    /**
+     * Creates {@link SurfaceRequest} and send it to {@link SurfaceProcessor}.
+     */
+    private void sendSurfaceRequest(
+            @NonNull CameraInternal cameraInternal,
+            @NonNull SurfaceEdge input,
+            @NonNull Map<DualOutConfig, SurfaceEdge> outputs,
+            boolean isPrimary) {
+        SurfaceRequest surfaceRequest = input.createSurfaceRequest(cameraInternal, isPrimary);
+        // TODO(b/348402401): Different from SurfaceProcessorNode, we don't support device rotation
+        //  for dual camera recording.
+        try {
+            mSurfaceProcessor.onInputSurface(surfaceRequest);
+        } catch (ProcessingException e) {
+            Logger.e(TAG, "Failed to send SurfaceRequest to SurfaceProcessor.", e);
+        }
+    }
+
+    /**
+     * Creates all {@link SurfaceOutput} and send them to {@link SurfaceProcessor}.
+     */
+    private void sendSurfaceOutputs(
+            @NonNull CameraInternal primaryCameraInternal,
+            @NonNull CameraInternal secondaryCameraInternal,
+            @NonNull SurfaceEdge primarySurfaceEdge,
+            @NonNull SurfaceEdge secondarySurfaceEdge,
+            @NonNull Map<DualOutConfig, SurfaceEdge> outputs) {
+        for (Map.Entry<DualOutConfig, SurfaceEdge> output : outputs.entrySet()) {
+            createAndSendSurfaceOutput(
+                    primaryCameraInternal,
+                    secondaryCameraInternal,
+                    primarySurfaceEdge,
+                    secondarySurfaceEdge,
+                    output);
+            // Send the new surface to SurfaceProcessor when it resets.
+            output.getValue().addOnInvalidatedListener(
+                    () -> createAndSendSurfaceOutput(
+                            primaryCameraInternal, secondaryCameraInternal,
+                            primarySurfaceEdge, secondarySurfaceEdge, output));
+        }
+    }
+
+    /**
+     * Creates a single {@link SurfaceOutput} and send it to {@link SurfaceProcessor}.
+     */
+    private void createAndSendSurfaceOutput(
+            @NonNull CameraInternal primaryCameraInternal,
+            @NonNull CameraInternal secondaryCameraInternal,
+            @NonNull SurfaceEdge primarySurfaceEdge,
+            @NonNull SurfaceEdge secondarySurfaceEdge,
+            Map.Entry<DualOutConfig, SurfaceEdge> output) {
+        SurfaceEdge outputEdge = output.getValue();
+        SurfaceOutput.CameraInputInfo primaryCameraInputInfo = SurfaceOutput.CameraInputInfo.of(
+                primarySurfaceEdge.getStreamSpec().getResolution(),
+                output.getKey().getPrimaryOutConfig().getCropRect(),
+                primarySurfaceEdge.hasCameraTransform() ? primaryCameraInternal : null,
+                output.getKey().getPrimaryOutConfig().getRotationDegrees(),
+                output.getKey().getPrimaryOutConfig().isMirroring());
+        SurfaceOutput.CameraInputInfo secondaryCameraInputInfo = SurfaceOutput.CameraInputInfo.of(
+                secondarySurfaceEdge.getStreamSpec().getResolution(),
+                output.getKey().getSecondaryOutConfig().getCropRect(),
+                secondarySurfaceEdge.hasCameraTransform() ? secondaryCameraInternal : null,
+                output.getKey().getSecondaryOutConfig().getRotationDegrees(),
+                output.getKey().getSecondaryOutConfig().isMirroring());
+        ListenableFuture<SurfaceOutput> future = outputEdge.createSurfaceOutputFuture(
+                output.getKey().getPrimaryOutConfig().getFormat(),
+                primaryCameraInputInfo,
+                secondaryCameraInputInfo);
+        Futures.addCallback(future, new FutureCallback<SurfaceOutput>() {
+            @Override
+            public void onSuccess(@Nullable SurfaceOutput output) {
+                Preconditions.checkNotNull(output);
+                try {
+                    mSurfaceProcessor.onOutputSurface(output);
+                } catch (ProcessingException e) {
+                    Logger.e(TAG, "Failed to send SurfaceOutput to SurfaceProcessor.", e);
+                }
+            }
+
+            @Override
+            public void onFailure(@NonNull Throwable t) {
+                if (outputEdge.getTargets() == CameraEffect.VIDEO_CAPTURE
+                        && t instanceof CancellationException) {
+                    Logger.d(TAG, "Downstream VideoCapture failed to provide Surface.");
+                } else {
+                    Logger.w(TAG, "Downstream node failed to provide Surface. Target: "
+                            + getHumanReadableName(outputEdge.getTargets()), t);
+                }
+            }
+        }, mainThreadExecutor());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void release() {
+        mSurfaceProcessor.release();
+        // Required for b/309409701. For some reason, the cleanup posted on {@link #release()} is
+        // not executed in unit tests which causes failures.
+        runOnMain(() -> {
+            if (mOutput != null) {
+                for (SurfaceEdge surface : mOutput.values()) {
+                    // The output DeferrableSurface will later be terminated by the processor.
+                    surface.close();
+                }
+            }
+        });
+    }
+
+    /**
+     * The input of a {@link DualSurfaceProcessorNode}.
+     */
+    @AutoValue
+    public abstract static class In {
+
+        /**
+         * Gets the input stream from primary camera.
+         *
+         * <p> {@link DualSurfaceProcessorNode} supports dual camera streams.
+         */
+        @NonNull
+        public abstract SurfaceEdge getPrimarySurfaceEdge();
+
+        /**
+         * Gets the input stream from secondary camera.
+         *
+         * <p> {@link DualSurfaceProcessorNode} supports dual camera streams.
+         */
+        @NonNull
+        public abstract SurfaceEdge getSecondarySurfaceEdge();
+
+        /**
+         * Gets the config for generating output streams.
+         *
+         * <p>{@link DualSurfaceProcessorNode#transform} creates two {@link SurfaceEdge} per
+         * {@link DualOutConfig} in this list.
+         */
+        @SuppressWarnings("AutoValueImmutableFields")
+        @NonNull
+        public abstract List<DualOutConfig> getOutConfigs();
+
+        /**
+         * Creates a {@link In} instance.
+         */
+        @NonNull
+        public static In of(
+                @NonNull SurfaceEdge primaryEdge,
+                @NonNull SurfaceEdge secondaryEdge,
+                @NonNull List<DualOutConfig> configs) {
+            return new AutoValue_DualSurfaceProcessorNode_In(primaryEdge, secondaryEdge, configs);
+        }
+    }
+
+    /**
+     * The output of a {@link DualSurfaceProcessorNode}.
+     *
+     * <p>A map of {@link OutConfig} with their corresponding {@link SurfaceEdge}.
+     */
+    public static class Out extends HashMap<DualOutConfig, SurfaceEdge> {
+    }
+}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/processing/util/GLUtils.java b/camera/camera-core/src/main/java/androidx/camera/core/processing/util/GLUtils.java
index 80b77cc..c60f0dc 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/processing/util/GLUtils.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/processing/util/GLUtils.java
@@ -25,6 +25,7 @@
 import android.opengl.GLES11Ext;
 import android.opengl.GLES20;
 import android.opengl.GLES30;
+import android.opengl.Matrix;
 import android.util.Log;
 import android.util.Size;
 import android.view.Surface;
@@ -75,11 +76,12 @@
 
     public static final String DEFAULT_VERTEX_SHADER = String.format(Locale.US,
             "uniform mat4 uTexMatrix;\n"
+                    + "uniform mat4 uTransMatrix;\n"
                     + "attribute vec4 aPosition;\n"
                     + "attribute vec4 aTextureCoord;\n"
                     + "varying vec2 %s;\n"
                     + "void main() {\n"
-                    + "    gl_Position = aPosition;\n"
+                    + "    gl_Position = uTransMatrix * aPosition;\n"
                     + "    %s = (uTexMatrix * aTextureCoord).xy;\n"
                     + "}\n", VAR_TEXTURE_COORD, VAR_TEXTURE_COORD);
 
@@ -88,9 +90,10 @@
                     + "in vec4 aPosition;\n"
                     + "in vec4 aTextureCoord;\n"
                     + "uniform mat4 uTexMatrix;\n"
+                    + "uniform mat4 uTransMatrix;\n"
                     + "out vec2 %s;\n"
                     + "void main() {\n"
-                    + "  gl_Position = aPosition;\n"
+                    + "  gl_Position = uTransMatrix * aPosition;\n"
                     + "  %s = (uTexMatrix * aTextureCoord).xy;\n"
                     + "}\n", VAR_TEXTURE_COORD, VAR_TEXTURE_COORD);
 
@@ -99,8 +102,10 @@
                     + "precision mediump float;\n"
                     + "varying vec2 %s;\n"
                     + "uniform samplerExternalOES %s;\n"
+                    + "uniform float uAlphaScale;\n"
                     + "void main() {\n"
-                    + "    gl_FragColor = texture2D(%s, %s);\n"
+                    + "    vec4 src = texture2D(%s, %s);\n"
+                    + "    gl_FragColor = vec4(src.rgb, src.a * uAlphaScale);\n"
                     + "}\n", VAR_TEXTURE_COORD, VAR_TEXTURE, VAR_TEXTURE, VAR_TEXTURE_COORD);
 
     public static final String HDR_FRAGMENT_SHADER = String.format(Locale.US,
@@ -111,6 +116,7 @@
                     + "uniform samplerExternalOES %s;\n"
                     + "uniform __samplerExternal2DY2YEXT %s;\n"
                     + "uniform int uSamplerSelector;\n"
+                    + "uniform float uAlphaScale;\n"
                     + "in vec2 %s;\n"
                     + "out vec4 outColor;\n"
                     + "\n"
@@ -125,14 +131,14 @@
                     + "}\n"
                     + "\n"
                     + "void main() {\n"
+                    + "  vec4 src = vec4(0.0);\n"
                     + "  if (uSamplerSelector == %d) {\n"
-                    + "    outColor = texture(%s, %s);\n"
+                    + "    src = texture(%s, %s);\n"
                     + "  } else if (uSamplerSelector == %d) {\n"
                     + "    vec3 srcYuv = texture(%s, %s).xyz;\n"
-                    + "    outColor = vec4(yuvToRgb(srcYuv), 1.0);\n"
-                    + "  } else {\n"
-                    + "    outColor = vec4(0.0);\n"
+                    + "    src = vec4(yuvToRgb(srcYuv), 1.0);\n"
                     + "  }\n"
+                    + "  outColor = vec4(src.rgb, src.a * uAlphaScale);\n"
                     + "}",
             VAR_TEXTURE,
             VAR_TEXTURE_YUV,
@@ -370,6 +376,16 @@
     }
 
     /**
+     * Creates a 4x4 identity matrix.
+     */
+    @NonNull
+    public static float[] create4x4IdentityMatrix() {
+        float[] matrix = new float[16];
+        Matrix.setIdentityM(matrix, /* smOffset= */ 0);
+        return matrix;
+    }
+
+    /**
      * Checks the location error.
      */
     public static void checkLocationOrThrow(int location, @NonNull String label) {
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/StreamSharing.java b/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/StreamSharing.java
index da0f7f3..8afe48f 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/StreamSharing.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/StreamSharing.java
@@ -45,11 +45,13 @@
 import androidx.annotation.VisibleForTesting;
 import androidx.camera.core.CameraEffect;
 import androidx.camera.core.ImageCapture;
+import androidx.camera.core.LayoutSettings;
 import androidx.camera.core.MirrorMode;
 import androidx.camera.core.UseCase;
 import androidx.camera.core.impl.CameraInfoInternal;
 import androidx.camera.core.impl.CameraInternal;
 import androidx.camera.core.impl.Config;
+import androidx.camera.core.impl.DeferrableSurface;
 import androidx.camera.core.impl.ImageFormatConstants;
 import androidx.camera.core.impl.ImageOutputConfig;
 import androidx.camera.core.impl.MutableConfig;
@@ -63,6 +65,9 @@
 import androidx.camera.core.processing.DefaultSurfaceProcessor;
 import androidx.camera.core.processing.SurfaceEdge;
 import androidx.camera.core.processing.SurfaceProcessorNode;
+import androidx.camera.core.processing.concurrent.DualOutConfig;
+import androidx.camera.core.processing.concurrent.DualSurfaceProcessor;
+import androidx.camera.core.processing.concurrent.DualSurfaceProcessorNode;
 import androidx.camera.core.processing.util.OutConfig;
 
 import com.google.common.util.concurrent.ListenableFuture;
@@ -84,21 +89,41 @@
 
     @NonNull
     private final VirtualCameraAdapter mVirtualCameraAdapter;
+    // The layout settings of primary camera in dual camera case.
+    @NonNull
+    private final LayoutSettings mLayoutSettings;
+    // The layout settings of secondary camera in dual camera case.
+    @NonNull
+    private final LayoutSettings mSecondaryLayoutSettings;
     // Node that applies effect to the input.
     @Nullable
     private SurfaceProcessorNode mEffectNode;
     // Node that shares a single stream to multiple UseCases.
     @Nullable
     private SurfaceProcessorNode mSharingNode;
+    // Node that shares dual streams to multiple UseCases.
+    @Nullable
+    private DualSurfaceProcessorNode mDualSharingNode;
     // The input edge that connects to the camera.
     @Nullable
     private SurfaceEdge mCameraEdge;
+    // The input edge that connects to the secondary camera in dual camera case.
+    @Nullable
+    private SurfaceEdge mSecondaryCameraEdge;
     // The input edge of the sharing node.
     @Nullable
     private SurfaceEdge mSharingInputEdge;
+    // The input edge of the secondary sharing node in dual camera case.
+    @Nullable
+    private SurfaceEdge mSecondarySharingInputEdge;
 
     @SuppressWarnings("WeakerAccess") // Synthetic access
     SessionConfig.Builder mSessionConfigBuilder;
+    @SuppressWarnings("WeakerAccess") // Synthetic access
+    SessionConfig.Builder mSecondarySessionConfigBuilder;
+
+    @Nullable
+    private SessionConfig.CloseableErrorListener mCloseableErrorListener;
 
     private static StreamSharingConfig getDefaultConfig(Set<UseCase> children) {
         MutableConfig mutableConfig = new StreamSharingBuilder().getMutableConfig();
@@ -122,22 +147,28 @@
      * {@link UseCase}s, and a {@link UseCaseConfigFactory} for getting default {@link UseCase}
      * configurations.
      */
-    public StreamSharing(@NonNull CameraInternal parentCamera,
+    public StreamSharing(@NonNull CameraInternal camera,
+            @Nullable CameraInternal secondaryCamera,
+            @NonNull LayoutSettings layoutSettings,
+            @NonNull LayoutSettings secondaryLayoutSettings,
             @NonNull Set<UseCase> children,
             @NonNull UseCaseConfigFactory useCaseConfigFactory) {
         super(getDefaultConfig(children));
         mDefaultConfig = getDefaultConfig(children);
+        mLayoutSettings = layoutSettings;
+        mSecondaryLayoutSettings = secondaryLayoutSettings;
         mVirtualCameraAdapter = new VirtualCameraAdapter(
-                parentCamera, children, useCaseConfigFactory, (jpegQuality, rotationDegrees) -> {
-            SurfaceProcessorNode sharingNode = mSharingNode;
-            if (sharingNode != null) {
-                return sharingNode.getSurfaceProcessor().snapshot(
-                        jpegQuality, rotationDegrees);
-            } else {
-                return Futures.immediateFailedFuture(new Exception(
-                        "Failed to take picture: pipeline is not ready."));
-            }
-        });
+                camera, secondaryCamera, children, useCaseConfigFactory,
+                (jpegQuality, rotationDegrees) -> {
+                    SurfaceProcessorNode sharingNode = mSharingNode;
+                    if (sharingNode != null) {
+                        return sharingNode.getSurfaceProcessor().snapshot(
+                                jpegQuality, rotationDegrees);
+                    } else {
+                        return Futures.immediateFailedFuture(new Exception(
+                                "Failed to take picture: pipeline is not ready."));
+                    }
+                });
     }
 
     @Nullable
@@ -172,11 +203,16 @@
 
     @NonNull
     @Override
-    protected StreamSpec onSuggestedStreamSpecUpdated(@NonNull StreamSpec streamSpec) {
-        updateSessionConfig(createPipelineAndUpdateChildrenSpecs(
-                getCameraId(), getCurrentConfig(), streamSpec));
+    protected StreamSpec onSuggestedStreamSpecUpdated(
+            @NonNull StreamSpec primaryStreamSpec,
+            @Nullable StreamSpec secondaryStreamSpec) {
+        updateSessionConfig(
+                createPipelineAndUpdateChildrenSpecs(getCameraId(),
+                        getSecondaryCameraId(),
+                        getCurrentConfig(),
+                        primaryStreamSpec, secondaryStreamSpec));
         notifyActive();
-        return streamSpec;
+        return primaryStreamSpec;
     }
 
     /**
@@ -187,7 +223,7 @@
     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
     protected StreamSpec onSuggestedStreamSpecImplementationOptionsUpdated(@NonNull Config config) {
         mSessionConfigBuilder.addImplementationOptions(config);
-        updateSessionConfig(mSessionConfigBuilder.build());
+        updateSessionConfig(List.of(mSessionConfigBuilder.build()));
         return getAttachedStreamSpec().toBuilder().setImplementationOptions(config).build();
     }
 
@@ -234,52 +270,142 @@
 
     @NonNull
     @MainThread
-    private SessionConfig createPipelineAndUpdateChildrenSpecs(
+    private List<SessionConfig> createPipelineAndUpdateChildrenSpecs(
             @NonNull String cameraId,
+            @Nullable String secondaryCameraId,
             @NonNull UseCaseConfig<?> config,
-            @NonNull StreamSpec streamSpec) {
+            @NonNull StreamSpec primaryStreamSpec,
+            @Nullable StreamSpec secondaryStreamSpec) {
         checkMainThread();
-        CameraInternal camera = checkNotNull(getCamera());
-        // Create input edge and the node.
+
+        if (secondaryStreamSpec == null) {
+            // primary
+            createPrimaryCamera(cameraId, secondaryCameraId,
+                    config, primaryStreamSpec, null);
+
+            // sharing node
+            mSharingNode = getSharingNode(requireNonNull(getCamera()), primaryStreamSpec);
+
+            boolean isViewportSet = getViewPortCropRect() != null;
+            Map<UseCase, OutConfig> outConfigMap =
+                    mVirtualCameraAdapter.getChildrenOutConfigs(mSharingInputEdge,
+                            getTargetRotationInternal(), isViewportSet);
+            SurfaceProcessorNode.Out out = mSharingNode.transform(
+                    SurfaceProcessorNode.In.of(mSharingInputEdge,
+                            new ArrayList<>(outConfigMap.values())));
+
+            Map<UseCase, SurfaceEdge> outputEdges = new HashMap<>();
+            for (Map.Entry<UseCase, OutConfig> entry : outConfigMap.entrySet()) {
+                outputEdges.put(entry.getKey(), out.get(entry.getValue()));
+            }
+
+            mVirtualCameraAdapter.setChildrenEdges(outputEdges);
+
+            return List.of(mSessionConfigBuilder.build());
+        } else {
+            // primary
+            createPrimaryCamera(cameraId, secondaryCameraId,
+                    config, primaryStreamSpec, secondaryStreamSpec);
+
+            // secondary
+            createSecondaryCamera(cameraId, secondaryCameraId,
+                    config, primaryStreamSpec, secondaryStreamSpec);
+
+            // sharing node
+            mDualSharingNode = getDualSharingNode(
+                    getCamera(),
+                    getSecondaryCamera(),
+                    primaryStreamSpec, // use primary stream spec
+                    mLayoutSettings,
+                    mSecondaryLayoutSettings);
+            boolean isViewportSet = getViewPortCropRect() != null;
+            Map<UseCase, DualOutConfig> outConfigMap =
+                    mVirtualCameraAdapter.getChildrenOutConfigs(
+                            mSharingInputEdge,
+                            mSecondarySharingInputEdge,
+                            getTargetRotationInternal(),
+                            isViewportSet);
+            DualSurfaceProcessorNode.Out out = mDualSharingNode.transform(
+                    DualSurfaceProcessorNode.In.of(
+                            mSharingInputEdge,
+                            mSecondarySharingInputEdge,
+                            new ArrayList<>(outConfigMap.values())));
+
+            Map<UseCase, SurfaceEdge> outputEdges = new HashMap<>();
+            for (Map.Entry<UseCase, DualOutConfig> entry : outConfigMap.entrySet()) {
+                outputEdges.put(entry.getKey(), out.get(entry.getValue()));
+            }
+            mVirtualCameraAdapter.setChildrenEdges(outputEdges);
+
+            return List.of(mSessionConfigBuilder.build(),
+                    mSecondarySessionConfigBuilder.build());
+        }
+    }
+
+    private void createPrimaryCamera(
+            @NonNull String cameraId,
+            @Nullable String secondaryCameraId,
+            @NonNull UseCaseConfig<?> config,
+            @NonNull StreamSpec primaryStreamSpec,
+            @Nullable StreamSpec secondaryStreamSpec) {
         mCameraEdge = new SurfaceEdge(
                 /*targets=*/PREVIEW | VIDEO_CAPTURE,
                 INTERNAL_DEFINED_IMAGE_FORMAT_PRIVATE,
-                streamSpec,
+                primaryStreamSpec,
                 getSensorToBufferTransformMatrix(),
-                camera.getHasTransform(),
-                requireNonNull(getCropRect(streamSpec.getResolution())),
-                getRelativeRotation(camera), // Rotation can be overridden by children.
-                // Once copied, the target rotation will no longer be useful.
+                requireNonNull(getCamera()).getHasTransform(),
+                requireNonNull(getCropRect(primaryStreamSpec.getResolution())),
+                getRelativeRotation(requireNonNull(getCamera())),
                 ImageOutputConfig.ROTATION_NOT_SPECIFIED,
-                isMirroringRequired(camera)); // Mirroring can be overridden by children.
-        mSharingInputEdge = getSharingInputEdge(mCameraEdge, camera);
+                isMirroringRequired(requireNonNull(getCamera())));
+        mSharingInputEdge = getSharingInputEdge(mCameraEdge, requireNonNull(getCamera()));
 
-        mSharingNode = getSharingNode(camera, streamSpec);
+        mSessionConfigBuilder = createSessionConfigBuilder(
+                mCameraEdge, config, primaryStreamSpec);
+        addCameraErrorListener(mSessionConfigBuilder,
+                cameraId, secondaryCameraId, config,
+                primaryStreamSpec, secondaryStreamSpec);
+    }
 
-        // Transform the input based on virtual camera configuration.
-        boolean isViewportSet = getViewPortCropRect() != null;
-        Map<UseCase, OutConfig> outConfigMap =
-                mVirtualCameraAdapter.getChildrenOutConfigs(mSharingInputEdge,
-                        getTargetRotationInternal(), isViewportSet);
-        SurfaceProcessorNode.Out out = mSharingNode.transform(
-                SurfaceProcessorNode.In.of(mSharingInputEdge,
-                        new ArrayList<>(outConfigMap.values())));
+    private void createSecondaryCamera(
+            @NonNull String cameraId,
+            @Nullable String secondaryCameraId,
+            @NonNull UseCaseConfig<?> config,
+            @NonNull StreamSpec primaryStreamSpec,
+            @Nullable StreamSpec secondaryStreamSpec) {
+        mSecondaryCameraEdge = new SurfaceEdge(
+                /*targets=*/PREVIEW | VIDEO_CAPTURE,
+                INTERNAL_DEFINED_IMAGE_FORMAT_PRIVATE,
+                secondaryStreamSpec,
+                getSensorToBufferTransformMatrix(),
+                requireNonNull(getSecondaryCamera()).getHasTransform(),
+                requireNonNull(getCropRect(secondaryStreamSpec.getResolution())),
+                getRelativeRotation(requireNonNull(getSecondaryCamera())),
+                ImageOutputConfig.ROTATION_NOT_SPECIFIED,
+                isMirroringRequired(requireNonNull(getSecondaryCamera())));
+        mSecondarySharingInputEdge = getSharingInputEdge(mSecondaryCameraEdge,
+                requireNonNull(getSecondaryCamera()));
 
-        // Pass the output edges to virtual camera to connect children.
-        Map<UseCase, SurfaceEdge> outputEdges = new HashMap<>();
-        for (Map.Entry<UseCase, OutConfig> entry : outConfigMap.entrySet()) {
-            outputEdges.put(entry.getKey(), out.get(entry.getValue()));
-        }
-        mVirtualCameraAdapter.setChildrenEdges(outputEdges);
+        mSecondarySessionConfigBuilder = createSessionConfigBuilder(
+                mSecondaryCameraEdge, config, secondaryStreamSpec);
+        addCameraErrorListener(mSecondarySessionConfigBuilder,
+                cameraId, secondaryCameraId, config,
+                primaryStreamSpec, secondaryStreamSpec);
+    }
 
+    @NonNull
+    private SessionConfig.Builder createSessionConfigBuilder(
+            @NonNull SurfaceEdge surfaceEdge,
+            @NonNull UseCaseConfig<?> config,
+            @NonNull StreamSpec streamSpec) {
         // Send the camera edge Surface to the camera2.
         SessionConfig.Builder builder = SessionConfig.Builder.createFrom(config,
                 streamSpec.getResolution());
-
         propagateChildrenTemplate(builder);
         propagateChildrenCamera2Interop(streamSpec.getResolution(), builder);
 
-        builder.addSurface(mCameraEdge.getDeferrableSurface(),
+        DeferrableSurface deferrableSurface = surfaceEdge.getDeferrableSurface();
+        builder.addSurface(deferrableSurface,
                 streamSpec.getDynamicRange(),
                 null,
                 MirrorMode.MIRROR_MODE_UNSPECIFIED);
@@ -288,9 +414,7 @@
         if (streamSpec.getImplementationOptions() != null) {
             builder.addImplementationOptions(streamSpec.getImplementationOptions());
         }
-        addCameraErrorListener(builder, cameraId, config, streamSpec);
-        mSessionConfigBuilder = builder;
-        return builder.build();
+        return builder;
     }
 
     private void propagateChildrenTemplate(@NonNull SessionConfig.Builder builder) {
@@ -382,6 +506,21 @@
         }
     }
 
+    @NonNull
+    private DualSurfaceProcessorNode getDualSharingNode(
+            @NonNull CameraInternal primaryCamera,
+            @NonNull CameraInternal secondaryCamera,
+            @NonNull StreamSpec streamSpec,
+            @NonNull LayoutSettings primaryLayoutSettings,
+            @NonNull LayoutSettings secondaryLayoutSettings) {
+        // TODO: handle EffectNode for dual camera case
+        return new DualSurfaceProcessorNode(primaryCamera, secondaryCamera,
+                DualSurfaceProcessor.Factory.newInstance(
+                        streamSpec.getDynamicRange(),
+                        primaryLayoutSettings,
+                        secondaryLayoutSettings));
+    }
+
     private int getRotationAppliedByEffect() {
         CameraEffect effect = checkNotNull(getEffect());
         if (effect.getTransformation() == CameraEffect.TRANSFORMATION_CAMERA_AND_SURFACE_ROTATION) {
@@ -425,38 +564,66 @@
     private void addCameraErrorListener(
             @NonNull SessionConfig.Builder sessionConfigBuilder,
             @NonNull String cameraId,
+            @Nullable String secondaryCameraId,
             @NonNull UseCaseConfig<?> config,
-            @NonNull StreamSpec streamSpec) {
-        sessionConfigBuilder.addErrorListener((sessionConfig, error) -> {
-            // Clear both StreamSharing and the children.
-            clearPipeline();
-            if (isCurrentCamera(cameraId)) {
-                // Only reset the pipeline when the bound camera is the same.
-                updateSessionConfig(
-                        createPipelineAndUpdateChildrenSpecs(cameraId, config, streamSpec));
-                notifyReset();
-                // Connect the latest {@link Surface} to newly created children edges. Currently
-                // children UseCase does not have additional logic in SessionConfig error listener
-                // so this is OK. If they do, we need to invoke the children's SessionConfig
-                // error listeners instead.
-                mVirtualCameraAdapter.resetChildren();
-            }
-        });
+            @NonNull StreamSpec primaryStreamSpec,
+            @Nullable StreamSpec secondaryStreamSpec) {
+        if (mCloseableErrorListener != null) {
+            mCloseableErrorListener.close();
+        }
+        mCloseableErrorListener = new SessionConfig.CloseableErrorListener(
+                (sessionConfig, error) -> {
+                    // Do nothing when the use case has been unbound.
+                    if (getCamera() == null) {
+                        return;
+                    }
+
+                    // Clear both StreamSharing and the children.
+                    clearPipeline();
+                    updateSessionConfig(
+                            createPipelineAndUpdateChildrenSpecs(cameraId, secondaryCameraId,
+                                    config, primaryStreamSpec, secondaryStreamSpec));
+                    notifyReset();
+                    // Connect the latest {@link Surface} to newly created children edges.
+                    // Currently children UseCase does not have additional logic in SessionConfig
+                    // error listener so this is OK. If they do, we need to invoke the children's
+                    // SessionConfig error listeners instead.
+                    mVirtualCameraAdapter.resetChildren();
+                });
+        sessionConfigBuilder.setErrorListener(mCloseableErrorListener);
     }
 
     private void clearPipeline() {
+        // Closes the old error listener
+        if (mCloseableErrorListener != null) {
+            mCloseableErrorListener.close();
+            mCloseableErrorListener = null;
+        }
+
         if (mCameraEdge != null) {
             mCameraEdge.close();
             mCameraEdge = null;
         }
+        if (mSecondaryCameraEdge != null) {
+            mSecondaryCameraEdge.close();
+            mSecondaryCameraEdge = null;
+        }
         if (mSharingInputEdge != null) {
             mSharingInputEdge.close();
             mSharingInputEdge = null;
         }
+        if (mSecondarySharingInputEdge != null) {
+            mSecondarySharingInputEdge.close();
+            mSecondarySharingInputEdge = null;
+        }
         if (mSharingNode != null) {
             mSharingNode.release();
             mSharingNode = null;
         }
+        if (mDualSharingNode != null) {
+            mDualSharingNode.release();
+            mDualSharingNode = null;
+        }
         if (mEffectNode != null) {
             mEffectNode.release();
             mEffectNode = null;
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/VirtualCameraAdapter.java b/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/VirtualCameraAdapter.java
index cfe3f76..cbd71a85 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/VirtualCameraAdapter.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/VirtualCameraAdapter.java
@@ -61,6 +61,7 @@
 import androidx.camera.core.impl.UseCaseConfigFactory;
 import androidx.camera.core.impl.stabilization.StabilizationMode;
 import androidx.camera.core.processing.SurfaceEdge;
+import androidx.camera.core.processing.concurrent.DualOutConfig;
 import androidx.camera.core.processing.util.OutConfig;
 
 import java.util.HashMap;
@@ -94,6 +95,9 @@
     // The parent camera instance.
     @NonNull
     private final CameraInternal mParentCamera;
+    // The parent secondary camera instance in dual camera case.
+    @Nullable
+    private final CameraInternal mSecondaryParentCamera;
     // The callback that receives the parent camera's metadata.
     @NonNull
     private final CameraCaptureCallback mParentMetadataCallback = createCameraCaptureCallback();
@@ -103,7 +107,8 @@
     private final Map<UseCase, UseCaseConfig<?>> mChildrenConfigsMap;
     @NonNull
     private final ResolutionsMerger mResolutionsMerger;
-
+    @Nullable
+    private ResolutionsMerger mSecondaryResolutionsMerger;
 
     /**
      * @param parentCamera         the parent {@link CameraInternal} instance. For example, the
@@ -112,18 +117,26 @@
      * @param useCaseConfigFactory the factory for configuring children {@link UseCase}.
      */
     VirtualCameraAdapter(@NonNull CameraInternal parentCamera,
+            @Nullable CameraInternal secondaryParentCamera,
             @NonNull Set<UseCase> children,
             @NonNull UseCaseConfigFactory useCaseConfigFactory,
             @NonNull StreamSharing.Control streamSharingControl) {
         mParentCamera = parentCamera;
+        mSecondaryParentCamera = secondaryParentCamera;
         mUseCaseConfigFactory = useCaseConfigFactory;
         mChildren = children;
+        // No need to create a new instance for secondary camera.
         mChildrenConfigsMap = toChildrenConfigsMap(parentCamera, children, useCaseConfigFactory);
         mChildrenConfigs = new HashSet<>(mChildrenConfigsMap.values());
         mResolutionsMerger = new ResolutionsMerger(parentCamera, mChildrenConfigs);
+        if (mSecondaryParentCamera != null) {
+            mSecondaryResolutionsMerger = new ResolutionsMerger(
+                    mSecondaryParentCamera, mChildrenConfigs);
+        }
         // Set children state to inactive by default.
         for (UseCase child : children) {
             mChildrenActiveState.put(child, false);
+            // No need to create a new instance for secondary camera.
             mChildrenVirtualCameras.put(child, new VirtualCamera(
                     parentCamera,
                     this,
@@ -175,6 +188,7 @@
             useCase.bindToCamera(
                     requireNonNull(mChildrenVirtualCameras.get(useCase)),
                     null,
+                    null,
                     useCase.getDefaultConfig(true, mUseCaseConfigFactory));
         }
     }
@@ -209,38 +223,79 @@
     Map<UseCase, OutConfig> getChildrenOutConfigs(@NonNull SurfaceEdge sharingInputEdge,
             @ImageOutputConfig.RotationValue int parentTargetRotation, boolean isViewportSet) {
         Map<UseCase, OutConfig> outConfigs = new HashMap<>();
-        // TODO: we might be able to extract parent rotation degrees from the input edge's
-        //  sensor-to-buffer matrix and the mirroring bit.
-        int parentRotationDegrees = mParentCamera.getCameraInfo().getSensorRotationDegrees(
-                parentTargetRotation);
-        boolean parentIsMirrored = isMirrored(sharingInputEdge.getSensorToBufferTransform());
         for (UseCase useCase : mChildren) {
-            Pair<Rect, Size> preferredSizePair = mResolutionsMerger.getPreferredChildSizePair(
-                    requireNonNull(mChildrenConfigsMap.get(useCase)),
-                    sharingInputEdge.getCropRect(),
-                    getRotationDegrees(sharingInputEdge.getSensorToBufferTransform()),
-                    isViewportSet
-            );
-            Rect cropRectBeforeScaling = preferredSizePair.first;
-            Size childSizeToScale = preferredSizePair.second;
-
-            int childRotationDegrees = getChildRotationDegrees(useCase);
-            requireNonNull(mChildrenVirtualCameras.get(useCase))
-                    .setRotationDegrees(childRotationDegrees);
-            int childParentDelta = within360(sharingInputEdge.getRotationDegrees()
-                    + childRotationDegrees - parentRotationDegrees);
-            outConfigs.put(useCase, OutConfig.of(
-                    getChildTargetType(useCase),
-                    getChildFormat(useCase),
-                    cropRectBeforeScaling,
-                    rotateSize(childSizeToScale, childParentDelta),
-                    childParentDelta,
-                    // Only mirror if the parent and the child disagrees.
-                    useCase.isMirroringRequired(mParentCamera) ^ parentIsMirrored));
+            OutConfig outConfig = calculateOutConfig(useCase, mResolutionsMerger,
+                    mParentCamera, sharingInputEdge, parentTargetRotation, isViewportSet);
+            outConfigs.put(useCase, outConfig);
         }
         return outConfigs;
     }
 
+    @NonNull
+    Map<UseCase, DualOutConfig> getChildrenOutConfigs(
+            @NonNull SurfaceEdge primaryInputEdge,
+            @NonNull SurfaceEdge secondaryInputEdge,
+            @ImageOutputConfig.RotationValue int parentTargetRotation,
+            boolean isViewportSet) {
+        Map<UseCase, DualOutConfig> outConfigs = new HashMap<>();
+        for (UseCase useCase : mChildren) {
+            // primary
+            OutConfig primaryOutConfig = calculateOutConfig(
+                    useCase, mResolutionsMerger,
+                    mParentCamera, primaryInputEdge,
+                    parentTargetRotation, isViewportSet);
+            // secondary
+            OutConfig secondaryOutConfig = calculateOutConfig(
+                    useCase, mSecondaryResolutionsMerger,
+                    requireNonNull(mSecondaryParentCamera),
+                    secondaryInputEdge,
+                    parentTargetRotation, isViewportSet);
+            outConfigs.put(useCase, DualOutConfig.of(
+                    primaryOutConfig, secondaryOutConfig));
+        }
+        return outConfigs;
+    }
+
+    @NonNull
+    private OutConfig calculateOutConfig(
+            @NonNull UseCase useCase,
+            @NonNull ResolutionsMerger resolutionsMerger,
+            @NonNull CameraInternal cameraInternal,
+            @Nullable SurfaceEdge cameraInputEdge,
+            @ImageOutputConfig.RotationValue int parentTargetRotation,
+            boolean isViewportSet) {
+        // TODO: we might be able to extract parent rotation degrees from the input edge's
+        //  sensor-to-buffer matrix and the mirroring bit.
+        int parentRotationDegrees = cameraInternal.getCameraInfo()
+                .getSensorRotationDegrees(parentTargetRotation);
+        boolean parentIsMirrored = isMirrored(
+                cameraInputEdge.getSensorToBufferTransform());
+        Pair<Rect, Size> preferredSizePair = resolutionsMerger
+                .getPreferredChildSizePair(
+                        requireNonNull(mChildrenConfigsMap.get(useCase)),
+                        cameraInputEdge.getCropRect(),
+                        getRotationDegrees(cameraInputEdge.getSensorToBufferTransform()),
+                        isViewportSet);
+        Rect cropRectBeforeScaling = preferredSizePair.first;
+        Size childSizeToScale = preferredSizePair.second;
+
+        // Only use primary camera info for output surface
+        int childRotationDegrees = getChildRotationDegrees(useCase, mParentCamera);
+        requireNonNull(mChildrenVirtualCameras.get(useCase))
+                .setRotationDegrees(childRotationDegrees);
+        int childParentDelta = within360(cameraInputEdge.getRotationDegrees()
+                + childRotationDegrees - parentRotationDegrees);
+        return OutConfig.of(
+                getChildTargetType(useCase),
+                getChildFormat(useCase),
+                cropRectBeforeScaling,
+                rotateSize(childSizeToScale, childParentDelta),
+                childParentDelta,
+                // Only mirror if the parent and the child disagrees.
+                useCase.isMirroringRequired(cameraInternal)
+                        ^ parentIsMirrored);
+    }
+
     /**
      * Update children {@link SurfaceEdge} calculated by {@link StreamSharing}.
      */
@@ -252,7 +307,7 @@
             SurfaceEdge surfaceEdge = entry.getValue();
             useCase.setViewPortCropRect(surfaceEdge.getCropRect());
             useCase.setSensorToBufferTransformMatrix(surfaceEdge.getSensorToBufferTransform());
-            useCase.updateSuggestedStreamSpec(surfaceEdge.getStreamSpec());
+            useCase.updateSuggestedStreamSpec(surfaceEdge.getStreamSpec(), null);
             useCase.notifyState();
         }
     }
@@ -340,11 +395,11 @@
     // --- private methods ---
 
     @IntRange(from = 0, to = 359)
-    private int getChildRotationDegrees(@NonNull UseCase child) {
+    private int getChildRotationDegrees(@NonNull UseCase child,
+            @NonNull CameraInternal cameraInternal) {
         int childTargetRotation = ((ImageOutputConfig) child.getCurrentConfig())
                 .getTargetRotation(Surface.ROTATION_0);
-        return mParentCamera.getCameraInfo().getSensorRotationDegrees(
-                childTargetRotation);
+        return cameraInternal.getCameraInfo().getSensorRotationDegrees(childTargetRotation);
     }
 
     private static int getChildFormat(@NonNull UseCase useCase) {
@@ -405,8 +460,8 @@
             // The Surface is closed by the child. This will happen when e.g. the child is Preview
             // with SurfaceView implementation.
             // Invoke the error listener so it will recreate the pipeline.
-            for (SessionConfig.ErrorListener listener : childSessionConfig.getErrorListeners()) {
-                listener.onError(childSessionConfig,
+            if (childSessionConfig.getErrorListener() != null) {
+                childSessionConfig.getErrorListener().onError(childSessionConfig,
                         SessionConfig.SessionError.SESSION_ERROR_SURFACE_NEEDS_RESET);
             }
         }
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/ImageCaptureTest.kt b/camera/camera-core/src/test/java/androidx/camera/core/ImageCaptureTest.kt
index a08e1d46..1b1fad6 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/ImageCaptureTest.kt
+++ b/camera/camera-core/src/test/java/androidx/camera/core/ImageCaptureTest.kt
@@ -174,7 +174,7 @@
                 bufferFormat = ImageFormat.JPEG,
             )
         // Act: pipeline can be recreated without crashing.
-        imageCapture.updateSuggestedStreamSpec(StreamSpec.builder(resolution).build())
+        imageCapture.updateSuggestedStreamSpec(StreamSpec.builder(resolution).build(), null)
     }
 
     @Test
@@ -276,12 +276,10 @@
         assertTakePictureManagerHasTheSameSurface(imageCapture)
 
         // Act: invoke onError callback.
-        imageCapture.sessionConfig.errorListeners
-            .single()
-            .onError(
-                imageCapture.sessionConfig,
-                SessionConfig.SessionError.SESSION_ERROR_SURFACE_NEEDS_RESET
-            )
+        imageCapture.sessionConfig.errorListener!!.onError(
+            imageCapture.sessionConfig,
+            SessionConfig.SessionError.SESSION_ERROR_SURFACE_NEEDS_RESET
+        )
 
         // Assert: the surface has been recreated.
         val newSurface = imageCapture.sessionConfig.surfaces.single().surface.get()
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/PreviewTest.kt b/camera/camera-core/src/test/java/androidx/camera/core/PreviewTest.kt
index 0c3c616..3ec52f0 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/PreviewTest.kt
+++ b/camera/camera-core/src/test/java/androidx/camera/core/PreviewTest.kt
@@ -465,14 +465,14 @@
     }
 
     @Test
-    fun invalidateAppSurfaceRequestWithProcessing_cameraNotReset() {
+    fun invalidateAppSurfaceRequestWithProcessing_cameraReset() {
         // Arrange: create Preview with processing.
         val surfaceRequest = createPreview(effect).mCurrentSurfaceRequest
         // Act: invalidate.
         surfaceRequest!!.invalidate()
         shadowOf(getMainLooper()).idle()
         // Assert: preview is not reset.
-        assertThat(backCamera.useCaseResetHistory).isEmpty()
+        assertThat(backCamera.useCaseResetHistory).containsExactly(previewToDetach)
     }
 
     @Test
@@ -584,7 +584,7 @@
         val originalSessionConfig = preview.sessionConfig
 
         // Act: invoke the error listener.
-        preview.sessionConfig.errorListeners[0].onError(
+        preview.sessionConfig.errorListener!!.onError(
             preview.sessionConfig,
             SessionConfig.SessionError.SESSION_ERROR_UNKNOWN
         )
@@ -849,6 +849,7 @@
         previewToDetach.bindToCamera(
             camera,
             null,
+            null,
             previewToDetach.getDefaultConfig(
                 true,
                 cameraXConfig.getUseCaseConfigFactoryProvider(null)!!.newInstance(context)
@@ -863,7 +864,7 @@
                 .setImplementationOptions(streamSpecOptions)
                 .build()
         previewToDetach.sensorToBufferTransformMatrix = sensorToBufferTransform
-        previewToDetach.updateSuggestedStreamSpec(streamSpec)
+        previewToDetach.updateSuggestedStreamSpec(streamSpec, null)
         return previewToDetach
     }
 
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/imagecapture/CaptureNodeTest.kt b/camera/camera-core/src/test/java/androidx/camera/core/imagecapture/CaptureNodeTest.kt
index 4bc0869..816367e 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/imagecapture/CaptureNodeTest.kt
+++ b/camera/camera-core/src/test/java/androidx/camera/core/imagecapture/CaptureNodeTest.kt
@@ -166,6 +166,106 @@
         assertThat(imagePropagated.get(0).imageInfo.tagBundle.getTag(tagBundleKeyB)).isEqualTo(2)
     }
 
+    @Test
+    fun requestNoProgressSent_ensureProgress100IsNotInvoked() {
+        // Arrange: Configure the CaptureNode and submit fake request.
+        val captureNode = CaptureNode()
+        val imageReaderProxy = FakeImageReaderProxy(2)
+        captureNodeIn =
+            CaptureNode.In.of(
+                Size(10, 10),
+                JPEG,
+                JPEG,
+                /* isVirtualCamera */ true,
+                { _, _, _, _, _ -> imageReaderProxy }
+            )
+        captureNodeOut = captureNode.transform(captureNodeIn)
+        captureNodeOut.edge.setListener { imagePropagated.add(it.imageProxy) }
+
+        // Create request
+        val captureBundle = createCaptureBundle(intArrayOf(1))
+        val takePictureCallback = FakeTakePictureCallback()
+        val request = FakeProcessingRequest(captureBundle, takePictureCallback)
+        val tagBundle =
+            TagBundle.create(Pair(captureBundle.hashCode().toString(), /* stage id */ 1))
+
+        captureNodeIn.requestEdge.accept(request)
+        imageReaderProxy.triggerImageAvailableSync(tagBundle)
+        shadowOf(getMainLooper()).idle()
+
+        // Assert: captureProcessProgress is not invoked.
+        assertThat(takePictureCallback.captureProcessProgressList).isEmpty()
+    }
+
+    @Test
+    fun requestSentNon100Progress_progress100isInvoked() {
+        // Arrange: Configure the CaptureNode and submit fake request.
+        val captureNode = CaptureNode()
+        val imageReaderProxy = FakeImageReaderProxy(2)
+        captureNodeIn =
+            CaptureNode.In.of(
+                Size(10, 10),
+                JPEG,
+                JPEG,
+                /* isVirtualCamera */ true,
+                { _, _, _, _, _ -> imageReaderProxy }
+            )
+        captureNodeOut = captureNode.transform(captureNodeIn)
+        captureNodeOut.edge.setListener { imagePropagated.add(it.imageProxy) }
+
+        // Create request
+        val captureBundle = createCaptureBundle(intArrayOf(1))
+        val takePictureCallback = FakeTakePictureCallback()
+        val request = FakeProcessingRequest(captureBundle, takePictureCallback)
+        val tagBundle =
+            TagBundle.create(Pair(captureBundle.hashCode().toString(), /* stage id */ 1))
+
+        captureNodeIn.requestEdge.accept(request)
+        // Act: notify onCaptureProcessProgressed that is not 100 after request starts.
+        captureNodeIn.cameraCaptureCallback.onCaptureProcessProgressed(1, 50)
+        captureNodeIn.cameraCaptureCallback.onCaptureProcessProgressed(1, 90)
+
+        imageReaderProxy.triggerImageAvailableSync(tagBundle)
+        shadowOf(getMainLooper()).idle()
+
+        // Assert: captureProcessProgress 100 is also invoked.
+        assertThat(takePictureCallback.captureProcessProgressList).containsExactly(50, 90, 100)
+    }
+
+    @Test
+    fun requestSent100Progress_ensureNoDuplicate() {
+        // Arrange: Configure the CaptureNode and submit fake request.
+        val captureNode = CaptureNode()
+        val imageReaderProxy = FakeImageReaderProxy(2)
+        captureNodeIn =
+            CaptureNode.In.of(
+                Size(10, 10),
+                JPEG,
+                JPEG,
+                /* isVirtualCamera */ true,
+                { _, _, _, _, _ -> imageReaderProxy }
+            )
+        captureNodeOut = captureNode.transform(captureNodeIn)
+        captureNodeOut.edge.setListener { imagePropagated.add(it.imageProxy) }
+
+        // Create request
+        val captureBundle = createCaptureBundle(intArrayOf(1))
+        val takePictureCallback = FakeTakePictureCallback()
+        val request = FakeProcessingRequest(captureBundle, takePictureCallback)
+        val tagBundle =
+            TagBundle.create(Pair(captureBundle.hashCode().toString(), /* stage id */ 1))
+
+        captureNodeIn.requestEdge.accept(request)
+        // Act: notify onCaptureProcessProgressed that is not 100 after request starts.
+        captureNodeIn.cameraCaptureCallback.onCaptureProcessProgressed(1, 100)
+
+        imageReaderProxy.triggerImageAvailableSync(tagBundle)
+        shadowOf(getMainLooper()).idle()
+
+        // Assert: captureProcessProgress 100 is only sent once.
+        assertThat(takePictureCallback.captureProcessProgressList).containsExactly(100)
+    }
+
     private fun FakeImageReaderProxy.triggerImageAvailableSync(
         tagBundle: TagBundle,
     ): FakeImageProxy {
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/imagecapture/FakeProcessingRequest.kt b/camera/camera-core/src/test/java/androidx/camera/core/imagecapture/FakeProcessingRequest.kt
index 6260b84..658a6bb 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/imagecapture/FakeProcessingRequest.kt
+++ b/camera/camera-core/src/test/java/androidx/camera/core/imagecapture/FakeProcessingRequest.kt
@@ -21,6 +21,7 @@
 import androidx.camera.core.ImageCapture
 import androidx.camera.core.imagecapture.Utils.CROP_RECT
 import androidx.camera.core.impl.CaptureBundle
+import androidx.concurrent.futures.CallbackToFutureAdapter
 import com.google.common.util.concurrent.ListenableFuture
 
 /** Fake [ProcessingRequest]. */
@@ -47,6 +48,6 @@
     constructor(
         captureBundle: CaptureBundle,
         callback: TakePictureCallback,
-        captureFuture: ListenableFuture<Void>
+        captureFuture: ListenableFuture<Void> = CallbackToFutureAdapter.getFuture { "test" }
     ) : this(null, captureBundle, CROP_RECT, 0, 100, Matrix(), callback, captureFuture)
 }
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/imagecapture/FakeTakePictureCallback.kt b/camera/camera-core/src/test/java/androidx/camera/core/imagecapture/FakeTakePictureCallback.kt
index 83ca31c..0e71ebb 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/imagecapture/FakeTakePictureCallback.kt
+++ b/camera/camera-core/src/test/java/androidx/camera/core/imagecapture/FakeTakePictureCallback.kt
@@ -30,7 +30,7 @@
     var captureFailure: ImageCaptureException? = null
     var processFailure: ImageCaptureException? = null
     var onDiskResult: OutputFileResults? = null
-    var captureProcessProgress = -1
+    var captureProcessProgressList: MutableList<Int> = mutableListOf()
     var onPostviewBitmapAvailable: Bitmap? = null
 
     var aborted = false
@@ -64,7 +64,7 @@
     }
 
     override fun onCaptureProcessProgressed(progress: Int) {
-        captureProcessProgress = progress
+        captureProcessProgressList.add(progress)
     }
 
     override fun onPostviewBitmapAvailable(bitmap: Bitmap) {
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/impl/SessionConfigTest.kt b/camera/camera-core/src/test/java/androidx/camera/core/impl/SessionConfigTest.kt
index 5b7beb0..6645aa2 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/impl/SessionConfigTest.kt
+++ b/camera/camera-core/src/test/java/androidx/camera/core/impl/SessionConfigTest.kt
@@ -881,11 +881,11 @@
         val builder = SessionConfig.Builder()
         val callback = mock(SessionConfig.ErrorListener::class.java)
 
-        builder.addErrorListener(callback)
+        builder.setErrorListener(callback)
 
         val config = builder.build()
 
-        assertThat(config.errorListeners).contains(callback)
+        assertThat(config.errorListener).isSameInstanceAs(callback)
     }
 
     @Test
@@ -895,24 +895,26 @@
         val deviceCallback0 = mock(CameraDevice.StateCallback::class.java)
         val repeatingCallback0 = mock(CameraCaptureCallback::class.java)
         val cameraCallback0 = mock(CameraCaptureCallback::class.java)
-        val errorListener0 = mock(SessionConfig.ErrorListener::class.java)
+        var errorCallbackInvoked0 = false
+        val errorListener0 = SessionConfig.ErrorListener { _, _ -> errorCallbackInvoked0 = true }
         builder0.addSessionStateCallback(sessionCallback0)
         builder0.addDeviceStateCallback(deviceCallback0)
         builder0.addRepeatingCameraCaptureCallback(repeatingCallback0)
         builder0.addCameraCaptureCallback(cameraCallback0)
-        builder0.addErrorListener(errorListener0)
+        builder0.setErrorListener(errorListener0)
 
         val builder1 = SessionConfig.Builder()
         val sessionCallback1 = mock(CameraCaptureSession.StateCallback::class.java)
         val deviceCallback1 = mock(CameraDevice.StateCallback::class.java)
         val repeatingCallback1 = mock(CameraCaptureCallback::class.java)
         val cameraCallback1 = mock(CameraCaptureCallback::class.java)
-        val errorListener1 = mock(SessionConfig.ErrorListener::class.java)
+        var errorCallbackInvoked1 = false
+        val errorListener1 = SessionConfig.ErrorListener { _, _ -> errorCallbackInvoked1 = true }
         builder1.addSessionStateCallback(sessionCallback1)
         builder1.addDeviceStateCallback(deviceCallback1)
         builder1.addRepeatingCameraCaptureCallback(repeatingCallback1)
         builder1.addCameraCaptureCallback(cameraCallback1)
-        builder1.addErrorListener(errorListener1)
+        builder1.setErrorListener(errorListener1)
 
         val validatingBuilder = ValidatingBuilder()
         validatingBuilder.add(builder0.build())
@@ -933,7 +935,12 @@
             )
         assertThat(sessionConfig.singleCameraCaptureCallbacks)
             .containsExactly(cameraCallback0, cameraCallback1)
-        assertThat(sessionConfig.errorListeners).containsExactly(errorListener0, errorListener1)
+        sessionConfig.errorListener!!.onError(
+            sessionConfig,
+            SessionConfig.SessionError.SESSION_ERROR_SURFACE_NEEDS_RESET
+        )
+        assertThat(errorCallbackInvoked0).isTrue()
+        assertThat(errorCallbackInvoked1).isTrue()
     }
 
     @Test
@@ -986,7 +993,7 @@
         builder.addSessionStateCallback(sessionCallback1)
         builder.setTemplateType(template1)
         builder.addImplementationOptions(optionsBundle1)
-        builder.addErrorListener(errorListener1)
+        builder.setErrorListener(errorListener1)
         val sessionConfig = builder.build()
 
         // 2. Act
@@ -999,7 +1006,7 @@
         builder.addSessionStateCallback(sessionCallback2)
         builder.setTemplateType(template2)
         builder.addImplementationOptions(optionsBundle2)
-        builder.addErrorListener(errorListener2)
+        builder.setErrorListener(errorListener2)
 
         // 3. Verify
         assertThat(sessionConfig.surfaces).containsExactly(deferrableSurface1)
@@ -1011,7 +1018,7 @@
         assertThat(sessionConfig.sessionStateCallbacks).containsExactly(sessionCallback1)
         assertThat(sessionConfig.templateType).isEqualTo(template1)
         assertThat(sessionConfig.implementationOptions.retrieveOption(OPTION)).isEqualTo(1)
-        assertThat(sessionConfig.errorListeners).containsExactly(errorListener1)
+        assertThat(sessionConfig.errorListener).isEqualTo(errorListener1)
     }
 
     @Test
@@ -1025,7 +1032,8 @@
         val deviceStateCallback2 = mock(CameraDevice.StateCallback::class.java)
         val sessionCallback1 = mock(CameraCaptureSession.StateCallback::class.java)
         val sessionCallback2 = mock(CameraCaptureSession.StateCallback::class.java)
-        val errorListener1 = mock(SessionConfig.ErrorListener::class.java)
+        var errorCallbackInvoked1 = false
+        val errorListener1 = SessionConfig.ErrorListener { _, _ -> errorCallbackInvoked1 = true }
         val errorListener2 = mock(SessionConfig.ErrorListener::class.java)
         val fpsRange1 = Range(30, 30)
         val fpsRange2 = Range(15, 30)
@@ -1045,7 +1053,7 @@
         builder.addSessionStateCallback(sessionCallback1)
         builder.setTemplateType(template1)
         builder.addImplementationOptions(optionsBundle1)
-        builder.addErrorListener(errorListener1)
+        builder.setErrorListener(errorListener1)
 
         val validatingBuilder = ValidatingBuilder()
         validatingBuilder.add(builder.build())
@@ -1063,7 +1071,7 @@
         builder2.addSessionStateCallback(sessionCallback2)
         builder2.setTemplateType(template2)
         builder2.addImplementationOptions(optionsBundle2)
-        builder2.addErrorListener(errorListener2)
+        builder2.setErrorListener(errorListener2)
         validatingBuilder.add(builder2.build())
 
         // 3. Verify
@@ -1076,7 +1084,13 @@
         assertThat(sessionConfig.sessionStateCallbacks).containsExactly(sessionCallback1)
         assertThat(sessionConfig.templateType).isEqualTo(template1)
         assertThat(sessionConfig.implementationOptions.retrieveOption(OPTION)).isEqualTo(1)
-        assertThat(sessionConfig.errorListeners).containsExactly(errorListener1)
+        // The preview error callback can still be invoked after the builder aggregates the error
+        // listeners
+        sessionConfig.errorListener!!.onError(
+            sessionConfig,
+            SessionConfig.SessionError.SESSION_ERROR_SURFACE_NEEDS_RESET
+        )
+        assertThat(errorCallbackInvoked1).isTrue()
     }
 
     private fun createSessionConfigWithTag(key: String, tagValue: Any): SessionConfig {
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/internal/CameraUseCaseAdapterTest.kt b/camera/camera-core/src/test/java/androidx/camera/core/internal/CameraUseCaseAdapterTest.kt
index 3fb962a..a28d501 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/internal/CameraUseCaseAdapterTest.kt
+++ b/camera/camera-core/src/test/java/androidx/camera/core/internal/CameraUseCaseAdapterTest.kt
@@ -26,6 +26,7 @@
 import android.util.Size
 import android.view.Surface
 import androidx.annotation.RequiresApi
+import androidx.camera.camera2.impl.Camera2ImplConfig
 import androidx.camera.core.CameraEffect
 import androidx.camera.core.CameraEffect.PREVIEW
 import androidx.camera.core.CameraEffect.VIDEO_CAPTURE
@@ -36,6 +37,7 @@
 import androidx.camera.core.FocusMeteringAction.FLAG_AWB
 import androidx.camera.core.ImageAnalysis
 import androidx.camera.core.ImageCapture
+import androidx.camera.core.LayoutSettings
 import androidx.camera.core.Preview
 import androidx.camera.core.SurfaceOrientedMeteringPointFactory
 import androidx.camera.core.TorchState
@@ -51,6 +53,7 @@
 import androidx.camera.core.impl.ImageFormatConstants.INTERNAL_DEFINED_IMAGE_FORMAT_PRIVATE
 import androidx.camera.core.impl.MutableOptionsBundle
 import androidx.camera.core.impl.OptionsBundle
+import androidx.camera.core.impl.PreviewConfig
 import androidx.camera.core.impl.RestrictedCameraControl
 import androidx.camera.core.impl.RestrictedCameraInfo
 import androidx.camera.core.impl.SessionProcessor
@@ -59,6 +62,7 @@
 import androidx.camera.core.impl.UseCaseConfigFactory.CaptureType
 import androidx.camera.core.impl.utils.executor.CameraXExecutors.mainThreadExecutor
 import androidx.camera.core.internal.CameraUseCaseAdapter.CameraException
+import androidx.camera.core.internal.TargetConfig.OPTION_TARGET_NAME
 import androidx.camera.core.processing.DefaultSurfaceProcessor
 import androidx.camera.core.streamsharing.StreamSharing
 import androidx.camera.testing.fakes.FakeCamera
@@ -93,6 +97,7 @@
 import org.robolectric.annotation.internal.DoNotInstrument
 
 private const val CAMERA_ID = "0"
+private const val SECONDARY_CAMERA_ID = "1"
 
 /** Unit tests for [CameraUseCaseAdapter]. */
 @RunWith(RobolectricTestRunner::class)
@@ -106,6 +111,7 @@
     private lateinit var executor: ExecutorService
     private lateinit var fakeCameraDeviceSurfaceManager: FakeCameraDeviceSurfaceManager
     private lateinit var fakeCamera: FakeCamera
+    private lateinit var fakeSecondaryCamera: FakeCamera
     private lateinit var useCaseConfigFactory: UseCaseConfigFactory
     private lateinit var previewEffect: FakeSurfaceEffect
     private lateinit var videoEffect: FakeSurfaceEffect
@@ -128,6 +134,7 @@
         fakeCameraControl = FakeCameraControl()
         fakeCameraInfo = FakeCameraInfoInternal()
         fakeCamera = FakeCamera(CAMERA_ID, fakeCameraControl, fakeCameraInfo)
+        fakeSecondaryCamera = FakeCamera(SECONDARY_CAMERA_ID, fakeCameraControl, fakeCameraInfo)
         cameraCoordinator = FakeCameraCoordinator()
         useCaseConfigFactory = FakeUseCaseConfigFactory()
         executor = Executors.newSingleThreadExecutor()
@@ -201,7 +208,7 @@
     }
 
     @Test
-    fun addUseCases_updateExistingUseCases() {
+    fun addUseCases_notUpdateExistingUseCasesIfOptionNotChanged() {
         // Arrange.
         adapter.addUseCases(setOf(preview))
         adapter.attachUseCases()
@@ -210,6 +217,31 @@
         adapter.addUseCases(setOf(video))
 
         // Assert.
+        assertThat(fakeCamera.useCaseUpdateHistory).doesNotContain(preview)
+    }
+
+    @Test
+    fun addUseCases_updateExistingUseCasesWhenOptionChanged() {
+        // Arrange.
+        adapter.addUseCases(setOf(preview))
+        adapter.attachUseCases()
+
+        // Intentionally modify the implementation options for preview so that an update of use case
+        // will be triggered.
+        val optionsBundle = MutableOptionsBundle.create()
+        optionsBundle.insertOption(OPTION_TARGET_NAME, "fakeName")
+        fakeCameraDeviceSurfaceManager.setSuggestedStreamSpec(
+            CAMERA_ID,
+            PreviewConfig::class.java,
+            StreamSpec.builder(Size(1920, 1080))
+                .setImplementationOptions(Camera2ImplConfig(optionsBundle))
+                .build()
+        )
+
+        // Act.
+        adapter.addUseCases(setOf(video))
+
+        // Assert.
         assertThat(fakeCamera.useCaseUpdateHistory).containsExactly(preview)
     }
 
@@ -282,7 +314,11 @@
         val adapter =
             CameraUseCaseAdapter(
                 fakeCamera,
+                null,
                 RestrictedCameraInfo(fakeCamera.cameraInfoInternal, extensionsConfig),
+                null,
+                LayoutSettings.DEFAULT,
+                LayoutSettings.DEFAULT,
                 FakeCameraCoordinator(),
                 fakeManager,
                 FakeUseCaseConfigFactory(),
@@ -324,7 +360,15 @@
 
     @Test(expected = CameraException::class)
     fun addStreamSharing_throwsException() {
-        val streamSharing = StreamSharing(fakeCamera, setOf(preview, video), useCaseConfigFactory)
+        val streamSharing =
+            StreamSharing(
+                fakeCamera,
+                null,
+                LayoutSettings.DEFAULT,
+                LayoutSettings.DEFAULT,
+                setOf(preview, video),
+                useCaseConfigFactory
+            )
         // Act: add use cases that can only be supported with StreamSharing
         adapter.addUseCases(setOf(streamSharing, video, image))
     }
@@ -584,7 +628,7 @@
         val fakeUseCase = spy(FakeUseCase())
         adapter.addUseCases(listOf(fakeUseCase))
         verify(fakeUseCase)
-            .bindToCamera(eq(fakeCamera), isNull(), any(FakeUseCaseConfig::class.java))
+            .bindToCamera(eq(fakeCamera), isNull(), isNull(), any(FakeUseCaseConfig::class.java))
     }
 
     @Test
@@ -1254,6 +1298,21 @@
             .isSameInstanceAs(fakeSessionProcessor)
     }
 
+    @Test
+    fun generateCameraId_isDualCameraRecording() {
+        val cameraUseCaseAdapter1 = createCameraUseCaseAdapter(fakeCamera)
+        val cameraUseCaseAdapter2 =
+            createCameraUseCaseAdapter(fakeCamera, secondaryCamera = fakeSecondaryCamera)
+        assertThat(cameraUseCaseAdapter1.cameraId).isNotEqualTo(cameraUseCaseAdapter2.cameraId)
+    }
+
+    @Test
+    fun generateCameraId_isNotDualCameraRecording() {
+        val cameraUseCaseAdapter1 = createCameraUseCaseAdapter(fakeCamera)
+        val cameraUseCaseAdapter2 = createCameraUseCaseAdapter(fakeCamera, secondaryCamera = null)
+        assertThat(cameraUseCaseAdapter1.cameraId).isEqualTo(cameraUseCaseAdapter2.cameraId)
+    }
+
     private fun createFakeVideoCaptureUseCase(): FakeUseCase {
         return FakeUseCaseConfig.Builder()
             .setCaptureType(CaptureType.VIDEO_CAPTURE)
@@ -1318,13 +1377,19 @@
      * adapters to detach.
      */
     private fun createCameraUseCaseAdapter(
-        cameraInternal: CameraInternal,
-        cameraConfig: CameraConfig = CameraConfigs.defaultConfig()
+        camera: CameraInternal,
+        cameraConfig: CameraConfig = CameraConfigs.defaultConfig(),
+        secondaryCamera: CameraInternal? = null
     ): CameraUseCaseAdapter {
         val adapter =
             CameraUseCaseAdapter(
-                cameraInternal,
-                RestrictedCameraInfo(cameraInternal.cameraInfoInternal, cameraConfig),
+                camera,
+                secondaryCamera,
+                RestrictedCameraInfo(camera.cameraInfoInternal, cameraConfig),
+                if (secondaryCamera == null) null
+                else RestrictedCameraInfo(secondaryCamera.cameraInfoInternal, cameraConfig),
+                LayoutSettings.DEFAULT,
+                LayoutSettings.DEFAULT,
                 cameraCoordinator,
                 fakeCameraDeviceSurfaceManager,
                 useCaseConfigFactory
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/processing/SurfaceEdgeTest.kt b/camera/camera-core/src/test/java/androidx/camera/core/processing/SurfaceEdgeTest.kt
index fa2f9f3..b90fa78 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/processing/SurfaceEdgeTest.kt
+++ b/camera/camera-core/src/test/java/androidx/camera/core/processing/SurfaceEdgeTest.kt
@@ -663,11 +663,14 @@
 
     private fun createSurfaceOutputFuture(surfaceEdge: SurfaceEdge) =
         surfaceEdge.createSurfaceOutputFuture(
-            INPUT_SIZE,
             INTERNAL_DEFINED_IMAGE_FORMAT_PRIVATE,
-            sizeToRect(INPUT_SIZE),
-            /*rotationDegrees=*/ 0,
-            /*mirroring=*/ false,
-            FakeCamera()
+            SurfaceOutput.CameraInputInfo.of(
+                INPUT_SIZE,
+                sizeToRect(INPUT_SIZE),
+                FakeCamera(),
+                /*rotationDegrees=*/ 0,
+                /*mirroring=*/ false
+            ),
+            null
         )
 }
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/processing/SurfaceOutputImplTest.kt b/camera/camera-core/src/test/java/androidx/camera/core/processing/SurfaceOutputImplTest.kt
index 33cc213..837ed2d 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/processing/SurfaceOutputImplTest.kt
+++ b/camera/camera-core/src/test/java/androidx/camera/core/processing/SurfaceOutputImplTest.kt
@@ -24,6 +24,7 @@
 import android.view.Surface
 import androidx.camera.core.CameraEffect
 import androidx.camera.core.CameraSelector.LENS_FACING_FRONT
+import androidx.camera.core.SurfaceOutput
 import androidx.camera.core.impl.ImageFormatConstants.INTERNAL_DEFINED_IMAGE_FORMAT_PRIVATE
 import androidx.camera.core.impl.utils.TransformUtils.sizeToRect
 import androidx.camera.core.impl.utils.executor.CameraXExecutors.mainThreadExecutor
@@ -169,11 +170,14 @@
                 TARGET,
                 INTERNAL_DEFINED_IMAGE_FORMAT_PRIVATE,
                 OUTPUT_SIZE,
-                INPUT_SIZE,
-                sizeToRect(INPUT_SIZE),
-                /*rotationDegrees=*/ 180,
-                /*mirroring=*/ false,
-                camera,
+                SurfaceOutput.CameraInputInfo.of(
+                    INPUT_SIZE,
+                    sizeToRect(INPUT_SIZE),
+                    camera,
+                    /*rotationDegrees=*/ 180,
+                    /*mirroring=*/ false
+                ),
+                null,
                 android.graphics.Matrix()
             )
             .apply { surfaceOutputsToCleanup.add(this) }
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/streamsharing/StreamSharingTest.kt b/camera/camera-core/src/test/java/androidx/camera/core/streamsharing/StreamSharingTest.kt
index 69fd488..c5e0c42 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/streamsharing/StreamSharingTest.kt
+++ b/camera/camera-core/src/test/java/androidx/camera/core/streamsharing/StreamSharingTest.kt
@@ -43,6 +43,7 @@
 import androidx.camera.core.ImageCapture
 import androidx.camera.core.ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY
 import androidx.camera.core.ImageProxy
+import androidx.camera.core.LayoutSettings
 import androidx.camera.core.Preview
 import androidx.camera.core.SurfaceRequest
 import androidx.camera.core.impl.CameraCaptureCallback
@@ -108,6 +109,7 @@
         FakeUseCase(FakeUseCaseConfig.Builder().setSurfaceOccupancyPriority(2).useCaseConfig)
     private val useCaseConfigFactory = FakeUseCaseConfigFactory()
     private val camera = FakeCamera()
+    private val secondaryCamera = FakeCamera()
     private val frontCamera =
         FakeCamera(null, FakeCameraInfoInternal(SENSOR_ROTATION, LENS_FACING_FRONT))
     private lateinit var streamSharing: StreamSharing
@@ -128,7 +130,15 @@
     fun setUp() {
         sharingProcessor = FakeSurfaceProcessorInternal(mainThreadExecutor())
         DefaultSurfaceProcessor.Factory.setSupplier { sharingProcessor }
-        streamSharing = StreamSharing(camera, setOf(child1, child2), useCaseConfigFactory)
+        streamSharing =
+            StreamSharing(
+                camera,
+                secondaryCamera,
+                LayoutSettings.DEFAULT,
+                LayoutSettings.DEFAULT,
+                setOf(child1, child2),
+                useCaseConfigFactory
+            )
         defaultConfig = streamSharing.getDefaultConfig(true, useCaseConfigFactory)!!
         effectProcessor = FakeSurfaceProcessorInternal(mainThreadExecutor())
         effect = FakeSurfaceEffect(PREVIEW or VIDEO_CAPTURE, effectProcessor)
@@ -158,13 +168,20 @@
         val preview = Preview.Builder().build()
         val videoCapture = VideoCapture.Builder(Recorder.Builder().build()).build()
         streamSharing =
-            StreamSharing(frontCamera, setOf(preview, videoCapture), useCaseConfigFactory)
+            StreamSharing(
+                frontCamera,
+                secondaryCamera,
+                LayoutSettings.DEFAULT,
+                LayoutSettings.DEFAULT,
+                setOf(preview, videoCapture),
+                useCaseConfigFactory
+            )
         streamSharing.setViewPortCropRect(cropRect)
         streamSharing.effect = effect
 
         // Act: Bind effect and get sharing input edge.
-        streamSharing.bindToCamera(frontCamera, null, defaultConfig)
-        streamSharing.onSuggestedStreamSpecUpdated(StreamSpec.builder(size).build())
+        streamSharing.bindToCamera(frontCamera, null, null, defaultConfig)
+        streamSharing.onSuggestedStreamSpecUpdated(StreamSpec.builder(size).build(), null)
 
         // Assert: the sharing node is built with the effect's processor
         val sharingProcessor =
@@ -186,12 +203,20 @@
                 CameraEffect.TRANSFORMATION_CAMERA_AND_SURFACE_ROTATION,
                 effectProcessor
             )
-        streamSharing = StreamSharing(frontCamera, setOf(child1), useCaseConfigFactory)
+        streamSharing =
+            StreamSharing(
+                frontCamera,
+                secondaryCamera,
+                LayoutSettings.DEFAULT,
+                LayoutSettings.DEFAULT,
+                setOf(child1),
+                useCaseConfigFactory
+            )
         streamSharing.setViewPortCropRect(cropRect)
         streamSharing.effect = effect
         // Act: Bind effect and get sharing input edge.
-        streamSharing.bindToCamera(frontCamera, null, defaultConfig)
-        streamSharing.onSuggestedStreamSpecUpdated(StreamSpec.builder(size).build())
+        streamSharing.bindToCamera(frontCamera, null, null, defaultConfig)
+        streamSharing.onSuggestedStreamSpecUpdated(StreamSpec.builder(size).build(), null)
         // Assert: no remaining rotation because it's handled by the effect.
         assertThat(streamSharing.sharingInputEdge!!.rotationDegrees).isEqualTo(0)
         assertThat(streamSharing.sharingInputEdge!!.cropRect).isEqualTo(Rect(100, 50, 500, 650))
@@ -201,12 +226,20 @@
     @Test
     fun effectDoNotHandleRotationAndMirroring_remainingTransformationIsNotEmpty() {
         // Arrange: create an effect that does not handle rotation.
-        streamSharing = StreamSharing(camera, setOf(child1), useCaseConfigFactory)
+        streamSharing =
+            StreamSharing(
+                camera,
+                secondaryCamera,
+                LayoutSettings.DEFAULT,
+                LayoutSettings.DEFAULT,
+                setOf(child1),
+                useCaseConfigFactory
+            )
         streamSharing.setViewPortCropRect(cropRect)
         streamSharing.effect = effect
         // Act: bind effect.
-        streamSharing.bindToCamera(frontCamera, null, defaultConfig)
-        streamSharing.onSuggestedStreamSpecUpdated(StreamSpec.builder(size).build())
+        streamSharing.bindToCamera(frontCamera, null, null, defaultConfig)
+        streamSharing.onSuggestedStreamSpecUpdated(StreamSpec.builder(size).build(), null)
         // Assert: the remaining rotation still exists because the effect doesn't handle it. It will
         // be handled by downstream pipeline.
         assertThat(streamSharing.sharingInputEdge!!.rotationDegrees).isEqualTo(SENSOR_ROTATION)
@@ -223,11 +256,19 @@
                 CameraEffect.TRANSFORMATION_PASSTHROUGH,
                 effectProcessor
             )
-        streamSharing = StreamSharing(camera, setOf(child1), useCaseConfigFactory)
+        streamSharing =
+            StreamSharing(
+                camera,
+                secondaryCamera,
+                LayoutSettings.DEFAULT,
+                LayoutSettings.DEFAULT,
+                setOf(child1),
+                useCaseConfigFactory
+            )
         streamSharing.effect = effect
         // Act: bind effect.
-        streamSharing.bindToCamera(frontCamera, null, defaultConfig)
-        streamSharing.onSuggestedStreamSpecUpdated(StreamSpec.builder(size).build())
+        streamSharing.bindToCamera(frontCamera, null, null, defaultConfig)
+        streamSharing.onSuggestedStreamSpecUpdated(StreamSpec.builder(size).build(), null)
         // Assert: surface processor is not applied, the sharing input edge is the camera edge.
         assertThat(streamSharing.sharingInputEdge).isEqualTo(streamSharing.cameraEdge)
     }
@@ -313,9 +354,17 @@
         // Arrange: set up StreamSharing with min latency ImageCapture as child
         val imageCapture =
             ImageCapture.Builder().setCaptureMode(CAPTURE_MODE_MINIMIZE_LATENCY).build()
-        streamSharing = StreamSharing(camera, setOf(child1, imageCapture), useCaseConfigFactory)
-        streamSharing.bindToCamera(camera, null, defaultConfig)
-        streamSharing.onSuggestedStreamSpecUpdated(StreamSpec.builder(size).build())
+        streamSharing =
+            StreamSharing(
+                camera,
+                secondaryCamera,
+                LayoutSettings.DEFAULT,
+                LayoutSettings.DEFAULT,
+                setOf(child1, imageCapture),
+                useCaseConfigFactory
+            )
+        streamSharing.bindToCamera(camera, null, null, defaultConfig)
+        streamSharing.onSuggestedStreamSpecUpdated(StreamSpec.builder(size).build(), null)
         imageCapture.targetRotation = Surface.ROTATION_90
 
         // Act: the child takes a picture.
@@ -363,7 +412,14 @@
                     .useCaseConfig
             )
         streamSharing =
-            StreamSharing(camera, setOf(unspecifiedChild, hdrChild), useCaseConfigFactory)
+            StreamSharing(
+                camera,
+                secondaryCamera,
+                LayoutSettings.DEFAULT,
+                LayoutSettings.DEFAULT,
+                setOf(unspecifiedChild, hdrChild),
+                useCaseConfigFactory
+            )
         assertThat(
                 streamSharing
                     .mergeConfigs(
@@ -392,7 +448,15 @@
                     .setDynamicRange(HLG_10_BIT)
                     .useCaseConfig
             )
-        streamSharing = StreamSharing(camera, setOf(sdrChild, hdrChild), useCaseConfigFactory)
+        streamSharing =
+            StreamSharing(
+                camera,
+                secondaryCamera,
+                LayoutSettings.DEFAULT,
+                LayoutSettings.DEFAULT,
+                setOf(sdrChild, hdrChild),
+                useCaseConfigFactory
+            )
         streamSharing.mergeConfigs(
             camera.cameraInfoInternal, /*extendedConfig*/
             null, /*cameraDefaultConfig*/
@@ -415,10 +479,10 @@
     @Test
     fun hasEffect_createEffectNode() {
         // Arrange: set an effect on StreamSharing.
-        streamSharing.bindToCamera(frontCamera, null, defaultConfig)
+        streamSharing.bindToCamera(frontCamera, null, null, defaultConfig)
         streamSharing.effect = effect
         // Act: create pipeline
-        streamSharing.onSuggestedStreamSpecUpdated(StreamSpec.builder(size).build())
+        streamSharing.onSuggestedStreamSpecUpdated(StreamSpec.builder(size).build(), null)
         shadowOf(getMainLooper()).idle()
         // Assert: processors received input and output Surfaces.
         assertThat(effectProcessor.surfaceRequest).isNotNull()
@@ -450,8 +514,8 @@
         val value = "value"
         val result1 = child1.setTagBundleOnSessionConfigAsync(key, value)
         val result2 = child2.setTagBundleOnSessionConfigAsync(key, value)
-        streamSharing.bindToCamera(camera, null, defaultConfig)
-        streamSharing.onSuggestedStreamSpecUpdated(StreamSpec.builder(size).build())
+        streamSharing.bindToCamera(camera, null, null, defaultConfig)
+        streamSharing.onSuggestedStreamSpecUpdated(StreamSpec.builder(size).build(), null)
 
         // Act: feed metadata to the parent.
         streamSharing.sessionConfig.repeatingCameraCaptureCallbacks
@@ -467,14 +531,23 @@
     fun sessionConfigHasStreamSpecImplementationOptions_whenCreatePipeline() {
         // Arrange: set up StreamSharing with ImageCapture as child
         val imageCapture = ImageCapture.Builder().build()
-        streamSharing = StreamSharing(camera, setOf(child1, imageCapture), useCaseConfigFactory)
-        streamSharing.bindToCamera(camera, null, defaultConfig)
+        streamSharing =
+            StreamSharing(
+                camera,
+                secondaryCamera,
+                LayoutSettings.DEFAULT,
+                LayoutSettings.DEFAULT,
+                setOf(child1, imageCapture),
+                useCaseConfigFactory
+            )
+        streamSharing.bindToCamera(camera, null, null, defaultConfig)
 
         // Act: update stream specification.
         val streamSpecOptions = MutableOptionsBundle.create()
         streamSpecOptions.insertOption(testImplementationOption, testImplementationOptionValue)
         streamSharing.onSuggestedStreamSpecUpdated(
-            StreamSpec.builder(size).setImplementationOptions(streamSpecOptions).build()
+            StreamSpec.builder(size).setImplementationOptions(streamSpecOptions).build(),
+            null
         )
 
         // Assert: the session config gets the correct implementation options from stream
@@ -492,12 +565,21 @@
         // Arrange: set up StreamSharing with ImageCapture as child with initial stream
         // specification implementation options.
         val imageCapture = ImageCapture.Builder().build()
-        streamSharing = StreamSharing(camera, setOf(child1, imageCapture), useCaseConfigFactory)
-        streamSharing.bindToCamera(camera, null, defaultConfig)
+        streamSharing =
+            StreamSharing(
+                camera,
+                secondaryCamera,
+                LayoutSettings.DEFAULT,
+                LayoutSettings.DEFAULT,
+                setOf(child1, imageCapture),
+                useCaseConfigFactory
+            )
+        streamSharing.bindToCamera(camera, null, null, defaultConfig)
         var streamSpecOptions = MutableOptionsBundle.create()
         streamSpecOptions.insertOption(testImplementationOption, testImplementationOptionValue)
         streamSharing.updateSuggestedStreamSpec(
-            StreamSpec.builder(size).setImplementationOptions(streamSpecOptions).build()
+            StreamSpec.builder(size).setImplementationOptions(streamSpecOptions).build(),
+            null
         )
 
         // Act: update stream specification implementation options.
@@ -519,11 +601,19 @@
     @Test
     fun sessionConfigIsSdr_whenUpdateStreamSpecWithDefaultDynamicRangeSettings() {
         // Arrange.
-        streamSharing = StreamSharing(camera, setOf(child1), useCaseConfigFactory)
-        streamSharing.bindToCamera(camera, null, defaultConfig)
+        streamSharing =
+            StreamSharing(
+                camera,
+                secondaryCamera,
+                LayoutSettings.DEFAULT,
+                LayoutSettings.DEFAULT,
+                setOf(child1),
+                useCaseConfigFactory
+            )
+        streamSharing.bindToCamera(camera, null, null, defaultConfig)
 
         // Act: update stream specification.
-        streamSharing.onSuggestedStreamSpecUpdated(StreamSpec.builder(size).build())
+        streamSharing.onSuggestedStreamSpecUpdated(StreamSpec.builder(size).build(), null)
 
         // Assert: the session config gets the correct dynamic range.
         val outputConfigs = streamSharing.sessionConfig.outputConfigs
@@ -534,12 +624,21 @@
     @Test
     fun sessionConfigIsHdr_whenUpdateStreamSpecWithHdr() {
         // Arrange.
-        streamSharing = StreamSharing(camera, setOf(child1), useCaseConfigFactory)
-        streamSharing.bindToCamera(camera, null, defaultConfig)
+        streamSharing =
+            StreamSharing(
+                camera,
+                secondaryCamera,
+                LayoutSettings.DEFAULT,
+                LayoutSettings.DEFAULT,
+                setOf(child1),
+                useCaseConfigFactory
+            )
+        streamSharing.bindToCamera(camera, null, null, defaultConfig)
 
         // Act: update stream specification.
         streamSharing.onSuggestedStreamSpecUpdated(
-            StreamSpec.builder(size).setDynamicRange(HLG_10_BIT).build()
+            StreamSpec.builder(size).setDynamicRange(HLG_10_BIT).build(),
+            null
         )
 
         // Assert: the session config gets the correct dynamic range.
@@ -555,11 +654,14 @@
         streamSharing =
             StreamSharing(
                 camera,
+                secondaryCamera,
+                LayoutSettings.DEFAULT,
+                LayoutSettings.DEFAULT,
                 setOf(previewBuilder.build()),
                 Camera2UseCaseConfigFactory(context)
             )
-        streamSharing.bindToCamera(camera, null, defaultConfig)
-        streamSharing.onSuggestedStreamSpecUpdated(StreamSpec.builder(size).build())
+        streamSharing.bindToCamera(camera, null, null, defaultConfig)
+        streamSharing.onSuggestedStreamSpecUpdated(StreamSpec.builder(size).build(), null)
         return streamSharing.sessionConfig
     }
 
@@ -603,10 +705,10 @@
     @Test
     fun updateStreamSpec_propagatesToChildren() {
         // Arrange: bind StreamSharing to the camera.
-        streamSharing.bindToCamera(camera, null, defaultConfig)
+        streamSharing.bindToCamera(camera, null, null, defaultConfig)
 
         // Act: update suggested specs.
-        streamSharing.onSuggestedStreamSpecUpdated(StreamSpec.builder(size).build())
+        streamSharing.onSuggestedStreamSpecUpdated(StreamSpec.builder(size).build(), null)
 
         // Assert: StreamSharing pipeline created.
         val node = streamSharing.sharingNode!!
@@ -633,8 +735,8 @@
     @Test
     fun onError_restartsPipeline() {
         // Arrange: bind stream sharing and update specs.
-        streamSharing.bindToCamera(camera, null, defaultConfig)
-        streamSharing.onSuggestedStreamSpecUpdated(StreamSpec.builder(size).build())
+        streamSharing.bindToCamera(camera, null, null, defaultConfig)
+        streamSharing.onSuggestedStreamSpecUpdated(StreamSpec.builder(size).build(), null)
         val cameraEdge = streamSharing.cameraEdge
         val node = streamSharing.sharingNode
         // Arrange: given children new Surfaces.
@@ -649,9 +751,10 @@
 
         // Act: send error to StreamSharing
         val sessionConfig = streamSharing.sessionConfig
-        sessionConfig.errorListeners
-            .single()
-            .onError(sessionConfig, SessionConfig.SessionError.SESSION_ERROR_SURFACE_NEEDS_RESET)
+        sessionConfig.errorListener!!.onError(
+            sessionConfig,
+            SessionConfig.SessionError.SESSION_ERROR_SURFACE_NEEDS_RESET
+        )
         shadowOf(getMainLooper()).idle()
 
         // Assert: StreamSharing and children pipeline are recreated.
@@ -684,7 +787,7 @@
     @Test
     fun bindChildToCamera_virtualCameraHasNoTransform() {
         // Act.
-        streamSharing.bindToCamera(camera, null, null)
+        streamSharing.bindToCamera(camera, null, null, null)
         // Assert.
         assertThat(child1.camera!!.hasTransform).isFalse()
         assertThat(child2.camera!!.hasTransform).isFalse()
@@ -693,7 +796,7 @@
     @Test
     fun bindChildToCamera_virtualCameraHasNoRotationDegrees() {
         // Act.
-        streamSharing.bindToCamera(frontCamera, null, null)
+        streamSharing.bindToCamera(frontCamera, null, null, null)
         // Assert.
         assertThat(child1.camera!!.cameraInfoInternal.getSensorRotationDegrees(Surface.ROTATION_0))
             .isEqualTo(0)
@@ -707,7 +810,7 @@
         assertThat(child1.camera).isNull()
         assertThat(child2.camera).isNull()
         // Act: bind to camera.
-        streamSharing.bindToCamera(camera, null, null)
+        streamSharing.bindToCamera(camera, null, null, null)
         // Assert: children bound to the virtual camera.
         assertThat(child1.camera).isInstanceOf(VirtualCamera::class.java)
         assertThat(child1.mergedConfigRetrieved).isTrue()
@@ -766,7 +869,15 @@
                 .setVideoStabilizationEnabled(false)
                 .build()
 
-        streamSharing = StreamSharing(camera, setOf(preview, videoCapture), useCaseConfigFactory)
+        streamSharing =
+            StreamSharing(
+                camera,
+                secondaryCamera,
+                LayoutSettings.DEFAULT,
+                LayoutSettings.DEFAULT,
+                setOf(preview, videoCapture),
+                useCaseConfigFactory
+            )
         assertThat(
                 streamSharing
                     .mergeConfigs(
@@ -787,7 +898,15 @@
                 .setVideoStabilizationEnabled(true)
                 .build()
 
-        streamSharing = StreamSharing(camera, setOf(preview, videoCapture), useCaseConfigFactory)
+        streamSharing =
+            StreamSharing(
+                camera,
+                secondaryCamera,
+                LayoutSettings.DEFAULT,
+                LayoutSettings.DEFAULT,
+                setOf(preview, videoCapture),
+                useCaseConfigFactory
+            )
         assertThat(
                 streamSharing
                     .mergeConfigs(
@@ -805,11 +924,19 @@
         // Arrange.
         val preview = Preview.Builder().build()
         val imageCapture = ImageCapture.Builder().build()
-        streamSharing = StreamSharing(camera, setOf(preview, imageCapture), useCaseConfigFactory)
-        streamSharing.bindToCamera(camera, null, defaultConfig)
+        streamSharing =
+            StreamSharing(
+                camera,
+                secondaryCamera,
+                LayoutSettings.DEFAULT,
+                LayoutSettings.DEFAULT,
+                setOf(preview, imageCapture),
+                useCaseConfigFactory
+            )
+        streamSharing.bindToCamera(camera, null, null, defaultConfig)
 
         // Act: update stream specification.
-        streamSharing.onSuggestedStreamSpecUpdated(StreamSpec.builder(size).build())
+        streamSharing.onSuggestedStreamSpecUpdated(StreamSpec.builder(size).build(), null)
 
         // Assert:
         assertThat(streamSharing.sessionConfig.templateType).isEqualTo(TEMPLATE_PREVIEW)
@@ -822,11 +949,18 @@
         val imageCapture = ImageCapture.Builder().build()
         val videoCapture = VideoCapture.withOutput(Recorder.Builder().build())
         streamSharing =
-            StreamSharing(camera, setOf(preview, imageCapture, videoCapture), useCaseConfigFactory)
-        streamSharing.bindToCamera(camera, null, defaultConfig)
+            StreamSharing(
+                camera,
+                secondaryCamera,
+                LayoutSettings.DEFAULT,
+                LayoutSettings.DEFAULT,
+                setOf(preview, imageCapture, videoCapture),
+                useCaseConfigFactory
+            )
+        streamSharing.bindToCamera(camera, null, null, defaultConfig)
 
         // Act: update stream specification.
-        streamSharing.onSuggestedStreamSpecUpdated(StreamSpec.builder(size).build())
+        streamSharing.onSuggestedStreamSpecUpdated(StreamSpec.builder(size).build(), null)
 
         // Assert:
         assertThat(streamSharing.sessionConfig.templateType).isEqualTo(TEMPLATE_RECORD)
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/streamsharing/VirtualCameraAdapterTest.kt b/camera/camera-core/src/test/java/androidx/camera/core/streamsharing/VirtualCameraAdapterTest.kt
index 70f7f69..b5fe6ac 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/streamsharing/VirtualCameraAdapterTest.kt
+++ b/camera/camera-core/src/test/java/androidx/camera/core/streamsharing/VirtualCameraAdapterTest.kt
@@ -78,7 +78,7 @@
         private val SESSION_CONFIG_WITH_SURFACE =
             SessionConfig.Builder()
                 .addSurface(FakeDeferrableSurface(INPUT_SIZE, ImageFormat.PRIVATE))
-                .addErrorListener { _, error -> receivedSessionConfigError = error }
+                .setErrorListener { _, error -> receivedSessionConfigError = error }
                 .build()
     }
 
@@ -99,8 +99,9 @@
     @Before
     fun setUp() {
         adapter =
-            VirtualCameraAdapter(parentCamera, setOf(child1, child2), useCaseConfigFactory) { _, _
-                ->
+            VirtualCameraAdapter(parentCamera, null, setOf(child1, child2), useCaseConfigFactory) {
+                _,
+                _ ->
                 snapshotTriggered = true
                 Futures.immediateFuture(null)
             }
@@ -162,9 +163,10 @@
         useCase.bindToCamera(
             parentCamera,
             null,
+            null,
             useCase.getDefaultConfig(true, useCaseConfigFactory)
         )
-        useCase.updateSuggestedStreamSpec(StreamSpec.builder(INPUT_SIZE).build())
+        useCase.updateSuggestedStreamSpec(StreamSpec.builder(INPUT_SIZE).build(), null)
         return VirtualCameraAdapter.getChildSurface(useCase)
     }
 
@@ -270,6 +272,7 @@
         adapter =
             VirtualCameraAdapter(
                 parentCamera,
+                null,
                 setOf(preview, child2, imageCapture),
                 useCaseConfigFactory
             ) { _, _ ->
diff --git a/camera/camera-effects-still-portrait/api/1.4.0-beta03.txt b/camera/camera-effects-still-portrait/api/1.4.0-beta03.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/camera/camera-effects-still-portrait/api/1.4.0-beta03.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/camera/camera-effects-still-portrait/api/res-1.4.0-beta03.txt b/camera/camera-effects-still-portrait/api/res-1.4.0-beta03.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/camera/camera-effects-still-portrait/api/res-1.4.0-beta03.txt
diff --git a/camera/camera-effects-still-portrait/api/restricted_1.4.0-beta03.txt b/camera/camera-effects-still-portrait/api/restricted_1.4.0-beta03.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/camera/camera-effects-still-portrait/api/restricted_1.4.0-beta03.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/camera/camera-effects/api/1.4.0-beta03.txt b/camera/camera-effects/api/1.4.0-beta03.txt
new file mode 100644
index 0000000..414b558
--- /dev/null
+++ b/camera/camera-effects/api/1.4.0-beta03.txt
@@ -0,0 +1,30 @@
+// Signature format: 4.0
+package androidx.camera.effects {
+
+  @com.google.auto.value.AutoValue public abstract class Frame {
+    ctor public Frame();
+    method public abstract android.graphics.Rect getCropRect();
+    method public android.graphics.Canvas getOverlayCanvas();
+    method @IntRange(from=0, to=359) public abstract int getRotationDegrees();
+    method public abstract android.graphics.Matrix getSensorToBufferTransform();
+    method public abstract android.util.Size getSize();
+    method public abstract long getTimestampNanos();
+    method public abstract boolean isMirroring();
+  }
+
+  public class OverlayEffect extends androidx.camera.core.CameraEffect implements java.lang.AutoCloseable {
+    ctor public OverlayEffect(int, int, android.os.Handler, androidx.core.util.Consumer<java.lang.Throwable!>);
+    method public void clearOnDrawListener();
+    method public void close();
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Integer!> drawFrameAsync(long);
+    method public android.os.Handler getHandler();
+    method public int getQueueDepth();
+    method public void setOnDrawListener(androidx.arch.core.util.Function<androidx.camera.effects.Frame!,java.lang.Boolean!>);
+    field public static final int RESULT_CANCELLED_BY_CALLER = 4; // 0x4
+    field public static final int RESULT_FRAME_NOT_FOUND = 2; // 0x2
+    field public static final int RESULT_INVALID_SURFACE = 3; // 0x3
+    field public static final int RESULT_SUCCESS = 1; // 0x1
+  }
+
+}
+
diff --git a/camera/camera-effects/api/res-1.4.0-beta03.txt b/camera/camera-effects/api/res-1.4.0-beta03.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/camera/camera-effects/api/res-1.4.0-beta03.txt
diff --git a/camera/camera-effects/api/restricted_1.4.0-beta03.txt b/camera/camera-effects/api/restricted_1.4.0-beta03.txt
new file mode 100644
index 0000000..414b558
--- /dev/null
+++ b/camera/camera-effects/api/restricted_1.4.0-beta03.txt
@@ -0,0 +1,30 @@
+// Signature format: 4.0
+package androidx.camera.effects {
+
+  @com.google.auto.value.AutoValue public abstract class Frame {
+    ctor public Frame();
+    method public abstract android.graphics.Rect getCropRect();
+    method public android.graphics.Canvas getOverlayCanvas();
+    method @IntRange(from=0, to=359) public abstract int getRotationDegrees();
+    method public abstract android.graphics.Matrix getSensorToBufferTransform();
+    method public abstract android.util.Size getSize();
+    method public abstract long getTimestampNanos();
+    method public abstract boolean isMirroring();
+  }
+
+  public class OverlayEffect extends androidx.camera.core.CameraEffect implements java.lang.AutoCloseable {
+    ctor public OverlayEffect(int, int, android.os.Handler, androidx.core.util.Consumer<java.lang.Throwable!>);
+    method public void clearOnDrawListener();
+    method public void close();
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Integer!> drawFrameAsync(long);
+    method public android.os.Handler getHandler();
+    method public int getQueueDepth();
+    method public void setOnDrawListener(androidx.arch.core.util.Function<androidx.camera.effects.Frame!,java.lang.Boolean!>);
+    field public static final int RESULT_CANCELLED_BY_CALLER = 4; // 0x4
+    field public static final int RESULT_FRAME_NOT_FOUND = 2; // 0x2
+    field public static final int RESULT_INVALID_SURFACE = 3; // 0x3
+    field public static final int RESULT_SUCCESS = 1; // 0x1
+  }
+
+}
+
diff --git a/camera/camera-extensions/api/1.4.0-beta03.txt b/camera/camera-extensions/api/1.4.0-beta03.txt
new file mode 100644
index 0000000..c454cfc
--- /dev/null
+++ b/camera/camera-extensions/api/1.4.0-beta03.txt
@@ -0,0 +1,35 @@
+// Signature format: 4.0
+package androidx.camera.extensions {
+
+  public interface CameraExtensionsControl {
+    method public default void setExtensionStrength(@IntRange(from=0, to=100) int);
+  }
+
+  public interface CameraExtensionsInfo {
+    method public default androidx.lifecycle.LiveData<java.lang.Integer!>? getCurrentExtensionMode();
+    method public default androidx.lifecycle.LiveData<java.lang.Integer!>? getExtensionStrength();
+    method public default boolean isCurrentExtensionModeAvailable();
+    method public default boolean isExtensionStrengthAvailable();
+  }
+
+  public final class ExtensionMode {
+    field public static final int AUTO = 5; // 0x5
+    field public static final int BOKEH = 1; // 0x1
+    field public static final int FACE_RETOUCH = 4; // 0x4
+    field public static final int HDR = 2; // 0x2
+    field public static final int NIGHT = 3; // 0x3
+    field public static final int NONE = 0; // 0x0
+  }
+
+  public final class ExtensionsManager {
+    method public androidx.camera.extensions.CameraExtensionsControl? getCameraExtensionsControl(androidx.camera.core.CameraControl);
+    method public androidx.camera.extensions.CameraExtensionsInfo getCameraExtensionsInfo(androidx.camera.core.CameraInfo);
+    method public android.util.Range<java.lang.Long!>? getEstimatedCaptureLatencyRange(androidx.camera.core.CameraSelector, int);
+    method public androidx.camera.core.CameraSelector getExtensionEnabledCameraSelector(androidx.camera.core.CameraSelector, int);
+    method public static com.google.common.util.concurrent.ListenableFuture<androidx.camera.extensions.ExtensionsManager!> getInstanceAsync(android.content.Context, androidx.camera.core.CameraProvider);
+    method public boolean isExtensionAvailable(androidx.camera.core.CameraSelector, int);
+    method public boolean isImageAnalysisSupported(androidx.camera.core.CameraSelector, int);
+  }
+
+}
+
diff --git a/camera/camera-extensions/api/res-1.4.0-beta03.txt b/camera/camera-extensions/api/res-1.4.0-beta03.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/camera/camera-extensions/api/res-1.4.0-beta03.txt
diff --git a/camera/camera-extensions/api/restricted_1.4.0-beta03.txt b/camera/camera-extensions/api/restricted_1.4.0-beta03.txt
new file mode 100644
index 0000000..c454cfc
--- /dev/null
+++ b/camera/camera-extensions/api/restricted_1.4.0-beta03.txt
@@ -0,0 +1,35 @@
+// Signature format: 4.0
+package androidx.camera.extensions {
+
+  public interface CameraExtensionsControl {
+    method public default void setExtensionStrength(@IntRange(from=0, to=100) int);
+  }
+
+  public interface CameraExtensionsInfo {
+    method public default androidx.lifecycle.LiveData<java.lang.Integer!>? getCurrentExtensionMode();
+    method public default androidx.lifecycle.LiveData<java.lang.Integer!>? getExtensionStrength();
+    method public default boolean isCurrentExtensionModeAvailable();
+    method public default boolean isExtensionStrengthAvailable();
+  }
+
+  public final class ExtensionMode {
+    field public static final int AUTO = 5; // 0x5
+    field public static final int BOKEH = 1; // 0x1
+    field public static final int FACE_RETOUCH = 4; // 0x4
+    field public static final int HDR = 2; // 0x2
+    field public static final int NIGHT = 3; // 0x3
+    field public static final int NONE = 0; // 0x0
+  }
+
+  public final class ExtensionsManager {
+    method public androidx.camera.extensions.CameraExtensionsControl? getCameraExtensionsControl(androidx.camera.core.CameraControl);
+    method public androidx.camera.extensions.CameraExtensionsInfo getCameraExtensionsInfo(androidx.camera.core.CameraInfo);
+    method public android.util.Range<java.lang.Long!>? getEstimatedCaptureLatencyRange(androidx.camera.core.CameraSelector, int);
+    method public androidx.camera.core.CameraSelector getExtensionEnabledCameraSelector(androidx.camera.core.CameraSelector, int);
+    method public static com.google.common.util.concurrent.ListenableFuture<androidx.camera.extensions.ExtensionsManager!> getInstanceAsync(android.content.Context, androidx.camera.core.CameraProvider);
+    method public boolean isExtensionAvailable(androidx.camera.core.CameraSelector, int);
+    method public boolean isImageAnalysisSupported(androidx.camera.core.CameraSelector, int);
+  }
+
+}
+
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/internal/AdvancedSessionProcessorTest.kt b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/internal/AdvancedSessionProcessorTest.kt
index 356f7cb..a71816d 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/internal/AdvancedSessionProcessorTest.kt
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/internal/AdvancedSessionProcessorTest.kt
@@ -721,6 +721,8 @@
         // OnePlus doesn't support physical camera well.
         assumeFalse("oneplus".equals(Build.BRAND, ignoreCase = true))
         assumeAllowsSharedSurface()
+        // Physical CameraId doesn't work on OnePlus
+        assumeFalse(Build.BRAND.uppercase().equals("ONEPLUS"))
         val physicalCameraIdList = getPhysicalCameraId(cameraSelector)
         assumeTrue(physicalCameraIdList.isNotEmpty())
 
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/internal/sessionprocessor/StillCaptureProcessorTest.kt b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/internal/sessionprocessor/StillCaptureProcessorTest.kt
index f47dc56..f5b033e 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/internal/sessionprocessor/StillCaptureProcessorTest.kt
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/internal/sessionprocessor/StillCaptureProcessorTest.kt
@@ -102,7 +102,10 @@
         fakeCaptureProcessorImpl = FakeCaptureProcessorImpl()
     }
 
-    private fun initStillCaptureProcessor(postviewOutputSurface: OutputSurface? = null) {
+    private fun initStillCaptureProcessor(
+        postviewOutputSurface: OutputSurface? = null,
+        overrideTimestamp: Boolean = false
+    ) {
         imageReaderOutputYuv =
             ImageReaderProxys.createIsolatedReader(WIDTH, HEIGHT, ImageFormat.YUV_420_888, 2)
         stillCaptureProcessor =
@@ -110,7 +113,8 @@
                 fakeCaptureProcessorImpl,
                 imageReaderOutputYuv!!.surface!!,
                 Size(WIDTH, HEIGHT),
-                postviewOutputSurface
+                postviewOutputSurface,
+                overrideTimestamp,
             )
     }
 
@@ -145,6 +149,13 @@
     }
 
     @Test
+    fun canOutputYuv_withOverrideTimestamp(): Unit = runBlocking {
+        initStillCaptureProcessor(overrideTimestamp = true)
+        withTimeout(10000) { openCameraAndCaptureImageAwait(listOf(1)) }
+            .use { assertThat(it.format).isEqualTo(ImageFormat.YUV_420_888) }
+    }
+
+    @Test
     fun onErrorInvoked_oemProcessingFailed(): Unit = runBlocking {
         initStillCaptureProcessor()
         fakeCaptureProcessorImpl.enableThrowExceptionDuringProcess()
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/compat/quirk/CaptureOutputSurfaceOccupiedQuirk.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/compat/quirk/CaptureOutputSurfaceOccupiedQuirk.java
new file mode 100644
index 0000000..4b06897
--- /dev/null
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/compat/quirk/CaptureOutputSurfaceOccupiedQuirk.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.extensions.internal.compat.quirk;
+
+import android.os.Build;
+
+import androidx.camera.core.impl.Quirk;
+
+/**
+ * <p>QuirkSummary
+ * Bug Id: b/347142571
+ * Description:
+ * On Xiaomi 13 or 13T devices, it doesn't close the previous ImageWriter that connects to the
+ * output surface when camera is closed. Therefore when suspending the app and resuming, same
+ * ImageCapture surface is passed to the onOutputSurface and cause it failed to connect the
+ * surface to the another ImageWriter.
+ * Device(s): Xiaomi devices.
+ *
+ */
+public class CaptureOutputSurfaceOccupiedQuirk implements Quirk {
+    static boolean load() {
+        return Build.BRAND.equalsIgnoreCase("Xiaomi");
+    }
+}
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/compat/quirk/DeviceQuirksLoader.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/compat/quirk/DeviceQuirksLoader.java
index 79bdcc0..4b5a2d9 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/compat/quirk/DeviceQuirksLoader.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/compat/quirk/DeviceQuirksLoader.java
@@ -50,6 +50,10 @@
             quirks.add(new GetAvailableKeysNeedsOnInit());
         }
 
+        if (CaptureOutputSurfaceOccupiedQuirk.load()) {
+            quirks.add(new CaptureOutputSurfaceOccupiedQuirk());
+        }
+
         return quirks;
     }
 }
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/compat/workaround/CaptureOutputSurfaceForCaptureProcessor.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/compat/workaround/CaptureOutputSurfaceForCaptureProcessor.java
new file mode 100644
index 0000000..edf011b
--- /dev/null
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/compat/workaround/CaptureOutputSurfaceForCaptureProcessor.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.extensions.internal.compat.workaround;
+
+import android.graphics.ImageFormat;
+import android.media.Image;
+import android.media.ImageWriter;
+import android.os.Build;
+import android.util.Size;
+import android.view.Surface;
+
+import androidx.annotation.DoNotInline;
+import androidx.annotation.GuardedBy;
+import androidx.annotation.NonNull;
+import androidx.annotation.OptIn;
+import androidx.annotation.RequiresApi;
+import androidx.camera.core.ExperimentalGetImage;
+import androidx.camera.core.ImageProxy;
+import androidx.camera.core.ImageReaderProxys;
+import androidx.camera.core.Logger;
+import androidx.camera.core.impl.ImageReaderProxy;
+import androidx.camera.core.impl.utils.executor.CameraXExecutors;
+import androidx.camera.extensions.internal.compat.quirk.CaptureOutputSurfaceOccupiedQuirk;
+import androidx.camera.extensions.internal.compat.quirk.DeviceQuirks;
+
+/**
+ * A workaround for 2 purposes:
+ * <p>1. Use a intermedia surface when passing the capture output surface
+ * to a {@link androidx.camera.extensions.impl.CaptureProcessorImpl} if
+ * {@link androidx.camera.extensions.internal.compat.quirk.CaptureOutputSurfaceOccupiedQuirk}
+ * exists on the device. This is needed if the OEM doesn't close the internal {@link ImageWriter}
+ * when the camera is closed and cause the output capture surface can't be connected to another
+ * {@link ImageWriter}.
+ *
+ * <p>2. Overriding the timestamp of the output image (via an intermediate surface) to ensure it
+ * matches the timestamp in {@link androidx.camera.core.impl.CameraCaptureResult}. For devices
+ * implementing v1.2 or prior, it is possible that they don't write the same timestamp to the
+ * output image.
+ *
+ * <p>If the quirk doesn't exist, it will pass along the output surface directly.
+ */
+@OptIn(markerClass = ExperimentalGetImage.class)
+public class CaptureOutputSurfaceForCaptureProcessor {
+    private static final String TAG = "CaptureOutputSurface";
+    private static final int MAX_IMAGES = 2;
+    private static final long UNSPECIFIED_TIMESTAMP = -1;
+
+    private final Object mLock = new Object();
+    @GuardedBy("mLock")
+    private final ImageWriter mImageWriter;
+    @GuardedBy("mLock")
+    private final ImageReaderProxy mIntermediateImageReader;
+    @GuardedBy("mLock")
+    private boolean mIsClosed = false;
+    @NonNull
+    private final Surface mOutputSurface;
+    private final boolean mNeedIntermediaSurface;
+    private final boolean mNeedOverrideTimestamp;
+    long mOutputImageTimeStamp = UNSPECIFIED_TIMESTAMP;
+
+
+    public CaptureOutputSurfaceForCaptureProcessor(
+            @NonNull Surface surface, @NonNull Size surfaceSize, boolean needOverrideTimestamp) {
+        mNeedOverrideTimestamp = needOverrideTimestamp;
+        mNeedIntermediaSurface = DeviceQuirks.get(CaptureOutputSurfaceOccupiedQuirk.class) != null
+                || needOverrideTimestamp;
+        if (Build.VERSION.SDK_INT >= 29 && mNeedIntermediaSurface) {
+            Logger.d(TAG, "Enabling intermediate surface");
+            mIntermediateImageReader = ImageReaderProxys.createIsolatedReader(
+                    surfaceSize.getWidth(), surfaceSize.getHeight(),
+                    ImageFormat.YUV_420_888, MAX_IMAGES);
+            mOutputSurface = mIntermediateImageReader.getSurface();
+            mImageWriter = ImageWriterCompat.newInstance(
+                    surface, MAX_IMAGES, ImageFormat.YUV_420_888);
+            mIntermediateImageReader.setOnImageAvailableListener(imageReader -> {
+                synchronized (mLock) {
+                    if (mIsClosed) {
+                        return;
+                    }
+                    ImageProxy imageProxy = imageReader.acquireNextImage();
+                    if (imageProxy != null) {
+                        Image image = imageProxy.getImage();
+                        if (image != null) {
+                            if (mNeedOverrideTimestamp
+                                    && mOutputImageTimeStamp != UNSPECIFIED_TIMESTAMP) {
+                                Api23Impl.setImageTimestamp(image, mOutputImageTimeStamp);
+                            }
+                            ImageWriterCompat.queueInputImage(mImageWriter, image);
+                        }
+                    }
+                }
+            }, CameraXExecutors.directExecutor());
+        } else {
+            mOutputSurface = surface;
+            mIntermediateImageReader = null;
+            mImageWriter = null;
+        }
+    }
+
+    /**
+     * Set the timestamp on the output image.
+     */
+    public void setOutputImageTimestamp(long timestamp) {
+        if (mNeedOverrideTimestamp) {
+            mOutputImageTimeStamp = timestamp;
+        }
+    }
+
+    /**
+     * Returns the output surface that is supported to pass to
+     * {@link androidx.camera.extensions.impl.CaptureProcessorImpl#onOutputSurface(Surface, int)}.
+     */
+    @NonNull
+    public Surface getSurface() {
+        return mOutputSurface;
+    }
+
+    /**
+     * Close the resources.
+     */
+    public void close() {
+        synchronized (mLock) {
+            mIsClosed = true;
+            if (Build.VERSION.SDK_INT >= 29 && mNeedIntermediaSurface) {
+                mIntermediateImageReader.clearOnImageAvailableListener();
+                mIntermediateImageReader.close();
+                ImageWriterCompat.close(mImageWriter);
+            }
+        }
+    }
+
+    @RequiresApi(29)
+    static final class ImageWriterCompat {
+        private ImageWriterCompat() {
+        }
+
+        /**
+         * Creates a {@link ImageWriter} instance.
+         */
+        @NonNull
+        @DoNotInline
+        static ImageWriter newInstance(@NonNull Surface surface, int maxImages, int imageFormat) {
+            return ImageWriter.newInstance(surface, maxImages, imageFormat);
+        }
+
+        static void queueInputImage(@NonNull ImageWriter imageWriter, @NonNull Image image) {
+            imageWriter.queueInputImage(image);
+        }
+
+        @DoNotInline
+        static void close(ImageWriter imageWriter) {
+            imageWriter.close();
+        }
+    }
+
+    @RequiresApi(23)
+    static final class Api23Impl {
+        private Api23Impl() {}
+
+        static void setImageTimestamp(@NonNull Image image, long timestamp) {
+            image.setTimestamp(timestamp);
+        }
+    }
+}
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/BasicExtenderSessionProcessor.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/BasicExtenderSessionProcessor.java
index e5d2d33..7eac730 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/BasicExtenderSessionProcessor.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/BasicExtenderSessionProcessor.java
@@ -96,7 +96,7 @@
     @GuardedBy("mLock")
     private final Map<CaptureRequest.Key<?>, Object> mParameters = new LinkedHashMap<>();
     @GuardedBy("mLock")
-    private final Map<Integer, Long> mCaptureStartedTimestampMap = new HashMap<>();
+    private final Map<Integer, Long> mRequestCompletedTimestampMap = new HashMap<>();
     private OnEnableDisableSessionDurationCheck mOnEnableDisableSessionDurationCheck =
             new OnEnableDisableSessionDurationCheck();
     @Nullable
@@ -173,7 +173,8 @@
             mStillCaptureProcessor = new StillCaptureProcessor(
                     captureProcessor, mCaptureOutputSurface.getSurface(),
                     mCaptureOutputSurface.getSize(),
-                    mPostviewOutputSurface);
+                    mPostviewOutputSurface,
+                    /* needOverrideTimestamp */ !mWillReceiveOnCaptureCompleted);
         } else {
             mCaptureOutputConfig = SurfaceOutputConfig.create(
                     sLastOutputConfigId.getAndIncrement(),
@@ -468,13 +469,13 @@
         mRequestProcessor.stopRepeating();
     }
 
-    private long getCaptureStartedTimestamp(int captureSequenceId) {
+    private long getRequestCompletedTimestamp(int captureSequenceId) {
         synchronized (mLock) {
-            Long timestamp = mCaptureStartedTimestampMap.get(captureSequenceId);
+            Long timestamp = mRequestCompletedTimestampMap.get(captureSequenceId);
             if (timestamp == null) {
                 return INVALID_TIMESTAMP;
             }
-            mCaptureStartedTimestampMap.remove(captureSequenceId);
+            mRequestCompletedTimestampMap.remove(captureSequenceId);
             return timestamp;
         }
     }
@@ -527,9 +528,6 @@
                     long frameNumber, long timestamp) {
                 if (!mIsCaptureStarted) {
                     mIsCaptureStarted = true;
-                    synchronized (mLock) {
-                        mCaptureStartedTimestampMap.put(captureSequenceId, timestamp);
-                    }
                     captureCallback.onCaptureStarted(captureSequenceId, timestamp);
                 }
             }
@@ -546,6 +544,13 @@
                         (RequestBuilder.RequestProcessorRequest) request;
 
                 if (mStillCaptureProcessor != null) {
+                    synchronized (mLock) {
+                        if (!mRequestCompletedTimestampMap.containsKey(captureSequenceId)) {
+                            mRequestCompletedTimestampMap.put(
+                                    captureSequenceId, cameraCaptureResult.getTimestamp());
+                        }
+                    }
+
                     mStillCaptureProcessor.notifyCaptureResult(
                             totalCaptureResult,
                             requestProcessorRequest.getCaptureStageId());
@@ -615,7 +620,7 @@
                                 // If ProcessResultImpl.onCaptureCompleted won't be invoked,
                                 // We finish the capture sequence using the timestamp retrieved at
                                 // onCaptureStarted when the process() completed.
-                                long timestamp = getCaptureStartedTimestamp(captureSequenceId);
+                                long timestamp = getRequestCompletedTimestamp(captureSequenceId);
                                 if (timestamp == INVALID_TIMESTAMP) {
                                     Logger.e(TAG, "Cannot get timestamp for the capture result");
                                     captureCallback.onCaptureFailed(captureSequenceId);
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/StillCaptureProcessor.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/StillCaptureProcessor.java
index e0d1cf5..6a48430 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/StillCaptureProcessor.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/StillCaptureProcessor.java
@@ -35,6 +35,7 @@
 import androidx.camera.extensions.internal.ClientVersion;
 import androidx.camera.extensions.internal.ExtensionVersion;
 import androidx.camera.extensions.internal.Version;
+import androidx.camera.extensions.internal.compat.workaround.CaptureOutputSurfaceForCaptureProcessor;
 import androidx.core.util.Preconditions;
 
 import java.util.HashMap;
@@ -59,6 +60,7 @@
  */
 class StillCaptureProcessor {
     private static final String TAG = "StillCaptureProcessor";
+    private static final long UNSPECIFIED_TIMESTAMP = -1;
     @NonNull
     final CaptureProcessorImpl mCaptureProcessorImpl;
     @NonNull
@@ -75,15 +77,23 @@
     // Stores the first capture result for injecting into the output JPEG ImageProxy.
     @GuardedBy("mLock")
     TotalCaptureResult mSourceCaptureResult = null;
+    CaptureOutputSurfaceForCaptureProcessor mCaptureOutputSurface;
     @GuardedBy("mLock")
     boolean mIsClosed = false;
+    long mTimeStampForOutputImage = UNSPECIFIED_TIMESTAMP;
 
     StillCaptureProcessor(@NonNull CaptureProcessorImpl captureProcessorImpl,
-            @NonNull Surface captureOutputSurface,
+            @NonNull Surface outputSurface,
             @NonNull Size surfaceSize,
-            @Nullable OutputSurface postviewOutputSurface) {
+            @Nullable OutputSurface postviewOutputSurface,
+            boolean needOverrideTimestamp) {
         mCaptureProcessorImpl = captureProcessorImpl;
-        mCaptureProcessorImpl.onOutputSurface(captureOutputSurface, ImageFormat.YUV_420_888);
+
+        mCaptureOutputSurface = new CaptureOutputSurfaceForCaptureProcessor(
+                outputSurface, surfaceSize, needOverrideTimestamp);
+
+        mCaptureProcessorImpl.onOutputSurface(
+                mCaptureOutputSurface.getSurface(), ImageFormat.YUV_420_888);
         mCaptureProcessorImpl.onImageFormatUpdate(ImageFormat.YUV_420_888);
 
         mIsPostviewConfigured = (postviewOutputSurface != null);
@@ -124,6 +134,7 @@
     void startCapture(boolean enablePostview, @NonNull List<Integer> captureIdList,
             @NonNull OnCaptureResultCallback onCaptureResultCallback) {
         Logger.d(TAG, "Start the capture: enablePostview=" + enablePostview);
+        mTimeStampForOutputImage = UNSPECIFIED_TIMESTAMP;
         synchronized (mLock) {
             Preconditions.checkState(!mIsClosed, "StillCaptureProcessor is closed. Can't invoke "
                     + "startCapture()");
@@ -249,6 +260,14 @@
             int captureStageId) {
         mCaptureResultImageMatcher.captureResultIncoming(captureResult,
                 captureStageId);
+        // Fetch the timestamp for the 1st captureResult received.
+        if (mTimeStampForOutputImage == UNSPECIFIED_TIMESTAMP) {
+            Long timestamp = captureResult.get(CaptureResult.SENSOR_TIMESTAMP);
+            if (timestamp != null) {
+                mTimeStampForOutputImage = timestamp;
+                mCaptureOutputSurface.setOutputImageTimestamp(mTimeStampForOutputImage);
+            }
+        }
 
         synchronized (mLock) {
             if (mSourceCaptureResult == null) {
@@ -272,6 +291,7 @@
             clearCaptureResults();
             mCaptureResultImageMatcher.clearImageReferenceListener();
             mCaptureResultImageMatcher.clear();
+            mCaptureOutputSurface.close();
         }
     }
 }
diff --git a/camera/camera-feature-combination-query-play-services/api/1.4.0-beta03.txt b/camera/camera-feature-combination-query-play-services/api/1.4.0-beta03.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/camera/camera-feature-combination-query-play-services/api/1.4.0-beta03.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/camera/camera-feature-combination-query-play-services/api/res-1.4.0-beta03.txt b/camera/camera-feature-combination-query-play-services/api/res-1.4.0-beta03.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/camera/camera-feature-combination-query-play-services/api/res-1.4.0-beta03.txt
diff --git a/camera/camera-feature-combination-query-play-services/api/restricted_1.4.0-beta03.txt b/camera/camera-feature-combination-query-play-services/api/restricted_1.4.0-beta03.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/camera/camera-feature-combination-query-play-services/api/restricted_1.4.0-beta03.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/camera/camera-feature-combination-query/api/1.4.0-beta03.txt b/camera/camera-feature-combination-query/api/1.4.0-beta03.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/camera/camera-feature-combination-query/api/1.4.0-beta03.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/camera/camera-feature-combination-query/api/res-1.4.0-beta03.txt b/camera/camera-feature-combination-query/api/res-1.4.0-beta03.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/camera/camera-feature-combination-query/api/res-1.4.0-beta03.txt
diff --git a/camera/camera-feature-combination-query/api/restricted_1.4.0-beta03.txt b/camera/camera-feature-combination-query/api/restricted_1.4.0-beta03.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/camera/camera-feature-combination-query/api/restricted_1.4.0-beta03.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/camera/camera-lifecycle/api/1.4.0-beta03.txt b/camera/camera-lifecycle/api/1.4.0-beta03.txt
new file mode 100644
index 0000000..a73d56a
--- /dev/null
+++ b/camera/camera-lifecycle/api/1.4.0-beta03.txt
@@ -0,0 +1,36 @@
+// Signature format: 4.0
+package androidx.camera.lifecycle {
+
+  @SuppressCompatibility @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface ExperimentalCameraProviderConfiguration {
+  }
+
+  public final class ProcessCameraProvider implements androidx.camera.core.CameraProvider {
+    method @MainThread public androidx.camera.core.Camera bindToLifecycle(androidx.lifecycle.LifecycleOwner lifecycleOwner, androidx.camera.core.CameraSelector cameraSelector, androidx.camera.core.UseCase?... useCases);
+    method @MainThread public androidx.camera.core.Camera bindToLifecycle(androidx.lifecycle.LifecycleOwner lifecycleOwner, androidx.camera.core.CameraSelector cameraSelector, androidx.camera.core.UseCaseGroup useCaseGroup);
+    method @MainThread public androidx.camera.core.ConcurrentCamera bindToLifecycle(java.util.List<androidx.camera.core.ConcurrentCamera.SingleCameraConfig?> singleCameraConfigs);
+    method @SuppressCompatibility @androidx.camera.lifecycle.ExperimentalCameraProviderConfiguration public static void configureInstance(androidx.camera.core.CameraXConfig cameraXConfig);
+    method public java.util.List<androidx.camera.core.CameraInfo> getAvailableCameraInfos();
+    method public java.util.List<java.util.List<androidx.camera.core.CameraInfo>> getAvailableConcurrentCameraInfos();
+    method public static com.google.common.util.concurrent.ListenableFuture<androidx.camera.lifecycle.ProcessCameraProvider> getInstance(android.content.Context context);
+    method @kotlin.jvm.Throws(exceptionClasses=CameraInfoUnavailableException::class) public boolean hasCamera(androidx.camera.core.CameraSelector cameraSelector) throws androidx.camera.core.CameraInfoUnavailableException;
+    method public boolean isBound(androidx.camera.core.UseCase useCase);
+    method @MainThread public boolean isConcurrentCameraModeOn();
+    method @VisibleForTesting public com.google.common.util.concurrent.ListenableFuture<java.lang.Void> shutdownAsync();
+    method @MainThread public void unbind(androidx.camera.core.UseCase?... useCases);
+    method @MainThread public void unbindAll();
+    property public final java.util.List<java.util.List<androidx.camera.core.CameraInfo>> availableConcurrentCameraInfos;
+    property @MainThread public final boolean isConcurrentCameraModeOn;
+    field public static final androidx.camera.lifecycle.ProcessCameraProvider.Companion Companion;
+  }
+
+  public static final class ProcessCameraProvider.Companion {
+    method @SuppressCompatibility @androidx.camera.lifecycle.ExperimentalCameraProviderConfiguration public void configureInstance(androidx.camera.core.CameraXConfig cameraXConfig);
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.camera.lifecycle.ProcessCameraProvider> getInstance(android.content.Context context);
+  }
+
+  public final class ProcessCameraProviderExtKt {
+    method public static suspend Object? awaitInstance(androidx.camera.lifecycle.ProcessCameraProvider.Companion, android.content.Context context, kotlin.coroutines.Continuation<? super androidx.camera.lifecycle.ProcessCameraProvider>);
+  }
+
+}
+
diff --git a/camera/camera-lifecycle/api/res-1.4.0-beta03.txt b/camera/camera-lifecycle/api/res-1.4.0-beta03.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/camera/camera-lifecycle/api/res-1.4.0-beta03.txt
diff --git a/camera/camera-lifecycle/api/restricted_1.4.0-beta03.txt b/camera/camera-lifecycle/api/restricted_1.4.0-beta03.txt
new file mode 100644
index 0000000..a73d56a
--- /dev/null
+++ b/camera/camera-lifecycle/api/restricted_1.4.0-beta03.txt
@@ -0,0 +1,36 @@
+// Signature format: 4.0
+package androidx.camera.lifecycle {
+
+  @SuppressCompatibility @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface ExperimentalCameraProviderConfiguration {
+  }
+
+  public final class ProcessCameraProvider implements androidx.camera.core.CameraProvider {
+    method @MainThread public androidx.camera.core.Camera bindToLifecycle(androidx.lifecycle.LifecycleOwner lifecycleOwner, androidx.camera.core.CameraSelector cameraSelector, androidx.camera.core.UseCase?... useCases);
+    method @MainThread public androidx.camera.core.Camera bindToLifecycle(androidx.lifecycle.LifecycleOwner lifecycleOwner, androidx.camera.core.CameraSelector cameraSelector, androidx.camera.core.UseCaseGroup useCaseGroup);
+    method @MainThread public androidx.camera.core.ConcurrentCamera bindToLifecycle(java.util.List<androidx.camera.core.ConcurrentCamera.SingleCameraConfig?> singleCameraConfigs);
+    method @SuppressCompatibility @androidx.camera.lifecycle.ExperimentalCameraProviderConfiguration public static void configureInstance(androidx.camera.core.CameraXConfig cameraXConfig);
+    method public java.util.List<androidx.camera.core.CameraInfo> getAvailableCameraInfos();
+    method public java.util.List<java.util.List<androidx.camera.core.CameraInfo>> getAvailableConcurrentCameraInfos();
+    method public static com.google.common.util.concurrent.ListenableFuture<androidx.camera.lifecycle.ProcessCameraProvider> getInstance(android.content.Context context);
+    method @kotlin.jvm.Throws(exceptionClasses=CameraInfoUnavailableException::class) public boolean hasCamera(androidx.camera.core.CameraSelector cameraSelector) throws androidx.camera.core.CameraInfoUnavailableException;
+    method public boolean isBound(androidx.camera.core.UseCase useCase);
+    method @MainThread public boolean isConcurrentCameraModeOn();
+    method @VisibleForTesting public com.google.common.util.concurrent.ListenableFuture<java.lang.Void> shutdownAsync();
+    method @MainThread public void unbind(androidx.camera.core.UseCase?... useCases);
+    method @MainThread public void unbindAll();
+    property public final java.util.List<java.util.List<androidx.camera.core.CameraInfo>> availableConcurrentCameraInfos;
+    property @MainThread public final boolean isConcurrentCameraModeOn;
+    field public static final androidx.camera.lifecycle.ProcessCameraProvider.Companion Companion;
+  }
+
+  public static final class ProcessCameraProvider.Companion {
+    method @SuppressCompatibility @androidx.camera.lifecycle.ExperimentalCameraProviderConfiguration public void configureInstance(androidx.camera.core.CameraXConfig cameraXConfig);
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.camera.lifecycle.ProcessCameraProvider> getInstance(android.content.Context context);
+  }
+
+  public final class ProcessCameraProviderExtKt {
+    method public static suspend Object? awaitInstance(androidx.camera.lifecycle.ProcessCameraProvider.Companion, android.content.Context context, kotlin.coroutines.Continuation<? super androidx.camera.lifecycle.ProcessCameraProvider>);
+  }
+
+}
+
diff --git a/camera/camera-lifecycle/build.gradle b/camera/camera-lifecycle/build.gradle
index f3d649a1..84855f8 100644
--- a/camera/camera-lifecycle/build.gradle
+++ b/camera/camera-lifecycle/build.gradle
@@ -38,6 +38,7 @@
     implementation(libs.kotlinCoroutinesAndroid)
     implementation("androidx.concurrent:concurrent-futures:1.1.0")
     implementation("androidx.concurrent:concurrent-futures-ktx:1.1.0")
+    implementation("androidx.tracing:tracing-ktx:1.2.0")
 
     annotationProcessor(libs.autoValue)
 
diff --git a/camera/camera-lifecycle/src/androidTest/java/androidx/camera/lifecycle/LifecycleCameraRepositoryTest.java b/camera/camera-lifecycle/src/androidTest/java/androidx/camera/lifecycle/LifecycleCameraRepositoryTest.java
index e1df029..35bbda9 100644
--- a/camera/camera-lifecycle/src/androidTest/java/androidx/camera/lifecycle/LifecycleCameraRepositoryTest.java
+++ b/camera/camera-lifecycle/src/androidTest/java/androidx/camera/lifecycle/LifecycleCameraRepositoryTest.java
@@ -22,6 +22,7 @@
 
 import static java.util.Collections.emptyList;
 
+import androidx.camera.core.LayoutSettings;
 import androidx.camera.core.concurrent.CameraCoordinator;
 import androidx.camera.core.impl.CameraConfig;
 import androidx.camera.core.impl.CameraConfigs;
@@ -628,8 +629,12 @@
     private CameraUseCaseAdapter createCameraUseCaseAdapterWithNewCameraConfig() {
         CameraConfig cameraConfig = new FakeCameraConfig();
         return new CameraUseCaseAdapter(mCamera,
+                null,
                 new RestrictedCameraInfo((CameraInfoInternal) mCamera.getCameraInfo(),
                         cameraConfig),
+                null,
+                LayoutSettings.DEFAULT,
+                LayoutSettings.DEFAULT,
                 mCameraCoordinator,
                 new FakeCameraDeviceSurfaceManager(),
                 new FakeUseCaseConfigFactory());
diff --git a/camera/camera-lifecycle/src/androidTest/java/androidx/camera/lifecycle/ProcessCameraProviderTest.kt b/camera/camera-lifecycle/src/androidTest/java/androidx/camera/lifecycle/ProcessCameraProviderTest.kt
index d1a3542..a214cd9 100644
--- a/camera/camera-lifecycle/src/androidTest/java/androidx/camera/lifecycle/ProcessCameraProviderTest.kt
+++ b/camera/camera-lifecycle/src/androidTest/java/androidx/camera/lifecycle/ProcessCameraProviderTest.kt
@@ -42,6 +42,7 @@
 import androidx.camera.core.impl.MutableOptionsBundle
 import androidx.camera.core.impl.RestrictedCameraInfo
 import androidx.camera.core.impl.SessionProcessor
+import androidx.camera.core.impl.UseCaseConfigFactory.CaptureType
 import androidx.camera.core.impl.utils.executor.CameraXExecutors.mainThreadExecutor
 import androidx.camera.testing.fakes.FakeAppConfig
 import androidx.camera.testing.fakes.FakeCamera
@@ -55,6 +56,8 @@
 import androidx.camera.testing.impl.fakes.FakeSessionProcessor
 import androidx.camera.testing.impl.fakes.FakeSurfaceEffect
 import androidx.camera.testing.impl.fakes.FakeSurfaceProcessor
+import androidx.camera.testing.impl.fakes.FakeUseCase
+import androidx.camera.testing.impl.fakes.FakeUseCaseConfig
 import androidx.camera.testing.impl.fakes.FakeUseCaseConfigFactory
 import androidx.concurrent.futures.await
 import androidx.test.core.app.ApplicationProvider
@@ -951,6 +954,49 @@
     }
 
     @Test
+    fun bindConcurrentCamera_isDualRecording() {
+        ProcessCameraProvider.configureInstance(createConcurrentCameraAppConfig())
+
+        runBlocking(MainScope().coroutineContext) {
+            provider = ProcessCameraProvider.getInstance(context).await()
+            val useCase0 = Preview.Builder().setSessionOptionUnpacker { _, _, _ -> }.build()
+            val useCase1 =
+                FakeUseCase(
+                    FakeUseCaseConfig.Builder(CaptureType.VIDEO_CAPTURE).useCaseConfig,
+                    CaptureType.VIDEO_CAPTURE
+                )
+
+            val singleCameraConfig0 =
+                SingleCameraConfig(
+                    CameraSelector.DEFAULT_BACK_CAMERA,
+                    UseCaseGroup.Builder().addUseCase(useCase0).addUseCase(useCase1).build(),
+                    lifecycleOwner0
+                )
+            val singleCameraConfig1 =
+                SingleCameraConfig(
+                    CameraSelector.DEFAULT_FRONT_CAMERA,
+                    UseCaseGroup.Builder().addUseCase(useCase0).addUseCase(useCase1).build(),
+                    lifecycleOwner1
+                )
+
+            if (context.packageManager.hasSystemFeature(FEATURE_CAMERA_CONCURRENT)) {
+                val concurrentCamera =
+                    provider.bindToLifecycle(listOf(singleCameraConfig0, singleCameraConfig1))
+
+                assertThat(concurrentCamera).isNotNull()
+                assertThat(concurrentCamera.cameras.size).isEqualTo(1)
+                assertThat(provider.isBound(useCase0)).isTrue()
+                assertThat(provider.isBound(useCase1)).isTrue()
+                assertThat(provider.isConcurrentCameraModeOn).isTrue()
+            } else {
+                assertThrows<UnsupportedOperationException> {
+                    provider.bindToLifecycle(listOf(singleCameraConfig0, singleCameraConfig1))
+                }
+            }
+        }
+    }
+
+    @Test
     @RequiresApi(23)
     fun bindWithExtensions_doesNotImpactPreviousCamera(): Unit =
         runBlocking(Dispatchers.Main) {
diff --git a/camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/LifecycleCamera.java b/camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/LifecycleCamera.java
index 8ae413d..d579d3c 100644
--- a/camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/LifecycleCamera.java
+++ b/camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/LifecycleCamera.java
@@ -16,10 +16,13 @@
 
 package androidx.camera.lifecycle;
 
+import android.annotation.SuppressLint;
 import android.os.Build;
 
 import androidx.annotation.GuardedBy;
 import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.VisibleForTesting;
 import androidx.camera.core.Camera;
 import androidx.camera.core.CameraControl;
 import androidx.camera.core.CameraInfo;
@@ -41,7 +44,10 @@
  * A {@link CameraUseCaseAdapter} whose starting and stopping is controlled by a
  *  {@link Lifecycle}.
  */
-final class LifecycleCamera implements LifecycleObserver, Camera {
+@SuppressLint("UsesNonDefaultVisibleForTesting")
+@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+public final class LifecycleCamera implements LifecycleObserver, Camera {
     private final Object mLock = new Object();
 
     @GuardedBy("mLock")
@@ -76,7 +82,7 @@
     }
 
     @OnLifecycleEvent(Lifecycle.Event.ON_START)
-    public void onStart(LifecycleOwner lifecycleOwner) {
+    public void onStart(@NonNull LifecycleOwner lifecycleOwner) {
         synchronized (mLock) {
             if (!mSuspended && !mReleased) {
                 mCameraUseCaseAdapter.attachUseCases();
@@ -86,7 +92,7 @@
     }
 
     @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
-    public void onStop(LifecycleOwner lifecycleOwner) {
+    public void onStop(@NonNull LifecycleOwner lifecycleOwner) {
         synchronized (mLock) {
             if (!mSuspended && !mReleased) {
                 mCameraUseCaseAdapter.detachUseCases();
@@ -96,14 +102,14 @@
     }
 
     @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
-    public void onDestroy(LifecycleOwner lifecycleOwner) {
+    public void onDestroy(@NonNull LifecycleOwner lifecycleOwner) {
         synchronized (mLock) {
             mCameraUseCaseAdapter.removeUseCases(mCameraUseCaseAdapter.getUseCases());
         }
     }
 
     @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
-    public void onResume(LifecycleOwner lifecycleOwner) {
+    public void onResume(@NonNull LifecycleOwner lifecycleOwner) {
         // ActiveResumingMode is required for Multi-window which is supported since Android 7(N).
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
             mCameraUseCaseAdapter.setActiveResumingMode(true);
@@ -111,7 +117,7 @@
     }
 
     @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
-    public void onPause(LifecycleOwner lifecycleOwner) {
+    public void onPause(@NonNull LifecycleOwner lifecycleOwner) {
         // ActiveResumingMode is required for Multi-window which is supported since Android 7(N).
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
             mCameraUseCaseAdapter.setActiveResumingMode(false);
@@ -179,12 +185,17 @@
         }
     }
 
+    /**
+     * Retrieves the lifecycle owner.
+     */
+    @NonNull
     public LifecycleOwner getLifecycleOwner() {
         synchronized (mLock) {
             return mLifecycleOwner;
         }
     }
 
+    @NonNull
     public CameraUseCaseAdapter getCameraUseCaseAdapter() {
         return mCameraUseCaseAdapter;
     }
diff --git a/camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/LifecycleCameraRepository.java b/camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/LifecycleCameraRepository.java
index 56ba8e7..c1d50f1 100644
--- a/camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/LifecycleCameraRepository.java
+++ b/camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/LifecycleCameraRepository.java
@@ -175,7 +175,7 @@
             LifecycleOwner lifecycleOwner = lifecycleCamera.getLifecycleOwner();
             Key key = Key.create(lifecycleOwner,
                     CameraUseCaseAdapter.generateCameraId(
-                            (RestrictedCameraInfo) lifecycleCamera.getCameraInfo()));
+                            (RestrictedCameraInfo) lifecycleCamera.getCameraInfo(), null));
 
             LifecycleCameraRepositoryObserver observer =
                     getLifecycleCameraRepositoryObserver(lifecycleOwner);
diff --git a/camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/ProcessCameraProvider.kt b/camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/ProcessCameraProvider.kt
index bdaa0ff..8e1c9b4 100644
--- a/camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/ProcessCameraProvider.kt
+++ b/camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/ProcessCameraProvider.kt
@@ -38,6 +38,7 @@
 import androidx.camera.core.ImageAnalysis
 import androidx.camera.core.ImageCapture
 import androidx.camera.core.InitializationException
+import androidx.camera.core.LayoutSettings
 import androidx.camera.core.Preview
 import androidx.camera.core.UseCase
 import androidx.camera.core.UseCaseGroup
@@ -51,6 +52,8 @@
 import androidx.camera.core.impl.CameraInternal
 import androidx.camera.core.impl.ExtendedCameraConfigProviderStore
 import androidx.camera.core.impl.RestrictedCameraInfo
+import androidx.camera.core.impl.UseCaseConfig
+import androidx.camera.core.impl.UseCaseConfigFactory.CaptureType
 import androidx.camera.core.impl.utils.ContextUtil
 import androidx.camera.core.impl.utils.Threads
 import androidx.camera.core.impl.utils.executor.CameraXExecutors
@@ -63,7 +66,9 @@
 import androidx.core.util.Preconditions
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.LifecycleOwner
+import androidx.tracing.trace
 import com.google.common.util.concurrent.ListenableFuture
+import java.util.Objects
 import java.util.Objects.requireNonNull
 
 /**
@@ -195,24 +200,28 @@
         lifecycleOwner: LifecycleOwner,
         cameraSelector: CameraSelector,
         vararg useCases: UseCase?
-    ): Camera {
-        if (cameraOperatingMode == CAMERA_OPERATING_MODE_CONCURRENT) {
-            throw UnsupportedOperationException(
-                "bindToLifecycle for single camera is not supported in concurrent camera mode, " +
-                    "call unbindAll() first"
-            )
+    ): Camera =
+        trace("CX:bindToLifecycle") {
+            if (cameraOperatingMode == CAMERA_OPERATING_MODE_CONCURRENT) {
+                throw UnsupportedOperationException(
+                    "bindToLifecycle for single camera is not supported in concurrent camera mode, " +
+                        "call unbindAll() first"
+                )
+            }
+            cameraOperatingMode = CAMERA_OPERATING_MODE_SINGLE
+            val camera =
+                bindToLifecycle(
+                    lifecycleOwner,
+                    cameraSelector,
+                    null,
+                    LayoutSettings.DEFAULT,
+                    LayoutSettings.DEFAULT,
+                    null,
+                    emptyList<CameraEffect>(),
+                    *useCases
+                )
+            return@trace camera
         }
-        cameraOperatingMode = CAMERA_OPERATING_MODE_SINGLE
-        val camera =
-            bindToLifecycle(
-                lifecycleOwner,
-                cameraSelector,
-                null,
-                emptyList<CameraEffect>(),
-                *useCases
-            )
-        return camera
-    }
 
     /**
      * Binds a [UseCaseGroup] to a [LifecycleOwner].
@@ -231,24 +240,28 @@
         lifecycleOwner: LifecycleOwner,
         cameraSelector: CameraSelector,
         useCaseGroup: UseCaseGroup
-    ): Camera {
-        if (cameraOperatingMode == CAMERA_OPERATING_MODE_CONCURRENT) {
-            throw UnsupportedOperationException(
-                "bindToLifecycle for single camera is not supported in concurrent camera mode, " +
-                    "call unbindAll() first."
-            )
+    ): Camera =
+        trace("CX:bindToLifecycle-UseCaseGroup") {
+            if (cameraOperatingMode == CAMERA_OPERATING_MODE_CONCURRENT) {
+                throw UnsupportedOperationException(
+                    "bindToLifecycle for single camera is not supported in concurrent camera mode, " +
+                        "call unbindAll() first."
+                )
+            }
+            cameraOperatingMode = CAMERA_OPERATING_MODE_SINGLE
+            val camera =
+                bindToLifecycle(
+                    lifecycleOwner,
+                    cameraSelector,
+                    null,
+                    LayoutSettings.DEFAULT,
+                    LayoutSettings.DEFAULT,
+                    useCaseGroup.viewPort,
+                    useCaseGroup.effects,
+                    *useCaseGroup.useCases.toTypedArray<UseCase>()
+                )
+            return@trace camera
         }
-        cameraOperatingMode = CAMERA_OPERATING_MODE_SINGLE
-        val camera =
-            bindToLifecycle(
-                lifecycleOwner,
-                cameraSelector,
-                useCaseGroup.viewPort,
-                useCaseGroup.effects,
-                *useCaseGroup.useCases.toTypedArray<UseCase>()
-            )
-        return camera
-    }
 
     /**
      * Binds list of [SingleCameraConfig]s to [LifecycleOwner].
@@ -269,6 +282,11 @@
      * own [UseCase]s and [LifecycleOwner]. See
      * [CameraX lifecycles]({@docRoot}training/camerax/architecture#lifecycles)
      *
+     * If the concurrent logical cameras are binding the same preview and video capture use cases,
+     * the concurrent cameras video recording will be supported. The concurrent camera preview
+     * stream will be shared with video capture and record the concurrent cameras as a whole. The
+     * [LayoutSettings] can be used to configure the position of each camera stream.
+     *
      * If we want to open concurrent physical cameras, which are two front cameras or two back
      * cameras, the device needs to support physical cameras and the capability could be checked via
      * [CameraInfo.isLogicalMultiCameraSupported]. Each physical cameras can have its own [UseCase]s
@@ -305,113 +323,164 @@
      */
     @OptIn(ExperimentalCameraInfo::class)
     @MainThread
-    fun bindToLifecycle(singleCameraConfigs: List<SingleCameraConfig?>): ConcurrentCamera {
-        if (singleCameraConfigs.size < 2) {
-            throw IllegalArgumentException("Concurrent camera needs two camera configs.")
-        }
-
-        if (singleCameraConfigs.size > 2) {
-            throw IllegalArgumentException(
-                "Concurrent camera is only supporting two cameras at maximum."
-            )
-        }
-
-        val firstCameraConfig = singleCameraConfigs[0]!!
-        val secondCameraConfig = singleCameraConfigs[1]!!
-
-        val cameras: MutableList<Camera> = ArrayList()
-        if (
-            firstCameraConfig.cameraSelector.lensFacing ==
-                secondCameraConfig.cameraSelector.lensFacing
-        ) {
-            if (cameraOperatingMode == CAMERA_OPERATING_MODE_CONCURRENT) {
-                throw UnsupportedOperationException(
-                    "Camera is already running, call unbindAll() before binding more cameras."
-                )
+    fun bindToLifecycle(singleCameraConfigs: List<SingleCameraConfig?>): ConcurrentCamera =
+        trace("CX:bindToLifecycle-Concurrent") {
+            if (singleCameraConfigs.size < 2) {
+                throw IllegalArgumentException("Concurrent camera needs two camera configs.")
             }
-            if (
-                firstCameraConfig.lifecycleOwner != secondCameraConfig.lifecycleOwner ||
-                    firstCameraConfig.useCaseGroup.viewPort !=
-                        secondCameraConfig.useCaseGroup.viewPort ||
-                    firstCameraConfig.useCaseGroup.effects !=
-                        secondCameraConfig.useCaseGroup.effects
-            ) {
+
+            if (singleCameraConfigs.size > 2) {
                 throw IllegalArgumentException(
-                    "Two camera configs need to have the same lifecycle owner, view port and " +
-                        "effects."
-                )
-            }
-            val lifecycleOwner = firstCameraConfig.lifecycleOwner
-            val cameraSelector = firstCameraConfig.cameraSelector
-            val viewPort = firstCameraConfig.useCaseGroup.viewPort
-            val effects = firstCameraConfig.useCaseGroup.effects
-            val useCases: MutableList<UseCase> = ArrayList()
-            for (config: SingleCameraConfig? in singleCameraConfigs) {
-                // Connect physical camera id with use case.
-                for (useCase: UseCase in config!!.useCaseGroup.useCases) {
-                    config.cameraSelector.physicalCameraId?.let { useCase.setPhysicalCameraId(it) }
-                }
-                useCases.addAll(config.useCaseGroup.useCases)
-            }
-
-            cameraOperatingMode = CAMERA_OPERATING_MODE_SINGLE
-            val camera =
-                bindToLifecycle(
-                    lifecycleOwner,
-                    cameraSelector,
-                    viewPort,
-                    effects,
-                    *useCases.toTypedArray<UseCase>()
-                )
-            cameras.add(camera)
-        } else {
-            if (!mContext!!.packageManager.hasSystemFeature(FEATURE_CAMERA_CONCURRENT)) {
-                throw UnsupportedOperationException(
-                    "Concurrent camera is not supported on the device."
+                    "Concurrent camera is only supporting two cameras at maximum."
                 )
             }
 
-            if (cameraOperatingMode == CAMERA_OPERATING_MODE_SINGLE) {
-                throw UnsupportedOperationException(
-                    "Camera is already running, call unbindAll() before binding more cameras."
-                )
-            }
+            val firstCameraConfig = singleCameraConfigs[0]!!
+            val secondCameraConfig = singleCameraConfigs[1]!!
 
-            val cameraInfosToBind: MutableList<CameraInfo> = ArrayList()
-            val firstCameraInfo: CameraInfo
-            val secondCameraInfo: CameraInfo
-            try {
-                firstCameraInfo = getCameraInfo(firstCameraConfig.cameraSelector)
-                secondCameraInfo = getCameraInfo(secondCameraConfig.cameraSelector)
-            } catch (e: IllegalArgumentException) {
-                throw IllegalArgumentException("Invalid camera selectors in camera configs.")
-            }
-            cameraInfosToBind.add(firstCameraInfo)
-            cameraInfosToBind.add(secondCameraInfo)
+            val cameras: MutableList<Camera> = ArrayList()
             if (
-                activeConcurrentCameraInfos.isNotEmpty() &&
-                    cameraInfosToBind != activeConcurrentCameraInfos
+                firstCameraConfig.cameraSelector.lensFacing ==
+                    secondCameraConfig.cameraSelector.lensFacing
             ) {
-                throw UnsupportedOperationException(
-                    "Cameras are already running, call unbindAll() before binding more cameras."
-                )
-            }
+                if (cameraOperatingMode == CAMERA_OPERATING_MODE_CONCURRENT) {
+                    throw UnsupportedOperationException(
+                        "Camera is already running, call unbindAll() before binding more cameras."
+                    )
+                }
+                if (
+                    firstCameraConfig.lifecycleOwner != secondCameraConfig.lifecycleOwner ||
+                        firstCameraConfig.useCaseGroup.viewPort !=
+                            secondCameraConfig.useCaseGroup.viewPort ||
+                        firstCameraConfig.useCaseGroup.effects !=
+                            secondCameraConfig.useCaseGroup.effects
+                ) {
+                    throw IllegalArgumentException(
+                        "Two camera configs need to have the same lifecycle owner, view port and " +
+                            "effects."
+                    )
+                }
+                val lifecycleOwner = firstCameraConfig.lifecycleOwner
+                val cameraSelector = firstCameraConfig.cameraSelector
+                val viewPort = firstCameraConfig.useCaseGroup.viewPort
+                val effects = firstCameraConfig.useCaseGroup.effects
+                val useCases: MutableList<UseCase> = ArrayList()
+                for (config: SingleCameraConfig? in singleCameraConfigs) {
+                    // Connect physical camera id with use case.
+                    for (useCase: UseCase in config!!.useCaseGroup.useCases) {
+                        config.cameraSelector.physicalCameraId?.let {
+                            useCase.setPhysicalCameraId(it)
+                        }
+                    }
+                    useCases.addAll(config.useCaseGroup.useCases)
+                }
 
-            cameraOperatingMode = CAMERA_OPERATING_MODE_CONCURRENT
-            for (config: SingleCameraConfig? in singleCameraConfigs) {
+                cameraOperatingMode = CAMERA_OPERATING_MODE_SINGLE
                 val camera =
                     bindToLifecycle(
-                        config!!.lifecycleOwner,
-                        config.cameraSelector,
-                        config.useCaseGroup.viewPort,
-                        config.useCaseGroup.effects,
-                        *config.useCaseGroup.useCases.toTypedArray<UseCase>()
+                        lifecycleOwner,
+                        cameraSelector,
+                        null,
+                        LayoutSettings.DEFAULT,
+                        LayoutSettings.DEFAULT,
+                        viewPort,
+                        effects,
+                        *useCases.toTypedArray<UseCase>()
                     )
                 cameras.add(camera)
+            } else {
+                if (!mContext!!.packageManager.hasSystemFeature(FEATURE_CAMERA_CONCURRENT)) {
+                    throw UnsupportedOperationException(
+                        "Concurrent camera is not supported on the device."
+                    )
+                }
+
+                if (cameraOperatingMode == CAMERA_OPERATING_MODE_SINGLE) {
+                    throw UnsupportedOperationException(
+                        "Camera is already running, call unbindAll() before binding more cameras."
+                    )
+                }
+
+                val cameraInfosToBind: MutableList<CameraInfo> = ArrayList()
+                val firstCameraInfo: CameraInfo
+                val secondCameraInfo: CameraInfo
+                try {
+                    firstCameraInfo = getCameraInfo(firstCameraConfig.cameraSelector)
+                    secondCameraInfo = getCameraInfo(secondCameraConfig.cameraSelector)
+                } catch (e: IllegalArgumentException) {
+                    throw IllegalArgumentException("Invalid camera selectors in camera configs.")
+                }
+                cameraInfosToBind.add(firstCameraInfo)
+                cameraInfosToBind.add(secondCameraInfo)
+                if (
+                    activeConcurrentCameraInfos.isNotEmpty() &&
+                        cameraInfosToBind != activeConcurrentCameraInfos
+                ) {
+                    throw UnsupportedOperationException(
+                        "Cameras are already running, call unbindAll() before binding more cameras."
+                    )
+                }
+
+                cameraOperatingMode = CAMERA_OPERATING_MODE_CONCURRENT
+
+                // For dual camera video capture, we are only supporting two use cases:
+                // Preview + VideoCapture. If ImageCapture support is added, the validation logic
+                // will be updated accordingly.
+                var isDualCameraVideoCapture = false
+                if (
+                    Objects.equals(
+                        firstCameraConfig.useCaseGroup.useCases,
+                        secondCameraConfig.useCaseGroup.useCases
+                    ) && firstCameraConfig.useCaseGroup.useCases.size == 2
+                ) {
+                    val useCase0 = firstCameraConfig.useCaseGroup.useCases[0]
+                    val useCase1 = firstCameraConfig.useCaseGroup.useCases[1]
+                    isDualCameraVideoCapture =
+                        (isVideoCapture(useCase0) && isPreview(useCase1)) ||
+                            (isPreview(useCase0) && isVideoCapture(useCase1))
+                }
+
+                if (isDualCameraVideoCapture) {
+                    cameras.add(
+                        bindToLifecycle(
+                            firstCameraConfig.lifecycleOwner,
+                            firstCameraConfig.cameraSelector,
+                            secondCameraConfig.cameraSelector,
+                            firstCameraConfig.layoutSettings,
+                            secondCameraConfig.layoutSettings,
+                            firstCameraConfig.useCaseGroup.viewPort,
+                            firstCameraConfig.useCaseGroup.effects,
+                            *firstCameraConfig.useCaseGroup.useCases.toTypedArray<UseCase>(),
+                        )
+                    )
+                } else {
+                    for (config: SingleCameraConfig? in singleCameraConfigs) {
+                        val camera =
+                            bindToLifecycle(
+                                config!!.lifecycleOwner,
+                                config.cameraSelector,
+                                null,
+                                LayoutSettings.DEFAULT,
+                                LayoutSettings.DEFAULT,
+                                config.useCaseGroup.viewPort,
+                                config.useCaseGroup.effects,
+                                *config.useCaseGroup.useCases.toTypedArray<UseCase>()
+                            )
+                        cameras.add(camera)
+                    }
+                }
+                activeConcurrentCameraInfos = cameraInfosToBind
             }
-            activeConcurrentCameraInfos = cameraInfosToBind
+            return@trace ConcurrentCamera(cameras)
         }
-        return ConcurrentCamera(cameras)
+
+    private fun isVideoCapture(useCase: UseCase): Boolean {
+        return useCase.currentConfig.containsOption(UseCaseConfig.OPTION_CAPTURE_TYPE) &&
+            useCase.currentConfig.captureType == CaptureType.VIDEO_CAPTURE
+    }
+
+    private fun isPreview(useCase: UseCase): Boolean {
+        return useCase is Preview
     }
 
     /**
@@ -458,8 +527,11 @@
      *
      * @param lifecycleOwner The [LifecycleOwner] which controls the lifecycle transitions of the
      *   use cases.
-     * @param cameraSelector The camera selector which determines the camera to use for set of use
-     *   cases.
+     * @param primaryCameraSelector The primary camera selector which determines the camera to use
+     *   for set of use cases.
+     * @param secondaryCameraSelector The secondary camera selector in dual camera case.
+     * @param primaryLayoutSettings The layout settings for the primary camera.
+     * @param secondaryLayoutSettings The layout settings for the secondary camera.
      * @param viewPort The viewPort which represents the visible camera sensor rect.
      * @param effects The effects applied to the camera outputs.
      * @param useCases The use cases to bind to a lifecycle.
@@ -474,69 +546,95 @@
     @OptIn(ExperimentalCameraInfo::class)
     internal fun bindToLifecycle(
         lifecycleOwner: LifecycleOwner,
-        cameraSelector: CameraSelector,
+        primaryCameraSelector: CameraSelector,
+        secondaryCameraSelector: CameraSelector?,
+        primaryLayoutSettings: LayoutSettings,
+        secondaryLayoutSettings: LayoutSettings,
         viewPort: ViewPort?,
         effects: List<CameraEffect?>,
         vararg useCases: UseCase?
-    ): Camera {
-        Threads.checkMainThread()
-        // TODO(b/153096869): override UseCase's target rotation.
+    ): Camera =
+        trace("CX:bindToLifecycle-internal") {
+            Threads.checkMainThread()
+            // TODO(b/153096869): override UseCase's target rotation.
 
-        // Get the LifecycleCamera if existed.
-        val cameraInternal = cameraSelector.select(mCameraX!!.cameraRepository.cameras)
-        val restrictedCameraInfo = getCameraInfo(cameraSelector) as RestrictedCameraInfo
+            // Get the LifecycleCamera if existed.
+            val primaryCameraInternal =
+                primaryCameraSelector.select(mCameraX!!.cameraRepository.cameras)
+            primaryCameraInternal.setPrimary(true)
+            val primaryRestrictedCameraInfo =
+                getCameraInfo(primaryCameraSelector) as RestrictedCameraInfo
 
-        var lifecycleCameraToBind =
-            mLifecycleCameraRepository.getLifecycleCamera(
-                lifecycleOwner,
-                CameraUseCaseAdapter.generateCameraId(restrictedCameraInfo)
-            )
-
-        // Check if there's another camera that has already been bound.
-        val lifecycleCameras = mLifecycleCameraRepository.lifecycleCameras
-        useCases.filterNotNull().forEach { useCase ->
-            for (lifecycleCamera: LifecycleCamera in lifecycleCameras) {
-                if (lifecycleCamera.isBound(useCase) && lifecycleCamera != lifecycleCameraToBind) {
-                    throw IllegalStateException(
-                        String.format(
-                            "Use case %s already bound to a different lifecycle.",
-                            useCase
-                        )
-                    )
-                }
+            var secondaryCameraInternal: CameraInternal? = null
+            var secondaryRestrictedCameraInfo: RestrictedCameraInfo? = null
+            if (secondaryCameraSelector != null) {
+                secondaryCameraInternal =
+                    secondaryCameraSelector.select(mCameraX!!.cameraRepository.cameras)
+                secondaryCameraInternal.setPrimary(false)
+                secondaryRestrictedCameraInfo =
+                    getCameraInfo(secondaryCameraSelector) as RestrictedCameraInfo
             }
-        }
 
-        // Create the LifecycleCamera if there's no existing one that can be used.
-        if (lifecycleCameraToBind == null) {
-            lifecycleCameraToBind =
-                mLifecycleCameraRepository.createLifecycleCamera(
+            var lifecycleCameraToBind =
+                mLifecycleCameraRepository.getLifecycleCamera(
                     lifecycleOwner,
-                    CameraUseCaseAdapter(
-                        cameraInternal,
-                        restrictedCameraInfo,
-                        mCameraX!!.cameraFactory.cameraCoordinator,
-                        mCameraX!!.cameraDeviceSurfaceManager,
-                        mCameraX!!.defaultConfigFactory
+                    CameraUseCaseAdapter.generateCameraId(
+                        primaryRestrictedCameraInfo,
+                        secondaryRestrictedCameraInfo
                     )
                 )
+
+            // Check if there's another camera that has already been bound.
+            val lifecycleCameras = mLifecycleCameraRepository.lifecycleCameras
+            useCases.filterNotNull().forEach { useCase ->
+                for (lifecycleCamera: LifecycleCamera in lifecycleCameras) {
+                    if (
+                        lifecycleCamera.isBound(useCase) && lifecycleCamera != lifecycleCameraToBind
+                    ) {
+                        throw IllegalStateException(
+                            String.format(
+                                "Use case %s already bound to a different lifecycle.",
+                                useCase
+                            )
+                        )
+                    }
+                }
+            }
+
+            // Create the LifecycleCamera if there's no existing one that can be used.
+            if (lifecycleCameraToBind == null) {
+                lifecycleCameraToBind =
+                    mLifecycleCameraRepository.createLifecycleCamera(
+                        lifecycleOwner,
+                        CameraUseCaseAdapter(
+                            primaryCameraInternal,
+                            secondaryCameraInternal,
+                            primaryRestrictedCameraInfo,
+                            secondaryRestrictedCameraInfo,
+                            primaryLayoutSettings,
+                            secondaryLayoutSettings,
+                            mCameraX!!.cameraFactory.cameraCoordinator,
+                            mCameraX!!.cameraDeviceSurfaceManager,
+                            mCameraX!!.defaultConfigFactory
+                        )
+                    )
+            }
+
+            if (useCases.isEmpty()) {
+                return@trace lifecycleCameraToBind!!
+            }
+
+            mLifecycleCameraRepository.bindToLifecycleCamera(
+                lifecycleCameraToBind!!,
+                viewPort,
+                effects,
+                listOf(*useCases),
+                mCameraX!!.cameraFactory.cameraCoordinator
+            )
+
+            return@trace lifecycleCameraToBind
         }
 
-        if (useCases.isEmpty()) {
-            return lifecycleCameraToBind!!
-        }
-
-        mLifecycleCameraRepository.bindToLifecycleCamera(
-            lifecycleCameraToBind!!,
-            viewPort,
-            effects,
-            listOf(*useCases),
-            mCameraX!!.cameraFactory.cameraCoordinator
-        )
-
-        return lifecycleCameraToBind
-    }
-
     override fun isBound(useCase: UseCase): Boolean {
         for (lifecycleCamera: LifecycleCamera in mLifecycleCameraRepository.lifecycleCameras) {
             if (lifecycleCamera.isBound(useCase)) {
@@ -563,35 +661,38 @@
      * @throws UnsupportedOperationException If called in concurrent mode.
      */
     @MainThread
-    override fun unbind(vararg useCases: UseCase?) {
-        Threads.checkMainThread()
+    override fun unbind(vararg useCases: UseCase?) =
+        trace("CX:unbind") {
+            Threads.checkMainThread()
 
-        if (cameraOperatingMode == CAMERA_OPERATING_MODE_CONCURRENT) {
-            throw UnsupportedOperationException(
-                "Unbind usecase is not supported in concurrent camera mode, call unbindAll() first."
-            )
+            if (cameraOperatingMode == CAMERA_OPERATING_MODE_CONCURRENT) {
+                throw UnsupportedOperationException(
+                    "Unbind usecase is not supported in concurrent camera mode, call unbindAll() first."
+                )
+            }
+
+            mLifecycleCameraRepository.unbind(listOf(*useCases))
         }
 
-        mLifecycleCameraRepository.unbind(listOf(*useCases))
-    }
-
     @MainThread
-    override fun unbindAll() {
-        Threads.checkMainThread()
-        cameraOperatingMode = CAMERA_OPERATING_MODE_UNSPECIFIED
-        mLifecycleCameraRepository.unbindAll()
-    }
-
-    @Throws(CameraInfoUnavailableException::class)
-    override fun hasCamera(cameraSelector: CameraSelector): Boolean {
-        try {
-            cameraSelector.select(mCameraX!!.cameraRepository.cameras)
-        } catch (e: IllegalArgumentException) {
-            return false
+    override fun unbindAll() =
+        trace("CX:unbindAll") {
+            Threads.checkMainThread()
+            cameraOperatingMode = CAMERA_OPERATING_MODE_UNSPECIFIED
+            mLifecycleCameraRepository.unbindAll()
         }
 
-        return true
-    }
+    @Throws(CameraInfoUnavailableException::class)
+    override fun hasCamera(cameraSelector: CameraSelector): Boolean =
+        trace("CX:hasCamera") {
+            try {
+                cameraSelector.select(mCameraX!!.cameraRepository.cameras)
+            } catch (e: IllegalArgumentException) {
+                return@trace false
+            }
+
+            return@trace true
+        }
 
     /**
      * Returns [CameraInfo] instances of the available cameras.
@@ -606,14 +707,15 @@
      *
      * @return A list of [CameraInfo] instances for the available cameras.
      */
-    override fun getAvailableCameraInfos(): List<CameraInfo> {
-        val availableCameraInfos: MutableList<CameraInfo> = ArrayList()
-        val cameras: Set<CameraInternal> = mCameraX!!.cameraRepository.cameras
-        for (camera: CameraInternal in cameras) {
-            availableCameraInfos.add(camera.cameraInfo)
+    override fun getAvailableCameraInfos(): List<CameraInfo> =
+        trace("CX:getAvailableCameraInfos") {
+            val availableCameraInfos: MutableList<CameraInfo> = ArrayList()
+            val cameras: Set<CameraInternal> = mCameraX!!.cameraRepository.cameras
+            for (camera: CameraInternal in cameras) {
+                availableCameraInfos.add(camera.cameraInfo)
+            }
+            return@trace availableCameraInfos
         }
-        return availableCameraInfos
-    }
 
     val availableConcurrentCameraInfos: List<List<CameraInfo>>
         /**
@@ -630,51 +732,53 @@
          * @return List of combinations of [CameraInfo].
          */
         @OptIn(ExperimentalCameraInfo::class)
-        get() {
-            requireNonNull(mCameraX)
-            requireNonNull(mCameraX!!.cameraFactory.cameraCoordinator)
-            val concurrentCameraSelectorLists =
-                mCameraX!!.cameraFactory.cameraCoordinator.concurrentCameraSelectors
+        get() =
+            trace("CX:getAvailableConcurrentCameraInfos") {
+                requireNonNull(mCameraX)
+                requireNonNull(mCameraX!!.cameraFactory.cameraCoordinator)
+                val concurrentCameraSelectorLists =
+                    mCameraX!!.cameraFactory.cameraCoordinator.concurrentCameraSelectors
 
-            val availableConcurrentCameraInfos: MutableList<List<CameraInfo>> = ArrayList()
-            for (cameraSelectors in concurrentCameraSelectorLists) {
-                val cameraInfos: MutableList<CameraInfo> = ArrayList()
-                for (cameraSelector in cameraSelectors) {
-                    var cameraInfo: CameraInfo
-                    try {
-                        cameraInfo = getCameraInfo(cameraSelector)
-                    } catch (e: IllegalArgumentException) {
-                        continue
+                val availableConcurrentCameraInfos: MutableList<List<CameraInfo>> = ArrayList()
+                for (cameraSelectors in concurrentCameraSelectorLists) {
+                    val cameraInfos: MutableList<CameraInfo> = ArrayList()
+                    for (cameraSelector in cameraSelectors) {
+                        var cameraInfo: CameraInfo
+                        try {
+                            cameraInfo = getCameraInfo(cameraSelector)
+                        } catch (e: IllegalArgumentException) {
+                            continue
+                        }
+                        cameraInfos.add(cameraInfo)
                     }
-                    cameraInfos.add(cameraInfo)
+                    availableConcurrentCameraInfos.add(cameraInfos)
                 }
-                availableConcurrentCameraInfos.add(cameraInfos)
+                return@trace availableConcurrentCameraInfos
             }
-            return availableConcurrentCameraInfos
-        }
 
     @ExperimentalCameraInfo
-    override fun getCameraInfo(cameraSelector: CameraSelector): CameraInfo {
-        val cameraInfoInternal =
-            cameraSelector.select(mCameraX!!.cameraRepository.cameras).cameraInfoInternal
-        val cameraConfig = getCameraConfig(cameraSelector, cameraInfoInternal)
+    override fun getCameraInfo(cameraSelector: CameraSelector): CameraInfo =
+        trace("CX:getCameraInfo") {
+            val cameraInfoInternal =
+                cameraSelector.select(mCameraX!!.cameraRepository.cameras).cameraInfoInternal
+            val cameraConfig = getCameraConfig(cameraSelector, cameraInfoInternal)
 
-        val key =
-            CameraUseCaseAdapter.CameraId.create(
-                cameraInfoInternal.cameraId,
-                cameraConfig.compatibilityId
-            )
-        var restrictedCameraInfo: RestrictedCameraInfo?
-        synchronized(mLock) {
-            restrictedCameraInfo = mCameraInfoMap[key]
-            if (restrictedCameraInfo == null) {
-                restrictedCameraInfo = RestrictedCameraInfo(cameraInfoInternal, cameraConfig)
-                mCameraInfoMap[key] = restrictedCameraInfo!!
+            val key =
+                CameraUseCaseAdapter.CameraId.create(
+                    cameraInfoInternal.cameraId,
+                    cameraConfig.compatibilityId
+                )
+            var restrictedCameraInfo: RestrictedCameraInfo?
+            synchronized(mLock) {
+                restrictedCameraInfo = mCameraInfoMap[key]
+                if (restrictedCameraInfo == null) {
+                    restrictedCameraInfo = RestrictedCameraInfo(cameraInfoInternal, cameraConfig)
+                    mCameraInfoMap[key] = restrictedCameraInfo!!
+                }
             }
-        }
 
-        return restrictedCameraInfo!!
-    }
+            return@trace restrictedCameraInfo!!
+        }
 
     val isConcurrentCameraModeOn: Boolean
         /**
@@ -722,17 +826,18 @@
         }
     }
 
-    private fun configureInstanceInternal(cameraXConfig: CameraXConfig) {
-        synchronized(mLock) {
-            Preconditions.checkNotNull(cameraXConfig)
-            Preconditions.checkState(
-                mCameraXConfigProvider == null,
-                "CameraX has already been configured. To use a different configuration, " +
-                    "shutdown() must be called."
-            )
-            mCameraXConfigProvider = CameraXConfig.Provider { cameraXConfig }
+    private fun configureInstanceInternal(cameraXConfig: CameraXConfig) =
+        trace("CX:configureInstanceInternal") {
+            synchronized(mLock) {
+                Preconditions.checkNotNull(cameraXConfig)
+                Preconditions.checkState(
+                    mCameraXConfigProvider == null,
+                    "CameraX has already been configured. To use a different configuration, " +
+                        "shutdown() must be called."
+                )
+                mCameraXConfigProvider = CameraXConfig.Provider { cameraXConfig }
+            }
         }
-    }
 
     private fun getCameraConfig(
         cameraSelector: CameraSelector,
@@ -883,8 +988,7 @@
          */
         @JvmStatic
         @ExperimentalCameraProviderConfiguration
-        fun configureInstance(cameraXConfig: CameraXConfig) {
-            sAppInstance.configureInstanceInternal(cameraXConfig)
-        }
+        fun configureInstance(cameraXConfig: CameraXConfig) =
+            trace("CX:configureInstance") { sAppInstance.configureInstanceInternal(cameraXConfig) }
     }
 }
diff --git a/camera/camera-mlkit-vision/api/1.4.0-beta03.txt b/camera/camera-mlkit-vision/api/1.4.0-beta03.txt
new file mode 100644
index 0000000..0cfc1f5
--- /dev/null
+++ b/camera/camera-mlkit-vision/api/1.4.0-beta03.txt
@@ -0,0 +1,20 @@
+// Signature format: 4.0
+package androidx.camera.mlkit.vision {
+
+  public class MlKitAnalyzer implements androidx.camera.core.ImageAnalysis.Analyzer {
+    ctor public MlKitAnalyzer(java.util.List<com.google.mlkit.vision.interfaces.Detector<? extends java.lang.Object!>!>, int, java.util.concurrent.Executor, androidx.core.util.Consumer<androidx.camera.mlkit.vision.MlKitAnalyzer.Result!>);
+    method public final void analyze(androidx.camera.core.ImageProxy);
+    method public final android.util.Size getDefaultTargetResolution();
+    method public final int getTargetCoordinateSystem();
+    method public final void updateTransform(android.graphics.Matrix?);
+  }
+
+  public static final class MlKitAnalyzer.Result {
+    ctor public MlKitAnalyzer.Result(java.util.Map<com.google.mlkit.vision.interfaces.Detector<? extends java.lang.Object!>!,java.lang.Object!>, long, java.util.Map<com.google.mlkit.vision.interfaces.Detector<? extends java.lang.Object!>!,java.lang.Throwable!>);
+    method public Throwable? getThrowable(com.google.mlkit.vision.interfaces.Detector<? extends java.lang.Object!>);
+    method public long getTimestamp();
+    method public <T> T? getValue(com.google.mlkit.vision.interfaces.Detector<T!>);
+  }
+
+}
+
diff --git a/camera/camera-mlkit-vision/api/res-1.4.0-beta03.txt b/camera/camera-mlkit-vision/api/res-1.4.0-beta03.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/camera/camera-mlkit-vision/api/res-1.4.0-beta03.txt
diff --git a/camera/camera-mlkit-vision/api/restricted_1.4.0-beta03.txt b/camera/camera-mlkit-vision/api/restricted_1.4.0-beta03.txt
new file mode 100644
index 0000000..0cfc1f5
--- /dev/null
+++ b/camera/camera-mlkit-vision/api/restricted_1.4.0-beta03.txt
@@ -0,0 +1,20 @@
+// Signature format: 4.0
+package androidx.camera.mlkit.vision {
+
+  public class MlKitAnalyzer implements androidx.camera.core.ImageAnalysis.Analyzer {
+    ctor public MlKitAnalyzer(java.util.List<com.google.mlkit.vision.interfaces.Detector<? extends java.lang.Object!>!>, int, java.util.concurrent.Executor, androidx.core.util.Consumer<androidx.camera.mlkit.vision.MlKitAnalyzer.Result!>);
+    method public final void analyze(androidx.camera.core.ImageProxy);
+    method public final android.util.Size getDefaultTargetResolution();
+    method public final int getTargetCoordinateSystem();
+    method public final void updateTransform(android.graphics.Matrix?);
+  }
+
+  public static final class MlKitAnalyzer.Result {
+    ctor public MlKitAnalyzer.Result(java.util.Map<com.google.mlkit.vision.interfaces.Detector<? extends java.lang.Object!>!,java.lang.Object!>, long, java.util.Map<com.google.mlkit.vision.interfaces.Detector<? extends java.lang.Object!>!,java.lang.Throwable!>);
+    method public Throwable? getThrowable(com.google.mlkit.vision.interfaces.Detector<? extends java.lang.Object!>);
+    method public long getTimestamp();
+    method public <T> T? getValue(com.google.mlkit.vision.interfaces.Detector<T!>);
+  }
+
+}
+
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCamera.java b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCamera.java
index 0a31448..8c8c3c4 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCamera.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCamera.java
@@ -78,6 +78,7 @@
     private final List<UseCase> mUseCaseUpdateHistory = new ArrayList<>();
     private final List<UseCase> mUseCaseResetHistory = new ArrayList<>();
     private boolean mHasTransform = true;
+    private boolean mIsPrimary = true;
 
     @Nullable
     private SessionConfig mSessionConfig;
@@ -382,6 +383,17 @@
         mHasTransform = hasCameraTransform;
     }
 
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    @Override
+    public void setPrimary(boolean isPrimary) {
+        mIsPrimary = isPrimary;
+    }
+
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public boolean isPrimary() {
+        return mIsPrimary;
+    }
+
     private void checkNotReleased() {
         if (isReleased()) {
             throw new IllegalStateException("Camera has been released.");
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/impl/CameraUtil.java b/camera/camera-testing/src/main/java/androidx/camera/testing/impl/CameraUtil.java
index 264f238..c7302a3 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/impl/CameraUtil.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/impl/CameraUtil.java
@@ -55,6 +55,7 @@
 import androidx.camera.core.CameraX;
 import androidx.camera.core.CameraXConfig;
 import androidx.camera.core.ExperimentalRetryPolicy;
+import androidx.camera.core.LayoutSettings;
 import androidx.camera.core.Logger;
 import androidx.camera.core.RetryPolicy;
 import androidx.camera.core.UseCase;
@@ -631,7 +632,11 @@
             CameraInternal camera =
                     cameraSelector.select(cameraX.getCameraRepository().getCameras());
             return new CameraUseCaseAdapter(camera,
+                    null,
                     new RestrictedCameraInfo(camera.getCameraInfoInternal(), cameraConfig),
+                    null,
+                    LayoutSettings.DEFAULT,
+                    LayoutSettings.DEFAULT,
                     cameraCoordinator,
                     cameraX.getCameraDeviceSurfaceManager(),
                     cameraX.getDefaultConfigFactory());
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/impl/FileUtil.kt b/camera/camera-testing/src/main/java/androidx/camera/testing/impl/FileUtil.kt
index c99c69f..47c04e7 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/impl/FileUtil.kt
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/impl/FileUtil.kt
@@ -70,7 +70,7 @@
                 fos.close()
             }
         }
-        Logger.d(TAG, "Export test information to: ${file.path}")
+        Logger.d(TAG, "Wrote [$text] to: ${file.path}")
     }
 
     /**
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/impl/fakes/FakeCameraDeviceSurfaceManager.java b/camera/camera-testing/src/main/java/androidx/camera/testing/impl/fakes/FakeCameraDeviceSurfaceManager.java
index 38a8444..be77670 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/impl/fakes/FakeCameraDeviceSurfaceManager.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/impl/fakes/FakeCameraDeviceSurfaceManager.java
@@ -31,9 +31,15 @@
 import androidx.camera.core.impl.AttachedSurfaceInfo;
 import androidx.camera.core.impl.CameraDeviceSurfaceManager;
 import androidx.camera.core.impl.CameraMode;
+import androidx.camera.core.impl.ImageAnalysisConfig;
+import androidx.camera.core.impl.ImageCaptureConfig;
+import androidx.camera.core.impl.PreviewConfig;
 import androidx.camera.core.impl.StreamSpec;
 import androidx.camera.core.impl.SurfaceConfig;
 import androidx.camera.core.impl.UseCaseConfig;
+import androidx.camera.core.impl.UseCaseConfigFactory;
+import androidx.camera.core.streamsharing.StreamSharingConfig;
+import androidx.camera.video.impl.VideoCaptureConfig;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -89,26 +95,69 @@
             @NonNull String cameraId,
             @NonNull List<AttachedSurfaceInfo> existingSurfaces,
             @NonNull Map<UseCaseConfig<?>, List<Size>> newUseCaseConfigsSupportedSizeMap,
-            boolean isPreviewStabilizationOn) {
+            boolean isPreviewStabilizationOn,
+            boolean hasVideoCapture) {
         List<UseCaseConfig<?>> newUseCaseConfigs =
                 new ArrayList<>(newUseCaseConfigsSupportedSizeMap.keySet());
         checkSurfaceCombo(existingSurfaces, newUseCaseConfigs);
+
+        // Populate the suggested stream specs for new use cases.
         Map<UseCaseConfig<?>, StreamSpec> suggestedStreamSpecs = new HashMap<>();
         for (UseCaseConfig<?> useCaseConfig : newUseCaseConfigs) {
-            StreamSpec streamSpec = StreamSpec.builder(MAX_OUTPUT_SIZE).build();
-            Map<Class<? extends UseCaseConfig<?>>, StreamSpec> definedStreamSpecs =
-                    mDefinedStreamSpecs.get(cameraId);
-            if (definedStreamSpecs != null) {
-                StreamSpec definedStreamSpec = definedStreamSpecs.get(useCaseConfig.getClass());
-                if (definedStreamSpec != null) {
-                    streamSpec = definedStreamSpec;
-                }
-            }
-
-            suggestedStreamSpecs.put(useCaseConfig, streamSpec);
+            suggestedStreamSpecs.put(useCaseConfig,
+                    getStreamSpec(cameraId, useCaseConfig.getClass(), hasVideoCapture));
         }
 
-        return new Pair<>(suggestedStreamSpecs, new HashMap<>());
+        // Populate the stream specs for existing use cases.
+        Map<AttachedSurfaceInfo, StreamSpec> existingStreamSpecs = new HashMap<>();
+        for (AttachedSurfaceInfo attachedSurfaceInfo : existingSurfaces) {
+            existingStreamSpecs.put(attachedSurfaceInfo, getStreamSpec(cameraId,
+                    captureTypeToUseCaseConfigType(attachedSurfaceInfo.getCaptureTypes().get(0)),
+                    hasVideoCapture));
+        }
+
+        return new Pair<>(suggestedStreamSpecs, existingStreamSpecs);
+    }
+
+    @NonNull
+    private StreamSpec getStreamSpec(@NonNull String cameraId, @NonNull Class<?> classType,
+            boolean hasVideoCapture) {
+        StreamSpec streamSpec = StreamSpec.builder(MAX_OUTPUT_SIZE)
+                .setZslDisabled(hasVideoCapture)
+                .build();
+        Map<Class<? extends UseCaseConfig<?>>, StreamSpec> definedStreamSpecs =
+                mDefinedStreamSpecs.get(cameraId);
+        if (definedStreamSpecs != null) {
+            StreamSpec definedStreamSpec = definedStreamSpecs.get(classType);
+            if (definedStreamSpec != null) {
+                streamSpec = definedStreamSpec;
+            }
+        }
+        return streamSpec;
+    }
+
+    /**
+     * Returns the {@link UseCaseConfig} type from a
+     * {@link androidx.camera.core.impl.UseCaseConfigFactory.CaptureType}.
+     */
+    private Class<?> captureTypeToUseCaseConfigType(
+            @NonNull UseCaseConfigFactory.CaptureType captureType) {
+        switch (captureType) {
+            case METERING_REPEATING:
+                // Fall-through
+            case PREVIEW:
+                return PreviewConfig.class;
+            case IMAGE_CAPTURE:
+                return ImageCaptureConfig.class;
+            case IMAGE_ANALYSIS:
+                return ImageAnalysisConfig.class;
+            case VIDEO_CAPTURE:
+                return VideoCaptureConfig.class;
+            case STREAM_SHARING:
+                return StreamSharingConfig.class;
+            default:
+                throw new IllegalArgumentException("Invalid capture type.");
+        }
     }
 
     /**
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/impl/fakes/FakeUseCase.java b/camera/camera-testing/src/main/java/androidx/camera/testing/impl/fakes/FakeUseCase.java
index 2d1ba6a..45ccb92 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/impl/fakes/FakeUseCase.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/impl/fakes/FakeUseCase.java
@@ -32,6 +32,7 @@
 import androidx.core.util.Supplier;
 
 import java.util.Collections;
+import java.util.List;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -132,12 +133,14 @@
 
     @Override
     @NonNull
-    protected StreamSpec onSuggestedStreamSpecUpdated(@NonNull StreamSpec suggestedStreamSpec) {
+    protected StreamSpec onSuggestedStreamSpecUpdated(
+            @NonNull StreamSpec primaryStreamSpec,
+            @Nullable StreamSpec secondaryStreamSpec) {
         SessionConfig sessionConfig = createPipeline();
         if (sessionConfig != null) {
-            updateSessionConfig(sessionConfig);
+            updateSessionConfig(List.of(sessionConfig));
         }
-        return suggestedStreamSpec;
+        return primaryStreamSpec;
     }
 
     @Nullable
@@ -206,7 +209,7 @@
      * Calls the protected method {@link UseCase#updateSessionConfig}.
      */
     public void updateSessionConfigForTesting(@NonNull SessionConfig sessionConfig) {
-        updateSessionConfig(sessionConfig);
+        updateSessionConfig(List.of(sessionConfig));
     }
 
     /**
diff --git a/camera/camera-testing/src/test/java/androidx/camera/testing/fakes/FakeCameraDeviceSurfaceManagerTest.java b/camera/camera-testing/src/test/java/androidx/camera/testing/fakes/FakeCameraDeviceSurfaceManagerTest.java
index 1ac4332..b1c0695 100644
--- a/camera/camera-testing/src/test/java/androidx/camera/testing/fakes/FakeCameraDeviceSurfaceManagerTest.java
+++ b/camera/camera-testing/src/test/java/androidx/camera/testing/fakes/FakeCameraDeviceSurfaceManagerTest.java
@@ -17,9 +17,12 @@
 package androidx.camera.testing.fakes;
 
 import static android.graphics.ImageFormat.YUV_420_888;
+
 import static androidx.camera.core.impl.SurfaceConfig.ConfigSize.PREVIEW;
 import static androidx.camera.core.impl.SurfaceConfig.ConfigType.YUV;
+
 import static com.google.common.truth.Truth.assertThat;
+
 import static java.util.Collections.emptyList;
 import static java.util.Collections.singletonList;
 
@@ -94,6 +97,7 @@
                 FAKE_CAMERA_ID0,
                 emptyList(),
                 createConfigOutputSizesMap(preview, analysis),
+                false,
                 false);
     }
 
@@ -113,6 +117,7 @@
                 CameraMode.DEFAULT,
                 FAKE_CAMERA_ID0,
                 singletonList(analysis), createConfigOutputSizesMap(preview, video),
+                false,
                 false);
     }
 
@@ -125,6 +130,7 @@
                 CameraMode.DEFAULT,
                 FAKE_CAMERA_ID0,
                 Collections.emptyList(), createConfigOutputSizesMap(preview, video, analysis),
+                false,
                 false);
     }
 
@@ -135,12 +141,14 @@
                         CameraMode.DEFAULT,
                         FAKE_CAMERA_ID0,
                         emptyList(), createConfigOutputSizesMap(mFakeUseCaseConfig),
+                        false,
                         false).first;
         Map<UseCaseConfig<?>, StreamSpec> suggestedStreamSpecCamera1 =
                 mFakeCameraDeviceSurfaceManager.getSuggestedStreamSpecs(
                         CameraMode.DEFAULT,
                         FAKE_CAMERA_ID1,
                         emptyList(), createConfigOutputSizesMap(mFakeUseCaseConfig),
+                        false,
                         false).first;
 
         assertThat(suggestedStreamSpecsCamera0.get(mFakeUseCaseConfig)).isEqualTo(
diff --git a/camera/camera-video/api/1.4.0-beta03.txt b/camera/camera-video/api/1.4.0-beta03.txt
new file mode 100644
index 0000000..beba6c4
--- /dev/null
+++ b/camera/camera-video/api/1.4.0-beta03.txt
@@ -0,0 +1,220 @@
+// Signature format: 4.0
+package androidx.camera.video {
+
+  @com.google.auto.value.AutoValue public abstract class AudioStats {
+    method public double getAudioAmplitude();
+    method public abstract int getAudioState();
+    method public abstract Throwable? getErrorCause();
+    method public boolean hasAudio();
+    method public boolean hasError();
+    field public static final double AUDIO_AMPLITUDE_NONE = 0.0;
+    field public static final int AUDIO_STATE_ACTIVE = 0; // 0x0
+    field public static final int AUDIO_STATE_DISABLED = 1; // 0x1
+    field public static final int AUDIO_STATE_ENCODER_ERROR = 3; // 0x3
+    field public static final int AUDIO_STATE_MUTED = 5; // 0x5
+    field public static final int AUDIO_STATE_SOURCE_ERROR = 4; // 0x4
+    field public static final int AUDIO_STATE_SOURCE_SILENCED = 2; // 0x2
+  }
+
+  @SuppressCompatibility @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface ExperimentalAudioApi {
+  }
+
+  @SuppressCompatibility @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface ExperimentalPersistentRecording {
+  }
+
+  public class FallbackStrategy {
+    method public static androidx.camera.video.FallbackStrategy higherQualityOrLowerThan(androidx.camera.video.Quality);
+    method public static androidx.camera.video.FallbackStrategy higherQualityThan(androidx.camera.video.Quality);
+    method public static androidx.camera.video.FallbackStrategy lowerQualityOrHigherThan(androidx.camera.video.Quality);
+    method public static androidx.camera.video.FallbackStrategy lowerQualityThan(androidx.camera.video.Quality);
+  }
+
+  public final class FileDescriptorOutputOptions extends androidx.camera.video.OutputOptions {
+    method public android.os.ParcelFileDescriptor getParcelFileDescriptor();
+  }
+
+  public static final class FileDescriptorOutputOptions.Builder {
+    ctor public FileDescriptorOutputOptions.Builder(android.os.ParcelFileDescriptor);
+    method public androidx.camera.video.FileDescriptorOutputOptions build();
+    method public androidx.camera.video.FileDescriptorOutputOptions.Builder setDurationLimitMillis(@IntRange(from=0) long);
+    method public androidx.camera.video.FileDescriptorOutputOptions.Builder setFileSizeLimit(@IntRange(from=0) long);
+    method public androidx.camera.video.FileDescriptorOutputOptions.Builder setLocation(android.location.Location?);
+  }
+
+  public final class FileOutputOptions extends androidx.camera.video.OutputOptions {
+    method public java.io.File getFile();
+  }
+
+  public static final class FileOutputOptions.Builder {
+    ctor public FileOutputOptions.Builder(java.io.File);
+    method public androidx.camera.video.FileOutputOptions build();
+    method public androidx.camera.video.FileOutputOptions.Builder setDurationLimitMillis(@IntRange(from=0) long);
+    method public androidx.camera.video.FileOutputOptions.Builder setFileSizeLimit(@IntRange(from=0) long);
+    method public androidx.camera.video.FileOutputOptions.Builder setLocation(android.location.Location?);
+  }
+
+  public final class MediaStoreOutputOptions extends androidx.camera.video.OutputOptions {
+    method public android.net.Uri getCollectionUri();
+    method public android.content.ContentResolver getContentResolver();
+    method public android.content.ContentValues getContentValues();
+    field public static final android.content.ContentValues EMPTY_CONTENT_VALUES;
+  }
+
+  public static final class MediaStoreOutputOptions.Builder {
+    ctor public MediaStoreOutputOptions.Builder(android.content.ContentResolver, android.net.Uri);
+    method public androidx.camera.video.MediaStoreOutputOptions build();
+    method public androidx.camera.video.MediaStoreOutputOptions.Builder setContentValues(android.content.ContentValues);
+    method public androidx.camera.video.MediaStoreOutputOptions.Builder setDurationLimitMillis(@IntRange(from=0) long);
+    method public androidx.camera.video.MediaStoreOutputOptions.Builder setFileSizeLimit(@IntRange(from=0) long);
+    method public androidx.camera.video.MediaStoreOutputOptions.Builder setLocation(android.location.Location?);
+  }
+
+  public abstract class OutputOptions {
+    method @IntRange(from=0) public long getDurationLimitMillis();
+    method @IntRange(from=0) public long getFileSizeLimit();
+    method public android.location.Location? getLocation();
+    field public static final int DURATION_UNLIMITED = 0; // 0x0
+    field public static final int FILE_SIZE_UNLIMITED = 0; // 0x0
+  }
+
+  @com.google.auto.value.AutoValue public abstract class OutputResults {
+    ctor public OutputResults();
+    method public abstract android.net.Uri getOutputUri();
+  }
+
+  public final class PendingRecording {
+    method @SuppressCompatibility @androidx.camera.video.ExperimentalPersistentRecording public androidx.camera.video.PendingRecording asPersistentRecording();
+    method @CheckResult public androidx.camera.video.Recording start(java.util.concurrent.Executor, androidx.core.util.Consumer<androidx.camera.video.VideoRecordEvent!>);
+    method @RequiresPermission(android.Manifest.permission.RECORD_AUDIO) public androidx.camera.video.PendingRecording withAudioEnabled();
+  }
+
+  public class Quality {
+    field public static final androidx.camera.video.Quality FHD;
+    field public static final androidx.camera.video.Quality HD;
+    field public static final androidx.camera.video.Quality HIGHEST;
+    field public static final androidx.camera.video.Quality LOWEST;
+    field public static final androidx.camera.video.Quality SD;
+    field public static final androidx.camera.video.Quality UHD;
+  }
+
+  public final class QualitySelector {
+    method public static androidx.camera.video.QualitySelector from(androidx.camera.video.Quality);
+    method public static androidx.camera.video.QualitySelector from(androidx.camera.video.Quality, androidx.camera.video.FallbackStrategy);
+    method public static androidx.camera.video.QualitySelector fromOrderedList(java.util.List<androidx.camera.video.Quality!>);
+    method public static androidx.camera.video.QualitySelector fromOrderedList(java.util.List<androidx.camera.video.Quality!>, androidx.camera.video.FallbackStrategy);
+    method public static android.util.Size? getResolution(androidx.camera.core.CameraInfo, androidx.camera.video.Quality);
+    method @Deprecated public static java.util.List<androidx.camera.video.Quality!> getSupportedQualities(androidx.camera.core.CameraInfo);
+    method @Deprecated public static boolean isQualitySupported(androidx.camera.core.CameraInfo, androidx.camera.video.Quality);
+  }
+
+  public final class Recorder implements androidx.camera.video.VideoOutput {
+    method public int getAspectRatio();
+    method public java.util.concurrent.Executor? getExecutor();
+    method public androidx.camera.video.QualitySelector getQualitySelector();
+    method public int getTargetVideoEncodingBitRate();
+    method public static androidx.camera.video.VideoCapabilities getVideoCapabilities(androidx.camera.core.CameraInfo);
+    method public static androidx.camera.video.VideoCapabilities getVideoCapabilities(androidx.camera.core.CameraInfo, int);
+    method public int getVideoCapabilitiesSource();
+    method public void onSurfaceRequested(androidx.camera.core.SurfaceRequest);
+    method @RequiresApi(26) public androidx.camera.video.PendingRecording prepareRecording(android.content.Context, androidx.camera.video.FileDescriptorOutputOptions);
+    method public androidx.camera.video.PendingRecording prepareRecording(android.content.Context, androidx.camera.video.FileOutputOptions);
+    method public androidx.camera.video.PendingRecording prepareRecording(android.content.Context, androidx.camera.video.MediaStoreOutputOptions);
+    field public static final androidx.camera.video.QualitySelector DEFAULT_QUALITY_SELECTOR;
+    field public static final int VIDEO_CAPABILITIES_SOURCE_CAMCORDER_PROFILE = 0; // 0x0
+    field public static final int VIDEO_CAPABILITIES_SOURCE_CODEC_CAPABILITIES = 1; // 0x1
+  }
+
+  public static final class Recorder.Builder {
+    ctor public Recorder.Builder();
+    method public androidx.camera.video.Recorder build();
+    method public androidx.camera.video.Recorder.Builder setAspectRatio(int);
+    method public androidx.camera.video.Recorder.Builder setExecutor(java.util.concurrent.Executor);
+    method public androidx.camera.video.Recorder.Builder setQualitySelector(androidx.camera.video.QualitySelector);
+    method public androidx.camera.video.Recorder.Builder setTargetVideoEncodingBitRate(@IntRange(from=1) int);
+    method public androidx.camera.video.Recorder.Builder setVideoCapabilitiesSource(int);
+  }
+
+  public final class Recording implements java.lang.AutoCloseable {
+    method public void close();
+    method @SuppressCompatibility @androidx.camera.video.ExperimentalPersistentRecording public boolean isPersistent();
+    method public void mute(boolean);
+    method public void pause();
+    method public void resume();
+    method public void stop();
+  }
+
+  @com.google.auto.value.AutoValue public abstract class RecordingStats {
+    method public abstract androidx.camera.video.AudioStats getAudioStats();
+    method public abstract long getNumBytesRecorded();
+    method public abstract long getRecordedDurationNanos();
+  }
+
+  public interface VideoCapabilities {
+    method public java.util.Set<androidx.camera.core.DynamicRange!> getSupportedDynamicRanges();
+    method public java.util.List<androidx.camera.video.Quality!> getSupportedQualities(androidx.camera.core.DynamicRange);
+    method public boolean isQualitySupported(androidx.camera.video.Quality, androidx.camera.core.DynamicRange);
+    method public default boolean isStabilizationSupported();
+  }
+
+  public final class VideoCapture<T extends androidx.camera.video.VideoOutput> extends androidx.camera.core.UseCase {
+    method public androidx.camera.core.DynamicRange getDynamicRange();
+    method public int getMirrorMode();
+    method public T getOutput();
+    method public android.util.Range<java.lang.Integer!> getTargetFrameRate();
+    method public int getTargetRotation();
+    method public boolean isVideoStabilizationEnabled();
+    method public void setTargetRotation(int);
+    method public static <T extends androidx.camera.video.VideoOutput> androidx.camera.video.VideoCapture<T!> withOutput(T);
+  }
+
+  public static final class VideoCapture.Builder<T extends androidx.camera.video.VideoOutput> implements androidx.camera.core.ExtendableBuilder<androidx.camera.video.VideoCapture!> {
+    ctor public VideoCapture.Builder(T);
+    method public androidx.camera.video.VideoCapture<T!> build();
+    method public androidx.camera.video.VideoCapture.Builder<T!> setDynamicRange(androidx.camera.core.DynamicRange);
+    method public androidx.camera.video.VideoCapture.Builder<T!> setMirrorMode(int);
+    method public androidx.camera.video.VideoCapture.Builder<T!> setTargetFrameRate(android.util.Range<java.lang.Integer!>);
+    method public androidx.camera.video.VideoCapture.Builder<T!> setTargetRotation(int);
+    method public androidx.camera.video.VideoCapture.Builder<T!> setVideoStabilizationEnabled(boolean);
+  }
+
+  public interface VideoOutput {
+    method public void onSurfaceRequested(androidx.camera.core.SurfaceRequest);
+  }
+
+  public abstract class VideoRecordEvent {
+    method public androidx.camera.video.OutputOptions getOutputOptions();
+    method public androidx.camera.video.RecordingStats getRecordingStats();
+  }
+
+  public static final class VideoRecordEvent.Finalize extends androidx.camera.video.VideoRecordEvent {
+    method public Throwable? getCause();
+    method public int getError();
+    method public androidx.camera.video.OutputResults getOutputResults();
+    method public boolean hasError();
+    field public static final int ERROR_DURATION_LIMIT_REACHED = 9; // 0x9
+    field public static final int ERROR_ENCODING_FAILED = 6; // 0x6
+    field public static final int ERROR_FILE_SIZE_LIMIT_REACHED = 2; // 0x2
+    field public static final int ERROR_INSUFFICIENT_STORAGE = 3; // 0x3
+    field public static final int ERROR_INVALID_OUTPUT_OPTIONS = 5; // 0x5
+    field public static final int ERROR_NONE = 0; // 0x0
+    field public static final int ERROR_NO_VALID_DATA = 8; // 0x8
+    field public static final int ERROR_RECORDER_ERROR = 7; // 0x7
+    field public static final int ERROR_RECORDING_GARBAGE_COLLECTED = 10; // 0xa
+    field public static final int ERROR_SOURCE_INACTIVE = 4; // 0x4
+    field public static final int ERROR_UNKNOWN = 1; // 0x1
+  }
+
+  public static final class VideoRecordEvent.Pause extends androidx.camera.video.VideoRecordEvent {
+  }
+
+  public static final class VideoRecordEvent.Resume extends androidx.camera.video.VideoRecordEvent {
+  }
+
+  public static final class VideoRecordEvent.Start extends androidx.camera.video.VideoRecordEvent {
+  }
+
+  public static final class VideoRecordEvent.Status extends androidx.camera.video.VideoRecordEvent {
+  }
+
+}
+
diff --git a/camera/camera-video/api/res-1.4.0-beta03.txt b/camera/camera-video/api/res-1.4.0-beta03.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/camera/camera-video/api/res-1.4.0-beta03.txt
diff --git a/camera/camera-video/api/restricted_1.4.0-beta03.txt b/camera/camera-video/api/restricted_1.4.0-beta03.txt
new file mode 100644
index 0000000..beba6c4
--- /dev/null
+++ b/camera/camera-video/api/restricted_1.4.0-beta03.txt
@@ -0,0 +1,220 @@
+// Signature format: 4.0
+package androidx.camera.video {
+
+  @com.google.auto.value.AutoValue public abstract class AudioStats {
+    method public double getAudioAmplitude();
+    method public abstract int getAudioState();
+    method public abstract Throwable? getErrorCause();
+    method public boolean hasAudio();
+    method public boolean hasError();
+    field public static final double AUDIO_AMPLITUDE_NONE = 0.0;
+    field public static final int AUDIO_STATE_ACTIVE = 0; // 0x0
+    field public static final int AUDIO_STATE_DISABLED = 1; // 0x1
+    field public static final int AUDIO_STATE_ENCODER_ERROR = 3; // 0x3
+    field public static final int AUDIO_STATE_MUTED = 5; // 0x5
+    field public static final int AUDIO_STATE_SOURCE_ERROR = 4; // 0x4
+    field public static final int AUDIO_STATE_SOURCE_SILENCED = 2; // 0x2
+  }
+
+  @SuppressCompatibility @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface ExperimentalAudioApi {
+  }
+
+  @SuppressCompatibility @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface ExperimentalPersistentRecording {
+  }
+
+  public class FallbackStrategy {
+    method public static androidx.camera.video.FallbackStrategy higherQualityOrLowerThan(androidx.camera.video.Quality);
+    method public static androidx.camera.video.FallbackStrategy higherQualityThan(androidx.camera.video.Quality);
+    method public static androidx.camera.video.FallbackStrategy lowerQualityOrHigherThan(androidx.camera.video.Quality);
+    method public static androidx.camera.video.FallbackStrategy lowerQualityThan(androidx.camera.video.Quality);
+  }
+
+  public final class FileDescriptorOutputOptions extends androidx.camera.video.OutputOptions {
+    method public android.os.ParcelFileDescriptor getParcelFileDescriptor();
+  }
+
+  public static final class FileDescriptorOutputOptions.Builder {
+    ctor public FileDescriptorOutputOptions.Builder(android.os.ParcelFileDescriptor);
+    method public androidx.camera.video.FileDescriptorOutputOptions build();
+    method public androidx.camera.video.FileDescriptorOutputOptions.Builder setDurationLimitMillis(@IntRange(from=0) long);
+    method public androidx.camera.video.FileDescriptorOutputOptions.Builder setFileSizeLimit(@IntRange(from=0) long);
+    method public androidx.camera.video.FileDescriptorOutputOptions.Builder setLocation(android.location.Location?);
+  }
+
+  public final class FileOutputOptions extends androidx.camera.video.OutputOptions {
+    method public java.io.File getFile();
+  }
+
+  public static final class FileOutputOptions.Builder {
+    ctor public FileOutputOptions.Builder(java.io.File);
+    method public androidx.camera.video.FileOutputOptions build();
+    method public androidx.camera.video.FileOutputOptions.Builder setDurationLimitMillis(@IntRange(from=0) long);
+    method public androidx.camera.video.FileOutputOptions.Builder setFileSizeLimit(@IntRange(from=0) long);
+    method public androidx.camera.video.FileOutputOptions.Builder setLocation(android.location.Location?);
+  }
+
+  public final class MediaStoreOutputOptions extends androidx.camera.video.OutputOptions {
+    method public android.net.Uri getCollectionUri();
+    method public android.content.ContentResolver getContentResolver();
+    method public android.content.ContentValues getContentValues();
+    field public static final android.content.ContentValues EMPTY_CONTENT_VALUES;
+  }
+
+  public static final class MediaStoreOutputOptions.Builder {
+    ctor public MediaStoreOutputOptions.Builder(android.content.ContentResolver, android.net.Uri);
+    method public androidx.camera.video.MediaStoreOutputOptions build();
+    method public androidx.camera.video.MediaStoreOutputOptions.Builder setContentValues(android.content.ContentValues);
+    method public androidx.camera.video.MediaStoreOutputOptions.Builder setDurationLimitMillis(@IntRange(from=0) long);
+    method public androidx.camera.video.MediaStoreOutputOptions.Builder setFileSizeLimit(@IntRange(from=0) long);
+    method public androidx.camera.video.MediaStoreOutputOptions.Builder setLocation(android.location.Location?);
+  }
+
+  public abstract class OutputOptions {
+    method @IntRange(from=0) public long getDurationLimitMillis();
+    method @IntRange(from=0) public long getFileSizeLimit();
+    method public android.location.Location? getLocation();
+    field public static final int DURATION_UNLIMITED = 0; // 0x0
+    field public static final int FILE_SIZE_UNLIMITED = 0; // 0x0
+  }
+
+  @com.google.auto.value.AutoValue public abstract class OutputResults {
+    ctor public OutputResults();
+    method public abstract android.net.Uri getOutputUri();
+  }
+
+  public final class PendingRecording {
+    method @SuppressCompatibility @androidx.camera.video.ExperimentalPersistentRecording public androidx.camera.video.PendingRecording asPersistentRecording();
+    method @CheckResult public androidx.camera.video.Recording start(java.util.concurrent.Executor, androidx.core.util.Consumer<androidx.camera.video.VideoRecordEvent!>);
+    method @RequiresPermission(android.Manifest.permission.RECORD_AUDIO) public androidx.camera.video.PendingRecording withAudioEnabled();
+  }
+
+  public class Quality {
+    field public static final androidx.camera.video.Quality FHD;
+    field public static final androidx.camera.video.Quality HD;
+    field public static final androidx.camera.video.Quality HIGHEST;
+    field public static final androidx.camera.video.Quality LOWEST;
+    field public static final androidx.camera.video.Quality SD;
+    field public static final androidx.camera.video.Quality UHD;
+  }
+
+  public final class QualitySelector {
+    method public static androidx.camera.video.QualitySelector from(androidx.camera.video.Quality);
+    method public static androidx.camera.video.QualitySelector from(androidx.camera.video.Quality, androidx.camera.video.FallbackStrategy);
+    method public static androidx.camera.video.QualitySelector fromOrderedList(java.util.List<androidx.camera.video.Quality!>);
+    method public static androidx.camera.video.QualitySelector fromOrderedList(java.util.List<androidx.camera.video.Quality!>, androidx.camera.video.FallbackStrategy);
+    method public static android.util.Size? getResolution(androidx.camera.core.CameraInfo, androidx.camera.video.Quality);
+    method @Deprecated public static java.util.List<androidx.camera.video.Quality!> getSupportedQualities(androidx.camera.core.CameraInfo);
+    method @Deprecated public static boolean isQualitySupported(androidx.camera.core.CameraInfo, androidx.camera.video.Quality);
+  }
+
+  public final class Recorder implements androidx.camera.video.VideoOutput {
+    method public int getAspectRatio();
+    method public java.util.concurrent.Executor? getExecutor();
+    method public androidx.camera.video.QualitySelector getQualitySelector();
+    method public int getTargetVideoEncodingBitRate();
+    method public static androidx.camera.video.VideoCapabilities getVideoCapabilities(androidx.camera.core.CameraInfo);
+    method public static androidx.camera.video.VideoCapabilities getVideoCapabilities(androidx.camera.core.CameraInfo, int);
+    method public int getVideoCapabilitiesSource();
+    method public void onSurfaceRequested(androidx.camera.core.SurfaceRequest);
+    method @RequiresApi(26) public androidx.camera.video.PendingRecording prepareRecording(android.content.Context, androidx.camera.video.FileDescriptorOutputOptions);
+    method public androidx.camera.video.PendingRecording prepareRecording(android.content.Context, androidx.camera.video.FileOutputOptions);
+    method public androidx.camera.video.PendingRecording prepareRecording(android.content.Context, androidx.camera.video.MediaStoreOutputOptions);
+    field public static final androidx.camera.video.QualitySelector DEFAULT_QUALITY_SELECTOR;
+    field public static final int VIDEO_CAPABILITIES_SOURCE_CAMCORDER_PROFILE = 0; // 0x0
+    field public static final int VIDEO_CAPABILITIES_SOURCE_CODEC_CAPABILITIES = 1; // 0x1
+  }
+
+  public static final class Recorder.Builder {
+    ctor public Recorder.Builder();
+    method public androidx.camera.video.Recorder build();
+    method public androidx.camera.video.Recorder.Builder setAspectRatio(int);
+    method public androidx.camera.video.Recorder.Builder setExecutor(java.util.concurrent.Executor);
+    method public androidx.camera.video.Recorder.Builder setQualitySelector(androidx.camera.video.QualitySelector);
+    method public androidx.camera.video.Recorder.Builder setTargetVideoEncodingBitRate(@IntRange(from=1) int);
+    method public androidx.camera.video.Recorder.Builder setVideoCapabilitiesSource(int);
+  }
+
+  public final class Recording implements java.lang.AutoCloseable {
+    method public void close();
+    method @SuppressCompatibility @androidx.camera.video.ExperimentalPersistentRecording public boolean isPersistent();
+    method public void mute(boolean);
+    method public void pause();
+    method public void resume();
+    method public void stop();
+  }
+
+  @com.google.auto.value.AutoValue public abstract class RecordingStats {
+    method public abstract androidx.camera.video.AudioStats getAudioStats();
+    method public abstract long getNumBytesRecorded();
+    method public abstract long getRecordedDurationNanos();
+  }
+
+  public interface VideoCapabilities {
+    method public java.util.Set<androidx.camera.core.DynamicRange!> getSupportedDynamicRanges();
+    method public java.util.List<androidx.camera.video.Quality!> getSupportedQualities(androidx.camera.core.DynamicRange);
+    method public boolean isQualitySupported(androidx.camera.video.Quality, androidx.camera.core.DynamicRange);
+    method public default boolean isStabilizationSupported();
+  }
+
+  public final class VideoCapture<T extends androidx.camera.video.VideoOutput> extends androidx.camera.core.UseCase {
+    method public androidx.camera.core.DynamicRange getDynamicRange();
+    method public int getMirrorMode();
+    method public T getOutput();
+    method public android.util.Range<java.lang.Integer!> getTargetFrameRate();
+    method public int getTargetRotation();
+    method public boolean isVideoStabilizationEnabled();
+    method public void setTargetRotation(int);
+    method public static <T extends androidx.camera.video.VideoOutput> androidx.camera.video.VideoCapture<T!> withOutput(T);
+  }
+
+  public static final class VideoCapture.Builder<T extends androidx.camera.video.VideoOutput> implements androidx.camera.core.ExtendableBuilder<androidx.camera.video.VideoCapture!> {
+    ctor public VideoCapture.Builder(T);
+    method public androidx.camera.video.VideoCapture<T!> build();
+    method public androidx.camera.video.VideoCapture.Builder<T!> setDynamicRange(androidx.camera.core.DynamicRange);
+    method public androidx.camera.video.VideoCapture.Builder<T!> setMirrorMode(int);
+    method public androidx.camera.video.VideoCapture.Builder<T!> setTargetFrameRate(android.util.Range<java.lang.Integer!>);
+    method public androidx.camera.video.VideoCapture.Builder<T!> setTargetRotation(int);
+    method public androidx.camera.video.VideoCapture.Builder<T!> setVideoStabilizationEnabled(boolean);
+  }
+
+  public interface VideoOutput {
+    method public void onSurfaceRequested(androidx.camera.core.SurfaceRequest);
+  }
+
+  public abstract class VideoRecordEvent {
+    method public androidx.camera.video.OutputOptions getOutputOptions();
+    method public androidx.camera.video.RecordingStats getRecordingStats();
+  }
+
+  public static final class VideoRecordEvent.Finalize extends androidx.camera.video.VideoRecordEvent {
+    method public Throwable? getCause();
+    method public int getError();
+    method public androidx.camera.video.OutputResults getOutputResults();
+    method public boolean hasError();
+    field public static final int ERROR_DURATION_LIMIT_REACHED = 9; // 0x9
+    field public static final int ERROR_ENCODING_FAILED = 6; // 0x6
+    field public static final int ERROR_FILE_SIZE_LIMIT_REACHED = 2; // 0x2
+    field public static final int ERROR_INSUFFICIENT_STORAGE = 3; // 0x3
+    field public static final int ERROR_INVALID_OUTPUT_OPTIONS = 5; // 0x5
+    field public static final int ERROR_NONE = 0; // 0x0
+    field public static final int ERROR_NO_VALID_DATA = 8; // 0x8
+    field public static final int ERROR_RECORDER_ERROR = 7; // 0x7
+    field public static final int ERROR_RECORDING_GARBAGE_COLLECTED = 10; // 0xa
+    field public static final int ERROR_SOURCE_INACTIVE = 4; // 0x4
+    field public static final int ERROR_UNKNOWN = 1; // 0x1
+  }
+
+  public static final class VideoRecordEvent.Pause extends androidx.camera.video.VideoRecordEvent {
+  }
+
+  public static final class VideoRecordEvent.Resume extends androidx.camera.video.VideoRecordEvent {
+  }
+
+  public static final class VideoRecordEvent.Start extends androidx.camera.video.VideoRecordEvent {
+  }
+
+  public static final class VideoRecordEvent.Status extends androidx.camera.video.VideoRecordEvent {
+  }
+
+}
+
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/VideoRecordingTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/VideoRecordingTest.kt
index 8c44d0b..8901d7c 100644
--- a/camera/camera-video/src/androidTest/java/androidx/camera/video/VideoRecordingTest.kt
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/VideoRecordingTest.kt
@@ -43,6 +43,7 @@
 import androidx.camera.core.UseCase
 import androidx.camera.core.UseCaseGroup
 import androidx.camera.core.impl.CameraControlInternal
+import androidx.camera.core.impl.SessionConfig
 import androidx.camera.core.impl.utils.AspectRatioUtil.ASPECT_RATIO_16_9
 import androidx.camera.core.impl.utils.AspectRatioUtil.ASPECT_RATIO_3_4
 import androidx.camera.core.impl.utils.AspectRatioUtil.ASPECT_RATIO_4_3
@@ -638,6 +639,114 @@
     }
 
     @Test
+    fun recordingWhenSessionErrorListenerReceivesError() {
+        val recorder = Recorder.Builder().build()
+        videoCapture = VideoCapture.withOutput(recorder)
+
+        instrumentation.runOnMainSync {
+            cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview, videoCapture)
+        }
+
+        // Verifies recording before triggering onError event
+        verifyRecording()
+
+        // Retrieves the initial session config
+        var sessionConfig = videoCapture.sessionConfig
+
+        // Checks that video can be recorded successfully when onError is received.
+        triggerOnErrorAndWaitForReady(
+            sessionConfig,
+            recorder.mVideoEncoderSession.readyToReleaseFuture
+        )
+        // Verifies recording after triggering onError event
+        verifyRecording()
+
+        // Rebinds to different camera
+        val oppositeCameraSelector = getOppositeDirectionCameraSelector()
+        if (CameraUtil.hasCameraWithLensFacing(oppositeCameraSelector.lensFacing!!)) {
+            instrumentation.runOnMainSync {
+                cameraProvider.unbindAll()
+                cameraProvider.bindToLifecycle(
+                    lifecycleOwner,
+                    oppositeCameraSelector,
+                    preview,
+                    videoCapture
+                )
+            }
+
+            // Verifies recording after binding to different camera
+            verifyRecording()
+
+            // Checks that video can be recorded successfully when onError is received by the
+            // old error listener.
+            triggerOnErrorAndWaitForReady(sessionConfig)
+
+            // Verifies recording after triggering onError event to the closed error listener
+            verifyRecording()
+        }
+
+        // Update the session config
+        sessionConfig = videoCapture.sessionConfig
+
+        // Checks that image can be received successfully when onError is received by the new
+        // error listener.
+        triggerOnErrorAndWaitForReady(
+            sessionConfig,
+            recorder.mVideoEncoderSession.readyToReleaseFuture
+        )
+        // Verifies recording after triggering onError event to the new active error listener
+        verifyRecording()
+    }
+
+    private fun getOppositeDirectionCameraSelector(): CameraSelector =
+        if (cameraSelector == CameraSelector.DEFAULT_BACK_CAMERA) {
+            CameraSelector.DEFAULT_FRONT_CAMERA
+        } else {
+            CameraSelector.DEFAULT_BACK_CAMERA
+        }
+
+    private fun verifyRecording() {
+        latchForVideoSaved = CountDownLatch(1)
+        latchForVideoRecording = CountDownLatch(5)
+
+        completeVideoRecording(videoCapture)
+    }
+
+    /**
+     * Triggers the onError to the error listener in the session config
+     *
+     * If the test starts recording immediately after `onError` is called. There could be a timing
+     * issue which causes the recording to be stopped. In that case, input the VideoEncoderSession's
+     * readyToReleaseFuture. This function will wait for the ready-to-release future to be
+     * completed. This can make sure that the following recording operation won't be interrupted
+     * when the previous DeferrableSurface is closed.
+     */
+    private fun triggerOnErrorAndWaitForReady(
+        sessionConfig: SessionConfig,
+        readyFuture: ListenableFuture<*>? = null
+    ) {
+        instrumentation.runOnMainSync {
+            sessionConfig.errorListener!!.onError(
+                sessionConfig,
+                SessionConfig.SessionError.SESSION_ERROR_UNKNOWN
+            )
+        }
+
+        // If the test starts recording immediately after `onError` is called. There could be a
+        // timing issue which causes the recording to be stopped.
+        // On the main thread: trigger OnError
+        //    -> resetPipeline
+        //    -> DeferrableSurface is closed
+        //    -> SurfaceRequest is complete
+        // On the test thread: start recording
+        // On the Recorder mSequentialExecutor:
+        //    The listener of readyToReleaseFuture executes due to SurfaceRequest is complete
+        //    -> Recorder.requestReset()
+        //    -> recording is stopped unexpectedly.
+        readyFuture?.get(VIDEO_TIMEOUT_SEC, TimeUnit.SECONDS)
+    }
+
+    @Test
     fun boundButNotRecordingDuringCapture_withPreviewAndImageCapture() {
         // Pre-check and arrange
         val imageCapture = ImageCapture.Builder().build()
@@ -1557,7 +1666,7 @@
 
     private fun completeVideoRecording(
         videoCapture: VideoCapture<Recorder>,
-        file: File,
+        file: File = temporaryFolder.newFile(),
         recording: Recording = startVideoRecording(videoCapture, file),
         allowError: Boolean = false,
     ) {
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/VideoCapture.java b/camera/camera-video/src/main/java/androidx/camera/video/VideoCapture.java
index c55dd58..578d79e 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/VideoCapture.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/VideoCapture.java
@@ -197,6 +197,8 @@
     private boolean mHasCompensatingTransformation = false;
     @Nullable
     private SourceStreamRequirementObserver mSourceStreamRequirementObserver;
+    @Nullable
+    private SessionConfig.CloseableErrorListener mCloseableErrorListener;
 
     /**
      * Create a VideoCapture associated with the given {@link VideoOutput}.
@@ -335,16 +337,18 @@
     @RestrictTo(Scope.LIBRARY_GROUP)
     @NonNull
     @Override
-    protected StreamSpec onSuggestedStreamSpecUpdated(@NonNull StreamSpec suggestedStreamSpec) {
-        Logger.d(TAG, "onSuggestedStreamSpecUpdated: " + suggestedStreamSpec);
+    protected StreamSpec onSuggestedStreamSpecUpdated(
+            @NonNull StreamSpec primaryStreamSpec,
+            @Nullable StreamSpec secondaryStreamSpec) {
+        Logger.d(TAG, "onSuggestedStreamSpecUpdated: " + primaryStreamSpec);
         VideoCaptureConfig<T> config = (VideoCaptureConfig<T>) getCurrentConfig();
         List<Size> customOrderedResolutions = config.getCustomOrderedResolutions(null);
         if (customOrderedResolutions != null
-                && !customOrderedResolutions.contains(suggestedStreamSpec.getResolution())) {
-            Logger.w(TAG, "suggested resolution " + suggestedStreamSpec.getResolution()
+                && !customOrderedResolutions.contains(primaryStreamSpec.getResolution())) {
+            Logger.w(TAG, "suggested resolution " + primaryStreamSpec.getResolution()
                     + " is not in custom ordered resolutions " + customOrderedResolutions);
         }
-        return suggestedStreamSpec;
+        return primaryStreamSpec;
     }
 
     /**
@@ -382,18 +386,19 @@
 
         Logger.d(TAG, "VideoCapture#onStateAttached: cameraID = " + getCameraId());
 
-        Preconditions.checkNotNull(getAttachedStreamSpec(), "The suggested stream "
-                + "specification should be already updated and shouldn't be null.");
-        Preconditions.checkState(mSurfaceRequest == null, "The surface request should be null "
-                + "when VideoCapture is attached.");
+        // For concurrent camera, the surface request might not be null when switching
+        // from single to dual camera.
+        if (getAttachedStreamSpec() == null || mSurfaceRequest != null) {
+            return;
+        }
         StreamSpec attachedStreamSpec = Preconditions.checkNotNull(getAttachedStreamSpec());
         mStreamInfo = fetchObservableValue(getOutput().getStreamInfo(),
                 StreamInfo.STREAM_INFO_ANY_INACTIVE);
-        mSessionConfigBuilder = createPipeline(getCameraId(),
+        mSessionConfigBuilder = createPipeline(
                 (VideoCaptureConfig<T>) getCurrentConfig(), attachedStreamSpec);
         applyStreamInfoAndStreamSpecToSessionConfigBuilder(mSessionConfigBuilder, mStreamInfo,
                 attachedStreamSpec);
-        updateSessionConfig(mSessionConfigBuilder.build());
+        updateSessionConfig(List.of(mSessionConfigBuilder.build()));
         // VideoCapture has to be active to apply SessionConfig's template type.
         notifyActive();
         getOutput().getStreamInfo().addObserver(CameraXExecutors.mainThreadExecutor(),
@@ -461,7 +466,7 @@
     @RestrictTo(Scope.LIBRARY_GROUP)
     protected StreamSpec onSuggestedStreamSpecImplementationOptionsUpdated(@NonNull Config config) {
         mSessionConfigBuilder.addImplementationOptions(config);
-        updateSessionConfig(mSessionConfigBuilder.build());
+        updateSessionConfig(List.of(mSessionConfigBuilder.build()));
         return requireNonNull(getAttachedStreamSpec()).toBuilder()
                 .setImplementationOptions(config).build();
     }
@@ -609,7 +614,7 @@
     @SuppressLint("WrongConstant")
     @MainThread
     @NonNull
-    private SessionConfig.Builder createPipeline(@NonNull String cameraId,
+    private SessionConfig.Builder createPipeline(
             @NonNull VideoCaptureConfig<T> config,
             @NonNull StreamSpec streamSpec) {
         Threads.checkMainThread();
@@ -701,8 +706,12 @@
         // default if unresolved).
         sessionConfigBuilder.setExpectedFrameRateRange(streamSpec.getExpectedFrameRateRange());
         sessionConfigBuilder.setVideoStabilization(config.getVideoStabilizationMode());
-        sessionConfigBuilder.addErrorListener(
-                (sessionConfig, error) -> resetPipeline(cameraId, config, streamSpec));
+        if (mCloseableErrorListener != null) {
+            mCloseableErrorListener.close();
+        }
+        mCloseableErrorListener = new SessionConfig.CloseableErrorListener(
+                (sessionConfig, error) -> resetPipeline());
+        sessionConfigBuilder.setErrorListener(mCloseableErrorListener);
         if (streamSpec.getImplementationOptions() != null) {
             sessionConfigBuilder.addImplementationOptions(streamSpec.getImplementationOptions());
         }
@@ -726,6 +735,12 @@
     private void clearPipeline() {
         Threads.checkMainThread();
 
+        // Closes the old error listener
+        if (mCloseableErrorListener != null) {
+            mCloseableErrorListener.close();
+            mCloseableErrorListener = null;
+        }
+
         if (mDeferrableSurface != null) {
             mDeferrableSurface.close();
             mDeferrableSurface = null;
@@ -746,23 +761,21 @@
     }
 
     @MainThread
-    @SuppressWarnings("WeakerAccess") /* synthetic accessor */
-    void resetPipeline(@NonNull String cameraId,
-            @NonNull VideoCaptureConfig<T> config,
-            @NonNull StreamSpec streamSpec) {
-        clearPipeline();
-
-        // Ensure the attached camera has not changed before resetting.
-        // TODO(b/143915543): Ensure this never gets called by a camera that is not attached
-        //  to this use case so we don't need to do this check.
-        if (isCurrentCamera(cameraId)) {
-            // Only reset the pipeline when the bound camera is the same.
-            mSessionConfigBuilder = createPipeline(cameraId, config, streamSpec);
-            applyStreamInfoAndStreamSpecToSessionConfigBuilder(mSessionConfigBuilder, mStreamInfo,
-                    streamSpec);
-            updateSessionConfig(mSessionConfigBuilder.build());
-            notifyReset();
+    @SuppressWarnings({"WeakerAccess", "unchecked"}) /* synthetic accessor */
+    void resetPipeline() {
+        // Do nothing when the use case has been unbound.
+        if (getCamera() == null) {
+            return;
         }
+
+        clearPipeline();
+        mSessionConfigBuilder = createPipeline(
+                (VideoCaptureConfig<T>) getCurrentConfig(),
+                Preconditions.checkNotNull(getAttachedStreamSpec()));
+        applyStreamInfoAndStreamSpecToSessionConfigBuilder(mSessionConfigBuilder, mStreamInfo,
+                getAttachedStreamSpec());
+        updateSessionConfig(List.of(mSessionConfigBuilder.build()));
+        notifyReset();
     }
 
     /**
@@ -852,8 +865,7 @@
                 // requested.
                 // 2. The in-progress transformation info becomes null, which means a recording
                 // has been finalized, and there's an existing compensating transformation.
-                resetPipeline(getCameraId(), (VideoCaptureConfig<T>) getCurrentConfig(),
-                        Preconditions.checkNotNull(getAttachedStreamSpec()));
+                resetPipeline();
             } else if ((currentStreamInfo.getId() != STREAM_ID_ERROR
                     && streamInfo.getId() == STREAM_ID_ERROR)
                     || (currentStreamInfo.getId() == STREAM_ID_ERROR
@@ -863,13 +875,13 @@
                 applyStreamInfoAndStreamSpecToSessionConfigBuilder(mSessionConfigBuilder,
                         streamInfo,
                         attachedStreamSpec);
-                updateSessionConfig(mSessionConfigBuilder.build());
+                updateSessionConfig(List.of(mSessionConfigBuilder.build()));
                 notifyReset();
             } else if (currentStreamInfo.getStreamState() != streamInfo.getStreamState()) {
                 applyStreamInfoAndStreamSpecToSessionConfigBuilder(mSessionConfigBuilder,
                         streamInfo,
                         attachedStreamSpec);
-                updateSessionConfig(mSessionConfigBuilder.build());
+                updateSessionConfig(List.of(mSessionConfigBuilder.build()));
                 notifyUpdated();
             }
         }
diff --git a/camera/camera-video/src/test/java/androidx/camera/video/VideoCaptureTest.kt b/camera/camera-video/src/test/java/androidx/camera/video/VideoCaptureTest.kt
index ab946e1..0f51b5b 100644
--- a/camera/camera-video/src/test/java/androidx/camera/video/VideoCaptureTest.kt
+++ b/camera/camera-video/src/test/java/androidx/camera/video/VideoCaptureTest.kt
@@ -205,9 +205,10 @@
         videoCapture.bindToCamera(
             camera,
             null,
+            null,
             videoCapture.getDefaultConfig(true, FakeUseCaseConfigFactory())
         )
-        videoCapture.updateSuggestedStreamSpec(StreamSpec.builder(Size(640, 480)).build())
+        videoCapture.updateSuggestedStreamSpec(StreamSpec.builder(Size(640, 480)).build(), null)
         videoCapture.onStateAttached()
         // Assert: camera edge does not have transform.
         assertThat(videoCapture.cameraEdge!!.hasCameraTransform()).isFalse()
diff --git a/camera/camera-view/api/1.4.0-beta03.txt b/camera/camera-view/api/1.4.0-beta03.txt
new file mode 100644
index 0000000..3b66417
--- /dev/null
+++ b/camera/camera-view/api/1.4.0-beta03.txt
@@ -0,0 +1,204 @@
+// Signature format: 4.0
+package androidx.camera.view {
+
+  public abstract class CameraController {
+    method @MainThread public void clearEffects();
+    method @MainThread public void clearImageAnalysisAnalyzer();
+    method @MainThread public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enableTorch(boolean);
+    method @MainThread public androidx.camera.core.CameraControl? getCameraControl();
+    method @MainThread public androidx.camera.core.CameraInfo? getCameraInfo();
+    method @MainThread public androidx.camera.core.CameraSelector getCameraSelector();
+    method @MainThread public java.util.concurrent.Executor? getImageAnalysisBackgroundExecutor();
+    method @MainThread public int getImageAnalysisBackpressureStrategy();
+    method @MainThread public int getImageAnalysisImageQueueDepth();
+    method @MainThread public int getImageAnalysisOutputImageFormat();
+    method @MainThread public androidx.camera.core.resolutionselector.ResolutionSelector? getImageAnalysisResolutionSelector();
+    method @Deprecated @MainThread public androidx.camera.view.CameraController.OutputSize? getImageAnalysisTargetSize();
+    method @MainThread public int getImageCaptureFlashMode();
+    method @MainThread public java.util.concurrent.Executor? getImageCaptureIoExecutor();
+    method @MainThread public int getImageCaptureMode();
+    method @MainThread public androidx.camera.core.resolutionselector.ResolutionSelector? getImageCaptureResolutionSelector();
+    method @Deprecated @MainThread public androidx.camera.view.CameraController.OutputSize? getImageCaptureTargetSize();
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> getInitializationFuture();
+    method @MainThread public androidx.camera.core.resolutionselector.ResolutionSelector? getPreviewResolutionSelector();
+    method @Deprecated @MainThread public androidx.camera.view.CameraController.OutputSize? getPreviewTargetSize();
+    method @MainThread public androidx.lifecycle.LiveData<java.lang.Integer!> getTapToFocusState();
+    method @MainThread public androidx.lifecycle.LiveData<java.lang.Integer!> getTorchState();
+    method @MainThread public androidx.camera.core.DynamicRange getVideoCaptureDynamicRange();
+    method @MainThread public int getVideoCaptureMirrorMode();
+    method @MainThread public androidx.camera.video.QualitySelector getVideoCaptureQualitySelector();
+    method @MainThread public android.util.Range<java.lang.Integer!> getVideoCaptureTargetFrameRate();
+    method @MainThread public androidx.lifecycle.LiveData<androidx.camera.core.ZoomState!> getZoomState();
+    method @MainThread public boolean hasCamera(androidx.camera.core.CameraSelector);
+    method @MainThread public boolean isImageAnalysisEnabled();
+    method @MainThread public boolean isImageCaptureEnabled();
+    method @MainThread public boolean isPinchToZoomEnabled();
+    method @MainThread public boolean isRecording();
+    method @MainThread public boolean isTapToFocusEnabled();
+    method @MainThread public boolean isVideoCaptureEnabled();
+    method @MainThread public void setCameraSelector(androidx.camera.core.CameraSelector);
+    method @MainThread public void setEffects(java.util.Set<androidx.camera.core.CameraEffect!>);
+    method @MainThread public void setEnabledUseCases(int);
+    method @MainThread public void setImageAnalysisAnalyzer(java.util.concurrent.Executor, androidx.camera.core.ImageAnalysis.Analyzer);
+    method @MainThread public void setImageAnalysisBackgroundExecutor(java.util.concurrent.Executor?);
+    method @MainThread public void setImageAnalysisBackpressureStrategy(int);
+    method @MainThread public void setImageAnalysisImageQueueDepth(int);
+    method @MainThread public void setImageAnalysisOutputImageFormat(int);
+    method @MainThread public void setImageAnalysisResolutionSelector(androidx.camera.core.resolutionselector.ResolutionSelector?);
+    method @Deprecated @MainThread public void setImageAnalysisTargetSize(androidx.camera.view.CameraController.OutputSize?);
+    method @MainThread public void setImageCaptureFlashMode(int);
+    method @MainThread public void setImageCaptureIoExecutor(java.util.concurrent.Executor?);
+    method @MainThread public void setImageCaptureMode(int);
+    method @MainThread public void setImageCaptureResolutionSelector(androidx.camera.core.resolutionselector.ResolutionSelector?);
+    method @Deprecated @MainThread public void setImageCaptureTargetSize(androidx.camera.view.CameraController.OutputSize?);
+    method @MainThread public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setLinearZoom(@FloatRange(from=0.0f, to=1.0f) float);
+    method @MainThread public void setPinchToZoomEnabled(boolean);
+    method @MainThread public void setPreviewResolutionSelector(androidx.camera.core.resolutionselector.ResolutionSelector?);
+    method @Deprecated @MainThread public void setPreviewTargetSize(androidx.camera.view.CameraController.OutputSize?);
+    method @MainThread public void setTapToFocusEnabled(boolean);
+    method @MainThread public void setVideoCaptureDynamicRange(androidx.camera.core.DynamicRange);
+    method @MainThread public void setVideoCaptureMirrorMode(int);
+    method @MainThread public void setVideoCaptureQualitySelector(androidx.camera.video.QualitySelector);
+    method @MainThread public void setVideoCaptureTargetFrameRate(android.util.Range<java.lang.Integer!>);
+    method @MainThread public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setZoomRatio(float);
+    method @MainThread @RequiresApi(26) public androidx.camera.video.Recording startRecording(androidx.camera.video.FileDescriptorOutputOptions, androidx.camera.view.video.AudioConfig, java.util.concurrent.Executor, androidx.core.util.Consumer<androidx.camera.video.VideoRecordEvent!>);
+    method @MainThread public androidx.camera.video.Recording startRecording(androidx.camera.video.FileOutputOptions, androidx.camera.view.video.AudioConfig, java.util.concurrent.Executor, androidx.core.util.Consumer<androidx.camera.video.VideoRecordEvent!>);
+    method @MainThread public androidx.camera.video.Recording startRecording(androidx.camera.video.MediaStoreOutputOptions, androidx.camera.view.video.AudioConfig, java.util.concurrent.Executor, androidx.core.util.Consumer<androidx.camera.video.VideoRecordEvent!>);
+    method @MainThread public void takePicture(androidx.camera.core.ImageCapture.OutputFileOptions, java.util.concurrent.Executor, androidx.camera.core.ImageCapture.OnImageSavedCallback);
+    method @MainThread public void takePicture(java.util.concurrent.Executor, androidx.camera.core.ImageCapture.OnImageCapturedCallback);
+    field @Deprecated public static final int COORDINATE_SYSTEM_VIEW_REFERENCED = 1; // 0x1
+    field public static final int IMAGE_ANALYSIS = 2; // 0x2
+    field public static final int IMAGE_CAPTURE = 1; // 0x1
+    field public static final int TAP_TO_FOCUS_FAILED = 4; // 0x4
+    field public static final int TAP_TO_FOCUS_FOCUSED = 2; // 0x2
+    field public static final int TAP_TO_FOCUS_NOT_FOCUSED = 3; // 0x3
+    field public static final int TAP_TO_FOCUS_NOT_STARTED = 0; // 0x0
+    field public static final int TAP_TO_FOCUS_STARTED = 1; // 0x1
+    field public static final int VIDEO_CAPTURE = 4; // 0x4
+  }
+
+  @Deprecated public static final class CameraController.OutputSize {
+    ctor @Deprecated public CameraController.OutputSize(android.util.Size);
+    ctor @Deprecated public CameraController.OutputSize(int);
+    method @Deprecated public int getAspectRatio();
+    method @Deprecated public android.util.Size? getResolution();
+    field @Deprecated public static final int UNASSIGNED_ASPECT_RATIO = -1; // 0xffffffff
+  }
+
+  @SuppressCompatibility @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface ExperimentalPreviewViewScreenFlash {
+  }
+
+  public final class LifecycleCameraController extends androidx.camera.view.CameraController {
+    ctor public LifecycleCameraController(android.content.Context);
+    method @MainThread public void bindToLifecycle(androidx.lifecycle.LifecycleOwner);
+    method @MainThread public void unbind();
+  }
+
+  public final class PreviewView extends android.widget.FrameLayout {
+    ctor @UiThread public PreviewView(android.content.Context);
+    ctor @UiThread public PreviewView(android.content.Context, android.util.AttributeSet?);
+    ctor @UiThread public PreviewView(android.content.Context, android.util.AttributeSet?, int);
+    ctor @UiThread public PreviewView(android.content.Context, android.util.AttributeSet?, int, int);
+    method @UiThread public android.graphics.Bitmap? getBitmap();
+    method @UiThread public androidx.camera.view.CameraController? getController();
+    method @UiThread public androidx.camera.view.PreviewView.ImplementationMode getImplementationMode();
+    method @UiThread public androidx.camera.core.MeteringPointFactory getMeteringPointFactory();
+    method @SuppressCompatibility public androidx.camera.view.transform.OutputTransform? getOutputTransform();
+    method public androidx.lifecycle.LiveData<androidx.camera.view.PreviewView.StreamState!> getPreviewStreamState();
+    method @UiThread public androidx.camera.view.PreviewView.ScaleType getScaleType();
+    method @SuppressCompatibility @UiThread @androidx.camera.view.ExperimentalPreviewViewScreenFlash public androidx.camera.core.ImageCapture.ScreenFlash? getScreenFlash();
+    method @UiThread public android.graphics.Matrix? getSensorToViewTransform();
+    method @UiThread public androidx.camera.core.Preview.SurfaceProvider getSurfaceProvider();
+    method @UiThread public androidx.camera.core.ViewPort? getViewPort();
+    method @UiThread public androidx.camera.core.ViewPort? getViewPort(int);
+    method @UiThread public void setController(androidx.camera.view.CameraController?);
+    method @UiThread public void setImplementationMode(androidx.camera.view.PreviewView.ImplementationMode);
+    method @UiThread public void setScaleType(androidx.camera.view.PreviewView.ScaleType);
+    method @SuppressCompatibility @androidx.camera.view.ExperimentalPreviewViewScreenFlash public void setScreenFlashOverlayColor(@ColorInt int);
+    method @UiThread public void setScreenFlashWindow(android.view.Window?);
+  }
+
+  public enum PreviewView.ImplementationMode {
+    enum_constant public static final androidx.camera.view.PreviewView.ImplementationMode COMPATIBLE;
+    enum_constant public static final androidx.camera.view.PreviewView.ImplementationMode PERFORMANCE;
+  }
+
+  public enum PreviewView.ScaleType {
+    enum_constant public static final androidx.camera.view.PreviewView.ScaleType FILL_CENTER;
+    enum_constant public static final androidx.camera.view.PreviewView.ScaleType FILL_END;
+    enum_constant public static final androidx.camera.view.PreviewView.ScaleType FILL_START;
+    enum_constant public static final androidx.camera.view.PreviewView.ScaleType FIT_CENTER;
+    enum_constant public static final androidx.camera.view.PreviewView.ScaleType FIT_END;
+    enum_constant public static final androidx.camera.view.PreviewView.ScaleType FIT_START;
+  }
+
+  public enum PreviewView.StreamState {
+    enum_constant public static final androidx.camera.view.PreviewView.StreamState IDLE;
+    enum_constant public static final androidx.camera.view.PreviewView.StreamState STREAMING;
+  }
+
+  public final class RotationProvider {
+    ctor public RotationProvider(android.content.Context);
+    method @CheckResult public boolean addListener(java.util.concurrent.Executor, androidx.camera.view.RotationProvider.Listener);
+    method public void removeListener(androidx.camera.view.RotationProvider.Listener);
+  }
+
+  public static interface RotationProvider.Listener {
+    method public void onRotationChanged(int);
+  }
+
+  public final class ScreenFlashView extends android.view.View {
+    ctor @UiThread public ScreenFlashView(android.content.Context);
+    ctor @UiThread public ScreenFlashView(android.content.Context, android.util.AttributeSet?);
+    ctor @UiThread public ScreenFlashView(android.content.Context, android.util.AttributeSet?, int);
+    ctor @UiThread public ScreenFlashView(android.content.Context, android.util.AttributeSet?, int, int);
+    method @UiThread public androidx.camera.core.ImageCapture.ScreenFlash? getScreenFlash();
+    method @UiThread public void setController(androidx.camera.view.CameraController?);
+    method @UiThread public void setScreenFlashWindow(android.view.Window?);
+  }
+
+}
+
+package androidx.camera.view.transform {
+
+  @SuppressCompatibility public final class CoordinateTransform {
+    ctor public CoordinateTransform(androidx.camera.view.transform.OutputTransform, androidx.camera.view.transform.OutputTransform);
+    method public void mapPoint(android.graphics.PointF);
+    method public void mapPoints(float[]);
+    method public void mapRect(android.graphics.RectF);
+    method public void transform(android.graphics.Matrix);
+  }
+
+  @SuppressCompatibility public final class FileTransformFactory {
+    ctor public FileTransformFactory();
+    method public androidx.camera.view.transform.OutputTransform getOutputTransform(android.content.ContentResolver, android.net.Uri) throws java.io.IOException;
+    method public androidx.camera.view.transform.OutputTransform getOutputTransform(java.io.File) throws java.io.IOException;
+    method public androidx.camera.view.transform.OutputTransform getOutputTransform(java.io.InputStream) throws java.io.IOException;
+    method public boolean isUsingExifOrientation();
+    method public void setUsingExifOrientation(boolean);
+  }
+
+  @SuppressCompatibility public final class ImageProxyTransformFactory {
+    ctor public ImageProxyTransformFactory();
+    method public androidx.camera.view.transform.OutputTransform getOutputTransform(androidx.camera.core.ImageProxy);
+    method public boolean isUsingCropRect();
+    method public boolean isUsingRotationDegrees();
+    method public void setUsingCropRect(boolean);
+    method public void setUsingRotationDegrees(boolean);
+  }
+
+  @SuppressCompatibility public final class OutputTransform {
+  }
+
+}
+
+package androidx.camera.view.video {
+
+  public class AudioConfig {
+    method @RequiresPermission(android.Manifest.permission.RECORD_AUDIO) public static androidx.camera.view.video.AudioConfig create(boolean);
+    method public boolean getAudioEnabled();
+    field public static final androidx.camera.view.video.AudioConfig AUDIO_DISABLED;
+  }
+
+}
+
diff --git a/camera/camera-view/api/res-1.4.0-beta03.txt b/camera/camera-view/api/res-1.4.0-beta03.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/camera/camera-view/api/res-1.4.0-beta03.txt
diff --git a/camera/camera-view/api/restricted_1.4.0-beta03.txt b/camera/camera-view/api/restricted_1.4.0-beta03.txt
new file mode 100644
index 0000000..3b66417
--- /dev/null
+++ b/camera/camera-view/api/restricted_1.4.0-beta03.txt
@@ -0,0 +1,204 @@
+// Signature format: 4.0
+package androidx.camera.view {
+
+  public abstract class CameraController {
+    method @MainThread public void clearEffects();
+    method @MainThread public void clearImageAnalysisAnalyzer();
+    method @MainThread public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enableTorch(boolean);
+    method @MainThread public androidx.camera.core.CameraControl? getCameraControl();
+    method @MainThread public androidx.camera.core.CameraInfo? getCameraInfo();
+    method @MainThread public androidx.camera.core.CameraSelector getCameraSelector();
+    method @MainThread public java.util.concurrent.Executor? getImageAnalysisBackgroundExecutor();
+    method @MainThread public int getImageAnalysisBackpressureStrategy();
+    method @MainThread public int getImageAnalysisImageQueueDepth();
+    method @MainThread public int getImageAnalysisOutputImageFormat();
+    method @MainThread public androidx.camera.core.resolutionselector.ResolutionSelector? getImageAnalysisResolutionSelector();
+    method @Deprecated @MainThread public androidx.camera.view.CameraController.OutputSize? getImageAnalysisTargetSize();
+    method @MainThread public int getImageCaptureFlashMode();
+    method @MainThread public java.util.concurrent.Executor? getImageCaptureIoExecutor();
+    method @MainThread public int getImageCaptureMode();
+    method @MainThread public androidx.camera.core.resolutionselector.ResolutionSelector? getImageCaptureResolutionSelector();
+    method @Deprecated @MainThread public androidx.camera.view.CameraController.OutputSize? getImageCaptureTargetSize();
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> getInitializationFuture();
+    method @MainThread public androidx.camera.core.resolutionselector.ResolutionSelector? getPreviewResolutionSelector();
+    method @Deprecated @MainThread public androidx.camera.view.CameraController.OutputSize? getPreviewTargetSize();
+    method @MainThread public androidx.lifecycle.LiveData<java.lang.Integer!> getTapToFocusState();
+    method @MainThread public androidx.lifecycle.LiveData<java.lang.Integer!> getTorchState();
+    method @MainThread public androidx.camera.core.DynamicRange getVideoCaptureDynamicRange();
+    method @MainThread public int getVideoCaptureMirrorMode();
+    method @MainThread public androidx.camera.video.QualitySelector getVideoCaptureQualitySelector();
+    method @MainThread public android.util.Range<java.lang.Integer!> getVideoCaptureTargetFrameRate();
+    method @MainThread public androidx.lifecycle.LiveData<androidx.camera.core.ZoomState!> getZoomState();
+    method @MainThread public boolean hasCamera(androidx.camera.core.CameraSelector);
+    method @MainThread public boolean isImageAnalysisEnabled();
+    method @MainThread public boolean isImageCaptureEnabled();
+    method @MainThread public boolean isPinchToZoomEnabled();
+    method @MainThread public boolean isRecording();
+    method @MainThread public boolean isTapToFocusEnabled();
+    method @MainThread public boolean isVideoCaptureEnabled();
+    method @MainThread public void setCameraSelector(androidx.camera.core.CameraSelector);
+    method @MainThread public void setEffects(java.util.Set<androidx.camera.core.CameraEffect!>);
+    method @MainThread public void setEnabledUseCases(int);
+    method @MainThread public void setImageAnalysisAnalyzer(java.util.concurrent.Executor, androidx.camera.core.ImageAnalysis.Analyzer);
+    method @MainThread public void setImageAnalysisBackgroundExecutor(java.util.concurrent.Executor?);
+    method @MainThread public void setImageAnalysisBackpressureStrategy(int);
+    method @MainThread public void setImageAnalysisImageQueueDepth(int);
+    method @MainThread public void setImageAnalysisOutputImageFormat(int);
+    method @MainThread public void setImageAnalysisResolutionSelector(androidx.camera.core.resolutionselector.ResolutionSelector?);
+    method @Deprecated @MainThread public void setImageAnalysisTargetSize(androidx.camera.view.CameraController.OutputSize?);
+    method @MainThread public void setImageCaptureFlashMode(int);
+    method @MainThread public void setImageCaptureIoExecutor(java.util.concurrent.Executor?);
+    method @MainThread public void setImageCaptureMode(int);
+    method @MainThread public void setImageCaptureResolutionSelector(androidx.camera.core.resolutionselector.ResolutionSelector?);
+    method @Deprecated @MainThread public void setImageCaptureTargetSize(androidx.camera.view.CameraController.OutputSize?);
+    method @MainThread public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setLinearZoom(@FloatRange(from=0.0f, to=1.0f) float);
+    method @MainThread public void setPinchToZoomEnabled(boolean);
+    method @MainThread public void setPreviewResolutionSelector(androidx.camera.core.resolutionselector.ResolutionSelector?);
+    method @Deprecated @MainThread public void setPreviewTargetSize(androidx.camera.view.CameraController.OutputSize?);
+    method @MainThread public void setTapToFocusEnabled(boolean);
+    method @MainThread public void setVideoCaptureDynamicRange(androidx.camera.core.DynamicRange);
+    method @MainThread public void setVideoCaptureMirrorMode(int);
+    method @MainThread public void setVideoCaptureQualitySelector(androidx.camera.video.QualitySelector);
+    method @MainThread public void setVideoCaptureTargetFrameRate(android.util.Range<java.lang.Integer!>);
+    method @MainThread public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setZoomRatio(float);
+    method @MainThread @RequiresApi(26) public androidx.camera.video.Recording startRecording(androidx.camera.video.FileDescriptorOutputOptions, androidx.camera.view.video.AudioConfig, java.util.concurrent.Executor, androidx.core.util.Consumer<androidx.camera.video.VideoRecordEvent!>);
+    method @MainThread public androidx.camera.video.Recording startRecording(androidx.camera.video.FileOutputOptions, androidx.camera.view.video.AudioConfig, java.util.concurrent.Executor, androidx.core.util.Consumer<androidx.camera.video.VideoRecordEvent!>);
+    method @MainThread public androidx.camera.video.Recording startRecording(androidx.camera.video.MediaStoreOutputOptions, androidx.camera.view.video.AudioConfig, java.util.concurrent.Executor, androidx.core.util.Consumer<androidx.camera.video.VideoRecordEvent!>);
+    method @MainThread public void takePicture(androidx.camera.core.ImageCapture.OutputFileOptions, java.util.concurrent.Executor, androidx.camera.core.ImageCapture.OnImageSavedCallback);
+    method @MainThread public void takePicture(java.util.concurrent.Executor, androidx.camera.core.ImageCapture.OnImageCapturedCallback);
+    field @Deprecated public static final int COORDINATE_SYSTEM_VIEW_REFERENCED = 1; // 0x1
+    field public static final int IMAGE_ANALYSIS = 2; // 0x2
+    field public static final int IMAGE_CAPTURE = 1; // 0x1
+    field public static final int TAP_TO_FOCUS_FAILED = 4; // 0x4
+    field public static final int TAP_TO_FOCUS_FOCUSED = 2; // 0x2
+    field public static final int TAP_TO_FOCUS_NOT_FOCUSED = 3; // 0x3
+    field public static final int TAP_TO_FOCUS_NOT_STARTED = 0; // 0x0
+    field public static final int TAP_TO_FOCUS_STARTED = 1; // 0x1
+    field public static final int VIDEO_CAPTURE = 4; // 0x4
+  }
+
+  @Deprecated public static final class CameraController.OutputSize {
+    ctor @Deprecated public CameraController.OutputSize(android.util.Size);
+    ctor @Deprecated public CameraController.OutputSize(int);
+    method @Deprecated public int getAspectRatio();
+    method @Deprecated public android.util.Size? getResolution();
+    field @Deprecated public static final int UNASSIGNED_ASPECT_RATIO = -1; // 0xffffffff
+  }
+
+  @SuppressCompatibility @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface ExperimentalPreviewViewScreenFlash {
+  }
+
+  public final class LifecycleCameraController extends androidx.camera.view.CameraController {
+    ctor public LifecycleCameraController(android.content.Context);
+    method @MainThread public void bindToLifecycle(androidx.lifecycle.LifecycleOwner);
+    method @MainThread public void unbind();
+  }
+
+  public final class PreviewView extends android.widget.FrameLayout {
+    ctor @UiThread public PreviewView(android.content.Context);
+    ctor @UiThread public PreviewView(android.content.Context, android.util.AttributeSet?);
+    ctor @UiThread public PreviewView(android.content.Context, android.util.AttributeSet?, int);
+    ctor @UiThread public PreviewView(android.content.Context, android.util.AttributeSet?, int, int);
+    method @UiThread public android.graphics.Bitmap? getBitmap();
+    method @UiThread public androidx.camera.view.CameraController? getController();
+    method @UiThread public androidx.camera.view.PreviewView.ImplementationMode getImplementationMode();
+    method @UiThread public androidx.camera.core.MeteringPointFactory getMeteringPointFactory();
+    method @SuppressCompatibility public androidx.camera.view.transform.OutputTransform? getOutputTransform();
+    method public androidx.lifecycle.LiveData<androidx.camera.view.PreviewView.StreamState!> getPreviewStreamState();
+    method @UiThread public androidx.camera.view.PreviewView.ScaleType getScaleType();
+    method @SuppressCompatibility @UiThread @androidx.camera.view.ExperimentalPreviewViewScreenFlash public androidx.camera.core.ImageCapture.ScreenFlash? getScreenFlash();
+    method @UiThread public android.graphics.Matrix? getSensorToViewTransform();
+    method @UiThread public androidx.camera.core.Preview.SurfaceProvider getSurfaceProvider();
+    method @UiThread public androidx.camera.core.ViewPort? getViewPort();
+    method @UiThread public androidx.camera.core.ViewPort? getViewPort(int);
+    method @UiThread public void setController(androidx.camera.view.CameraController?);
+    method @UiThread public void setImplementationMode(androidx.camera.view.PreviewView.ImplementationMode);
+    method @UiThread public void setScaleType(androidx.camera.view.PreviewView.ScaleType);
+    method @SuppressCompatibility @androidx.camera.view.ExperimentalPreviewViewScreenFlash public void setScreenFlashOverlayColor(@ColorInt int);
+    method @UiThread public void setScreenFlashWindow(android.view.Window?);
+  }
+
+  public enum PreviewView.ImplementationMode {
+    enum_constant public static final androidx.camera.view.PreviewView.ImplementationMode COMPATIBLE;
+    enum_constant public static final androidx.camera.view.PreviewView.ImplementationMode PERFORMANCE;
+  }
+
+  public enum PreviewView.ScaleType {
+    enum_constant public static final androidx.camera.view.PreviewView.ScaleType FILL_CENTER;
+    enum_constant public static final androidx.camera.view.PreviewView.ScaleType FILL_END;
+    enum_constant public static final androidx.camera.view.PreviewView.ScaleType FILL_START;
+    enum_constant public static final androidx.camera.view.PreviewView.ScaleType FIT_CENTER;
+    enum_constant public static final androidx.camera.view.PreviewView.ScaleType FIT_END;
+    enum_constant public static final androidx.camera.view.PreviewView.ScaleType FIT_START;
+  }
+
+  public enum PreviewView.StreamState {
+    enum_constant public static final androidx.camera.view.PreviewView.StreamState IDLE;
+    enum_constant public static final androidx.camera.view.PreviewView.StreamState STREAMING;
+  }
+
+  public final class RotationProvider {
+    ctor public RotationProvider(android.content.Context);
+    method @CheckResult public boolean addListener(java.util.concurrent.Executor, androidx.camera.view.RotationProvider.Listener);
+    method public void removeListener(androidx.camera.view.RotationProvider.Listener);
+  }
+
+  public static interface RotationProvider.Listener {
+    method public void onRotationChanged(int);
+  }
+
+  public final class ScreenFlashView extends android.view.View {
+    ctor @UiThread public ScreenFlashView(android.content.Context);
+    ctor @UiThread public ScreenFlashView(android.content.Context, android.util.AttributeSet?);
+    ctor @UiThread public ScreenFlashView(android.content.Context, android.util.AttributeSet?, int);
+    ctor @UiThread public ScreenFlashView(android.content.Context, android.util.AttributeSet?, int, int);
+    method @UiThread public androidx.camera.core.ImageCapture.ScreenFlash? getScreenFlash();
+    method @UiThread public void setController(androidx.camera.view.CameraController?);
+    method @UiThread public void setScreenFlashWindow(android.view.Window?);
+  }
+
+}
+
+package androidx.camera.view.transform {
+
+  @SuppressCompatibility public final class CoordinateTransform {
+    ctor public CoordinateTransform(androidx.camera.view.transform.OutputTransform, androidx.camera.view.transform.OutputTransform);
+    method public void mapPoint(android.graphics.PointF);
+    method public void mapPoints(float[]);
+    method public void mapRect(android.graphics.RectF);
+    method public void transform(android.graphics.Matrix);
+  }
+
+  @SuppressCompatibility public final class FileTransformFactory {
+    ctor public FileTransformFactory();
+    method public androidx.camera.view.transform.OutputTransform getOutputTransform(android.content.ContentResolver, android.net.Uri) throws java.io.IOException;
+    method public androidx.camera.view.transform.OutputTransform getOutputTransform(java.io.File) throws java.io.IOException;
+    method public androidx.camera.view.transform.OutputTransform getOutputTransform(java.io.InputStream) throws java.io.IOException;
+    method public boolean isUsingExifOrientation();
+    method public void setUsingExifOrientation(boolean);
+  }
+
+  @SuppressCompatibility public final class ImageProxyTransformFactory {
+    ctor public ImageProxyTransformFactory();
+    method public androidx.camera.view.transform.OutputTransform getOutputTransform(androidx.camera.core.ImageProxy);
+    method public boolean isUsingCropRect();
+    method public boolean isUsingRotationDegrees();
+    method public void setUsingCropRect(boolean);
+    method public void setUsingRotationDegrees(boolean);
+  }
+
+  @SuppressCompatibility public final class OutputTransform {
+  }
+
+}
+
+package androidx.camera.view.video {
+
+  public class AudioConfig {
+    method @RequiresPermission(android.Manifest.permission.RECORD_AUDIO) public static androidx.camera.view.video.AudioConfig create(boolean);
+    method public boolean getAudioEnabled();
+    field public static final androidx.camera.view.video.AudioConfig AUDIO_DISABLED;
+  }
+
+}
+
diff --git a/camera/camera-view/src/main/java/androidx/camera/view/CameraController.java b/camera/camera-view/src/main/java/androidx/camera/view/CameraController.java
index 36ffe57..8e8933e 100644
--- a/camera/camera-view/src/main/java/androidx/camera/view/CameraController.java
+++ b/camera/camera-view/src/main/java/androidx/camera/view/CameraController.java
@@ -304,6 +304,9 @@
     private DynamicRange mVideoCaptureDynamicRange = DynamicRange.UNSPECIFIED;
 
     @NonNull
+    private DynamicRange mPreviewDynamicRange = DynamicRange.UNSPECIFIED;
+
+    @NonNull
     private Range<Integer> mVideoCaptureTargetFrameRate = StreamSpec.FRAME_RATE_RANGE_UNSPECIFIED;
 
     // The latest bound camera.
@@ -690,6 +693,46 @@
     }
 
     /**
+     * Sets the {@link DynamicRange} for preview.
+     *
+     * <p>The dynamic range specifies how the range of colors, highlights and shadows that
+     * are displayed on a display. Some dynamic ranges will allow the preview to make full use of
+     * the extended range of brightness of a display.
+     *
+     * <p> The supported dynamic ranges of the camera can be queried using
+     * {@link CameraInfo#querySupportedDynamicRanges(Set)}.
+     *
+     * <p>It is possible to choose a high dynamic range (HDR) with unspecified encoding by providing
+     * {@link DynamicRange#HDR_UNSPECIFIED_10_BIT}. If the dynamic range is not provided, the
+     * default value is {@link DynamicRange#SDR}.
+     *
+     * @see Preview.Builder#setDynamicRange(DynamicRange)
+     *
+     * TODO: make this public in the next release.
+     */
+    @MainThread
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public void setPreviewDynamicRange(@NonNull DynamicRange dynamicRange) {
+        checkMainThread();
+        mPreviewDynamicRange = dynamicRange;
+        unbindPreviewAndRecreate();
+        startCameraAndTrackStates();
+    }
+
+    /**
+     * Gets the {@link DynamicRange} for preview.
+     *
+     * TODO: make this public in the next release.
+     */
+    @MainThread
+    @NonNull
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public DynamicRange getPreviewDynamicRange() {
+        checkMainThread();
+        return mPreviewDynamicRange;
+    }
+
+    /**
      * Unbinds {@link Preview} and recreates with the latest parameters.
      */
     @MainThread
@@ -707,7 +750,7 @@
         Preview.Builder builder = new Preview.Builder();
         setTargetOutputSize(builder, mPreviewTargetSize);
         setResolutionSelector(builder, mPreviewResolutionSelector);
-
+        builder.setDynamicRange(mPreviewDynamicRange);
         return builder.build();
     }
 
diff --git a/camera/camera-view/src/test/java/androidx/camera/view/CameraControllerTest.kt b/camera/camera-view/src/test/java/androidx/camera/view/CameraControllerTest.kt
index 048c05d..8a1ebb0 100644
--- a/camera/camera-view/src/test/java/androidx/camera/view/CameraControllerTest.kt
+++ b/camera/camera-view/src/test/java/androidx/camera/view/CameraControllerTest.kt
@@ -485,6 +485,14 @@
 
     @UiThreadTest
     @Test
+    fun setPreviewDynamicRange() {
+        controller.previewDynamicRange = DynamicRange.HDR10_10_BIT
+        assertThat(controller.previewDynamicRange).isEqualTo(DynamicRange.HDR10_10_BIT)
+        assertThat(controller.mPreview.dynamicRange).isEqualTo(DynamicRange.HDR10_10_BIT)
+    }
+
+    @UiThreadTest
+    @Test
     fun setVideoCaptureFrameRate() {
         controller.videoCaptureTargetFrameRate = Range.create(60, 120)
         assertThat(controller.videoCaptureTargetFrameRate).isEqualTo(Range.create(60, 120))
diff --git a/camera/integration-tests/avsynctestapp/build.gradle b/camera/integration-tests/avsynctestapp/build.gradle
index 1b66787..58084b0 100644
--- a/camera/integration-tests/avsynctestapp/build.gradle
+++ b/camera/integration-tests/avsynctestapp/build.gradle
@@ -61,8 +61,8 @@
 
     // Align dependencies in debugRuntimeClasspath and debugAndroidTestRuntimeClasspath.
     androidTestImplementation("androidx.annotation:annotation-experimental:1.4.0")
-    androidTestImplementation("androidx.annotation:annotation:1.8.0")
-    androidTestImplementation("androidx.lifecycle:lifecycle-common:2.8.2")
+    androidTestImplementation(project(":annotation:annotation"))
+    androidTestImplementation("androidx.lifecycle:lifecycle-common:2.8.3")
 
     // Testing framework
     testImplementation(libs.kotlinCoroutinesTest)
diff --git a/camera/integration-tests/coretestapp/lint-baseline.xml b/camera/integration-tests/coretestapp/lint-baseline.xml
index 2fe575f..821001e 100644
--- a/camera/integration-tests/coretestapp/lint-baseline.xml
+++ b/camera/integration-tests/coretestapp/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.4.0-alpha12" type="baseline" client="gradle" dependencies="false" name="AGP (8.4.0-alpha12)" variant="all" version="8.4.0-alpha12">
+<issues format="6" by="lint 8.6.0-alpha07" type="baseline" client="gradle" dependencies="false" name="AGP (8.6.0-alpha07)" variant="all" version="8.6.0-alpha07">
 
     <issue
         id="BanThreadSleep"
@@ -156,6 +156,42 @@
 
     <issue
         id="RestrictedApiAndroidX"
+        message="FileUtil.writeTextToExternalFile can only be called from within the same library group (referenced groupId=`androidx.camera` from groupId=`androidx.camera.integration-tests`)"
+        errorLine1="            writeTextToExternalFile(text, filename, extension);"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/camera/integration/core/CameraXActivity.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
+        message="FileUtil.writeTextToExternalFile can only be called from within the same library group (referenced groupId=`androidx.camera` from groupId=`androidx.camera.integration-tests`)"
+        errorLine1="            writeTextToExternalFile(text, filename, extension);"
+        errorLine2="                                    ~~~~">
+        <location
+            file="src/main/java/androidx/camera/integration/core/CameraXActivity.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
+        message="FileUtil.writeTextToExternalFile can only be called from within the same library group (referenced groupId=`androidx.camera` from groupId=`androidx.camera.integration-tests`)"
+        errorLine1="            writeTextToExternalFile(text, filename, extension);"
+        errorLine2="                                          ~~~~~~~~">
+        <location
+            file="src/main/java/androidx/camera/integration/core/CameraXActivity.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
+        message="FileUtil.writeTextToExternalFile can only be called from within the same library group (referenced groupId=`androidx.camera` from groupId=`androidx.camera.integration-tests`)"
+        errorLine1="            writeTextToExternalFile(text, filename, extension);"
+        errorLine2="                                                    ~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/camera/integration/core/CameraXActivity.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
         message="Camera.isUseCasesCombinationSupported can only be called from within the same library group (referenced groupId=`androidx.camera` from groupId=`androidx.camera.integration-tests`)"
         errorLine1="        return mCamera.isUseCasesCombinationSupported(buildUseCases().toArray(new UseCase[0]));"
         errorLine2="                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -390,6 +426,141 @@
 
     <issue
         id="RestrictedApiAndroidX"
+        message="FileUtil.getAbsolutePathFromUri can only be called from within the same library group (referenced groupId=`androidx.camera` from groupId=`androidx.camera.integration-tests`)"
+        errorLine1="                getAbsolutePathFromUri(getApplicationContext().getContentResolver(),"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/camera/integration/core/ConcurrentCameraActivity.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
+        message="FileUtil.getAbsolutePathFromUri can only be called from within the same library group (referenced groupId=`androidx.camera` from groupId=`androidx.camera.integration-tests`)"
+        errorLine1="                getAbsolutePathFromUri(getApplicationContext().getContentResolver(),"
+        errorLine2="                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/camera/integration/core/ConcurrentCameraActivity.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
+        message="FileUtil.getAbsolutePathFromUri can only be called from within the same library group (referenced groupId=`androidx.camera` from groupId=`androidx.camera.integration-tests`)"
+        errorLine1="                        MediaStore.Video.Media.EXTERNAL_CONTENT_URI);"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/camera/integration/core/ConcurrentCameraActivity.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
+        message="FileUtil.createParentFolder can only be called from within the same library group (referenced groupId=`androidx.camera` from groupId=`androidx.camera.integration-tests`)"
+        errorLine1="        if (videoFilePath == null || !createParentFolder(videoFilePath)) {"
+        errorLine2="                                      ~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/camera/integration/core/ConcurrentCameraActivity.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
+        message="FileUtil.createParentFolder can only be called from within the same library group (referenced groupId=`androidx.camera` from groupId=`androidx.camera.integration-tests`)"
+        errorLine1="        if (videoFilePath == null || !createParentFolder(videoFilePath)) {"
+        errorLine2="                                                         ~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/camera/integration/core/ConcurrentCameraActivity.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
+        message="FileUtil.getAbsolutePathFromUri can only be called from within the same library group (referenced groupId=`androidx.camera` from groupId=`androidx.camera.integration-tests`)"
+        errorLine1="                        videoFilePath = getAbsolutePathFromUri("
+        errorLine2="                                        ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/camera/integration/core/ConcurrentCameraActivity.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
+        message="FileUtil.getAbsolutePathFromUri can only be called from within the same library group (referenced groupId=`androidx.camera` from groupId=`androidx.camera.integration-tests`)"
+        errorLine1="                                getApplicationContext().getContentResolver(),"
+        errorLine2="                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/camera/integration/core/ConcurrentCameraActivity.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
+        message="FileUtil.getAbsolutePathFromUri can only be called from within the same library group (referenced groupId=`androidx.camera` from groupId=`androidx.camera.integration-tests`)"
+        errorLine1="                                uri"
+        errorLine2="                                ~~~">
+        <location
+            file="src/main/java/androidx/camera/integration/core/ConcurrentCameraActivity.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
+        message="FileUtil.canDeviceWriteToMediaStore can only be called from within the same library group (referenced groupId=`androidx.camera` from groupId=`androidx.camera.integration-tests`)"
+        errorLine1="                    if (canDeviceWriteToMediaStore()) {"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/camera/integration/core/ConcurrentCameraActivity.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
+        message="FileUtil.generateVideoMediaStoreOptions can only be called from within the same library group (referenced groupId=`androidx.camera` from groupId=`androidx.camera.integration-tests`)"
+        errorLine1="                                generateVideoMediaStoreOptions(getContentResolver(), fileName));"
+        errorLine2="                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/camera/integration/core/ConcurrentCameraActivity.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
+        message="FileUtil.generateVideoMediaStoreOptions can only be called from within the same library group (referenced groupId=`androidx.camera` from groupId=`androidx.camera.integration-tests`)"
+        errorLine1="                                generateVideoMediaStoreOptions(getContentResolver(), fileName));"
+        errorLine2="                                                               ~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/camera/integration/core/ConcurrentCameraActivity.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
+        message="FileUtil.generateVideoMediaStoreOptions can only be called from within the same library group (referenced groupId=`androidx.camera` from groupId=`androidx.camera.integration-tests`)"
+        errorLine1="                                generateVideoMediaStoreOptions(getContentResolver(), fileName));"
+        errorLine2="                                                                                     ~~~~~~~~">
+        <location
+            file="src/main/java/androidx/camera/integration/core/ConcurrentCameraActivity.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
+        message="FileUtil.generateVideoFileOutputOptions can only be called from within the same library group (referenced groupId=`androidx.camera` from groupId=`androidx.camera.integration-tests`)"
+        errorLine1="                                this, generateVideoFileOutputOptions(fileName, extension));"
+        errorLine2="                                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/camera/integration/core/ConcurrentCameraActivity.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
+        message="FileUtil.generateVideoFileOutputOptions can only be called from within the same library group (referenced groupId=`androidx.camera` from groupId=`androidx.camera.integration-tests`)"
+        errorLine1="                                this, generateVideoFileOutputOptions(fileName, extension));"
+        errorLine2="                                                                     ~~~~~~~~">
+        <location
+            file="src/main/java/androidx/camera/integration/core/ConcurrentCameraActivity.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
+        message="FileUtil.generateVideoFileOutputOptions can only be called from within the same library group (referenced groupId=`androidx.camera` from groupId=`androidx.camera.integration-tests`)"
+        errorLine1="                                this, generateVideoFileOutputOptions(fileName, extension));"
+        errorLine2="                                                                               ~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/camera/integration/core/ConcurrentCameraActivity.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
         message="TransformUtils.within360 can only be called from within the same library group (referenced groupId=`androidx.camera` from groupId=`androidx.camera.integration-tests`)"
         errorLine1="            return within360((180 - mTextureRotationDegrees) + mSurfaceRotationDegrees);"
         errorLine2="                   ~~~~~~~~~">
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ImageAnalysisTest.kt b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ImageAnalysisTest.kt
index 03b29ead..94f1e7e 100644
--- a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ImageAnalysisTest.kt
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ImageAnalysisTest.kt
@@ -34,6 +34,8 @@
 import androidx.camera.core.ImageProxy
 import androidx.camera.core.impl.ImageOutputConfig
 import androidx.camera.core.impl.ImageOutputConfig.OPTION_RESOLUTION_SELECTOR
+import androidx.camera.core.impl.SessionConfig
+import androidx.camera.core.impl.utils.Threads.runOnMainSync
 import androidx.camera.core.impl.utils.executor.CameraXExecutors
 import androidx.camera.core.internal.utils.SizeUtil
 import androidx.camera.core.resolutionselector.AspectRatioStrategy
@@ -488,6 +490,60 @@
             .isEqualTo(PREFER_HIGHER_RESOLUTION_OVER_CAPTURE_RATE)
     }
 
+    @Test
+    fun analyzerAnalyzesImages_whenSessionErrorListenerReceivesError() = runBlocking {
+        val imageAnalysis = ImageAnalysis.Builder().build()
+        withContext(Dispatchers.Main) {
+            cameraProvider.bindToLifecycle(
+                fakeLifecycleOwner,
+                DEFAULT_CAMERA_SELECTOR,
+                imageAnalysis
+            )
+        }
+
+        imageAnalysis.setAnalyzer(CameraXExecutors.newHandlerExecutor(handler), analyzer)
+        // Retrieves the initial session config
+        val initialSessionConfig = imageAnalysis.sessionConfig
+
+        // Checks that image can be received successfully when onError is received.
+        triggerOnErrorAndVerifyNewImageReceived(initialSessionConfig)
+
+        if (CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_FRONT)) {
+            withContext(Dispatchers.Main) {
+                cameraProvider.unbind(imageAnalysis)
+                cameraProvider.bindToLifecycle(
+                    fakeLifecycleOwner,
+                    CameraSelector.DEFAULT_FRONT_CAMERA,
+                    imageAnalysis
+                )
+            }
+
+            // Checks that image can be received successfully when onError is received by the old
+            // error listener.
+            triggerOnErrorAndVerifyNewImageReceived(initialSessionConfig)
+        }
+
+        // Checks that image can be received successfully when onError is received by the new
+        // error listener.
+        triggerOnErrorAndVerifyNewImageReceived(imageAnalysis.sessionConfig)
+    }
+
+    private fun triggerOnErrorAndVerifyNewImageReceived(sessionConfig: SessionConfig) {
+        // Forces invoke the onError callback
+        runOnMainSync {
+            sessionConfig.errorListener!!.onError(
+                sessionConfig,
+                SessionConfig.SessionError.SESSION_ERROR_UNKNOWN
+            )
+        }
+        // Resets the semaphore
+        analysisResultsSemaphore = Semaphore(0)
+        analysisResultsSemaphore.tryAcquire(5, TimeUnit.SECONDS)
+
+        // Verifies image can be received
+        synchronized(analysisResultLock) { assertThat(analysisResults).isNotEmpty() }
+    }
+
     private data class ImageProperties(
         val resolution: Size,
         val format: Int,
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ImageCaptureTest.kt b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ImageCaptureTest.kt
index b63033e..e752bdb 100644
--- a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ImageCaptureTest.kt
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ImageCaptureTest.kt
@@ -63,6 +63,7 @@
 import androidx.camera.core.impl.ImageOutputConfig
 import androidx.camera.core.impl.ImageOutputConfig.OPTION_RESOLUTION_SELECTOR
 import androidx.camera.core.impl.MutableOptionsBundle
+import androidx.camera.core.impl.SessionConfig
 import androidx.camera.core.impl.SessionProcessor
 import androidx.camera.core.impl.UseCaseConfigFactory
 import androidx.camera.core.impl.utils.CameraOrientationUtil
@@ -423,6 +424,66 @@
     }
 
     @Test
+    fun canTakeImage_whenSessionErrorListenerReceivesError(): Unit = runBlocking {
+        val imageCapture = ImageCapture.Builder().build()
+        // Arrange.
+        withContext(Dispatchers.Main) {
+            cameraProvider.bindToLifecycle(
+                fakeLifecycleOwner,
+                CameraSelector.DEFAULT_BACK_CAMERA,
+                imageCapture
+            )
+        }
+
+        // Retrieves the initial session config
+        val initialSessionConfig = imageCapture.sessionConfig
+
+        // Checks that image can be taken successfully when onError is received.
+        triggerOnErrorAndTakePicture(imageCapture, initialSessionConfig)
+
+        if (CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_FRONT)) {
+            withContext(Dispatchers.Main) {
+                // Binds the ImageCapture use case to the other camera
+                cameraProvider.unbind(imageCapture)
+                cameraProvider.bindToLifecycle(
+                    fakeLifecycleOwner,
+                    CameraSelector.DEFAULT_FRONT_CAMERA,
+                    imageCapture
+                )
+            }
+
+            // Checks that image can be taken successfully when onError is received by the old
+            // error listener.
+            triggerOnErrorAndTakePicture(imageCapture, initialSessionConfig)
+        }
+
+        // Checks that image can be taken successfully when onError is received by the new
+        // error listener.
+        triggerOnErrorAndTakePicture(imageCapture, imageCapture.sessionConfig)
+    }
+
+    private suspend fun triggerOnErrorAndTakePicture(
+        imageCapture: ImageCapture,
+        sessionConfig: SessionConfig
+    ) {
+        withContext(Dispatchers.Main) {
+            // Forces invoke the onError callback
+            sessionConfig.errorListener!!.onError(
+                sessionConfig,
+                SessionConfig.SessionError.SESSION_ERROR_UNKNOWN
+            )
+        }
+
+        // Act.
+        val callback = FakeImageCaptureCallback()
+        imageCapture.takePicture(mainExecutor, callback)
+
+        // Assert.
+        // Image can still be taken when an error reported to the session config error listener
+        callback.awaitCapturesAndAssert(capturedImagesCount = 1)
+    }
+
+    @Test
     fun saveCanSucceed_withNonExistingFile() {
         val saveLocation = temporaryFolder.newFile("test${System.currentTimeMillis()}.jpg")
 
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/StreamSharingTest.kt b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/StreamSharingTest.kt
new file mode 100644
index 0000000..98de967
--- /dev/null
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/StreamSharingTest.kt
@@ -0,0 +1,304 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.integration.core
+
+import android.content.Context
+import android.graphics.SurfaceTexture
+import android.util.Size
+import androidx.camera.camera2.Camera2Config
+import androidx.camera.camera2.pipe.integration.CameraPipeConfig
+import androidx.camera.core.Camera
+import androidx.camera.core.CameraSelector
+import androidx.camera.core.CameraXConfig
+import androidx.camera.core.ImageAnalysis
+import androidx.camera.core.ImageCapture
+import androidx.camera.core.Preview
+import androidx.camera.core.UseCase
+import androidx.camera.core.impl.SessionConfig
+import androidx.camera.core.impl.utils.executor.CameraXExecutors.mainThreadExecutor
+import androidx.camera.core.internal.CameraUseCaseAdapter
+import androidx.camera.core.streamsharing.StreamSharing
+import androidx.camera.lifecycle.LifecycleCamera
+import androidx.camera.lifecycle.ProcessCameraProvider
+import androidx.camera.testing.impl.AndroidUtil.skipVideoRecordingTestIfNotSupportedByEmulator
+import androidx.camera.testing.impl.CameraPipeConfigTestRule
+import androidx.camera.testing.impl.CameraUtil
+import androidx.camera.testing.impl.CameraUtil.PreTestCameraIdList
+import androidx.camera.testing.impl.SurfaceTextureProvider
+import androidx.camera.testing.impl.SurfaceTextureProvider.SurfaceTextureCallback
+import androidx.camera.testing.impl.fakes.FakeLifecycleOwner
+import androidx.camera.video.FileOutputOptions
+import androidx.camera.video.Recorder
+import androidx.camera.video.VideoCapture
+import androidx.camera.video.VideoRecordEvent
+import androidx.core.util.Consumer
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.filters.LargeTest
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.testutils.fail
+import com.google.common.truth.Truth.assertThat
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.Semaphore
+import java.util.concurrent.TimeUnit
+import org.junit.After
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TemporaryFolder
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@LargeTest
+@RunWith(Parameterized::class)
+class StreamSharingTest(private val implName: String, private val cameraConfig: CameraXConfig) {
+    @get:Rule
+    val cameraPipeConfigTestRule =
+        CameraPipeConfigTestRule(
+            active = implName == CameraPipeConfig::class.simpleName,
+        )
+
+    @get:Rule
+    val cameraRule =
+        CameraUtil.grantCameraPermissionAndPreTestAndPostTest(PreTestCameraIdList(cameraConfig))
+
+    @get:Rule
+    val temporaryFolder =
+        TemporaryFolder(ApplicationProvider.getApplicationContext<Context>().cacheDir)
+
+    companion object {
+        private const val VIDEO_TIMEOUT_SEC = 10L
+        private const val TAG = "StreamSharingTest"
+        private val DEFAULT_CAMERA_SELECTOR = CameraSelector.DEFAULT_BACK_CAMERA
+
+        @JvmStatic
+        @Parameterized.Parameters(name = "{0}")
+        fun data() =
+            listOf(
+                arrayOf(Camera2Config::class.simpleName, Camera2Config.defaultConfig()),
+                arrayOf(CameraPipeConfig::class.simpleName, CameraPipeConfig.defaultConfig())
+            )
+    }
+
+    private val instrumentation = InstrumentationRegistry.getInstrumentation()
+    private val context: Context = ApplicationProvider.getApplicationContext()
+    private lateinit var cameraProvider: ProcessCameraProvider
+    private var surfaceFutureSemaphore: Semaphore = Semaphore(0)
+
+    @Before
+    fun setUp() {
+        assumeTrue(CameraUtil.hasCameraWithLensFacing(DEFAULT_CAMERA_SELECTOR.lensFacing!!))
+        skipVideoRecordingTestIfNotSupportedByEmulator()
+        ProcessCameraProvider.configureInstance(cameraConfig)
+        cameraProvider = ProcessCameraProvider.getInstance(context)[10, TimeUnit.SECONDS]
+    }
+
+    @After
+    fun tearDown() {
+        if (::cameraProvider.isInitialized) {
+            cameraProvider.shutdownAsync()[10, TimeUnit.SECONDS]
+        }
+    }
+
+    @Test
+    fun previewAndRecordingCanProceedAfterSessionError() {
+        val recorder = Recorder.Builder().build()
+        val videoCapture = VideoCapture.withOutput(recorder)
+        val preview = Preview.Builder().build()
+        val imageAnalysis = ImageAnalysis.Builder().build()
+        val imageCapture = ImageCapture.Builder().build()
+        val useCases = arrayOf(videoCapture, preview, imageAnalysis, imageCapture)
+
+        instrumentation.runOnMainSync {
+            // Sets surface provider to preview
+            preview.surfaceProvider = getSurfaceProvider()
+        }
+
+        // Checks whether the back camera can support four UseCases combination
+        val cameraUseCaseAdapter =
+            checkStreamSharingSupportAndRetrieveCameraUseCaseAdapter(
+                DEFAULT_CAMERA_SELECTOR,
+                useCases
+            )
+        assumeTrue(cameraUseCaseAdapter != null)
+
+        // Checks whether stream sharing is actually enabled
+        var streamSharing = retrieveStreamSharing(cameraUseCaseAdapter!!.cameraUseCases)
+        assumeTrue(streamSharing != null)
+
+        // Verifies preview and recording before triggering onError event
+        verifyPreviewImageReceivedAndRecording(videoCapture)
+
+        // Retrieves the initial session config
+        var sessionConfig = streamSharing!!.sessionConfig
+
+        // Verifies preview and recording after triggering onError event
+        triggerErrorAndVerifyPreviewImageReceivedAndRecording(sessionConfig, videoCapture)
+
+        val frontCameraUseCaseAdapter =
+            if (CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_FRONT)) {
+                checkStreamSharingSupportAndRetrieveCameraUseCaseAdapter(
+                    CameraSelector.DEFAULT_FRONT_CAMERA,
+                    useCases
+                )
+            } else {
+                null
+            }
+
+        // Rebinds to different camera
+        frontCameraUseCaseAdapter?.let {
+            // Checks whether stream sharing is actually enabled
+            streamSharing = retrieveStreamSharing(it.cameraUseCases)
+            assumeTrue(streamSharing != null)
+
+            // Verifies preview and recording after triggering onError event to the closed error
+            // listener
+            triggerErrorAndVerifyPreviewImageReceivedAndRecording(sessionConfig, videoCapture)
+        }
+
+        // Update the session config
+        sessionConfig = streamSharing!!.sessionConfig
+
+        // Verifies preview and recording after triggering onError event to the new active error
+        // listener
+        triggerErrorAndVerifyPreviewImageReceivedAndRecording(sessionConfig, videoCapture)
+    }
+
+    private fun checkStreamSharingSupportAndRetrieveCameraUseCaseAdapter(
+        cameraSelector: CameraSelector,
+        useCases: Array<UseCase>
+    ): CameraUseCaseAdapter? {
+        lateinit var lifecycleOwner: FakeLifecycleOwner
+        lateinit var camera: Camera
+
+        instrumentation.runOnMainSync {
+            lifecycleOwner = FakeLifecycleOwner().apply { startAndResume() }
+            camera = cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector)
+        }
+
+        // Checks whether the camera can support the UseCases combination only when stream sharing
+        // is enabled
+        if (
+            camera.isUseCasesCombinationSupported(false, *useCases) ||
+                !camera.isUseCasesCombinationSupported(true, *useCases)
+        ) {
+            return null
+        }
+
+        instrumentation.runOnMainSync {
+            cameraProvider.unbindAll()
+            cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, *useCases)
+        }
+
+        return (camera as LifecycleCamera).cameraUseCaseAdapter
+    }
+
+    private fun getSurfaceProvider(): Preview.SurfaceProvider {
+        return SurfaceTextureProvider.createSurfaceTextureProvider(
+            object : SurfaceTextureCallback {
+                override fun onSurfaceTextureReady(
+                    surfaceTexture: SurfaceTexture,
+                    resolution: Size
+                ) {
+                    // Note that the onSurfaceTextureReady will only be received once since
+                    // surfaceTexture.updateTexImage() isn't invoked here. Therefore,
+                    // surfaceFutureSemaphore will also only be released once. This is to simplify
+                    // the preview related test. Otherwise, the test need to make sure that the
+                    // previous preview stream has been stopped and then renew the semaphore to
+                    // monitor the new preview stream is started successfully.
+                    surfaceTexture.setOnFrameAvailableListener { surfaceFutureSemaphore.release() }
+                }
+
+                override fun onSafeToRelease(surfaceTexture: SurfaceTexture) {
+                    surfaceTexture.release()
+                }
+            }
+        )
+    }
+
+    private fun retrieveStreamSharing(useCases: Iterable<UseCase>): StreamSharing? =
+        useCases.filterIsInstance<StreamSharing>().firstOrNull()
+
+    private fun verifyPreviewImageReceivedAndRecording(videoCapture: VideoCapture<Recorder>) {
+        // Verify. preview image can be received
+        verifyPreviewStreaming()
+        // Verify. recording can work successfully
+        startAndVerifyVideoRecording(videoCapture)
+    }
+
+    private fun triggerErrorAndVerifyPreviewImageReceivedAndRecording(
+        sessionConfig: SessionConfig,
+        videoCapture: VideoCapture<Recorder>
+    ) {
+        // This should be reset before onError is invoked to make sure that the semaphore can be
+        // successfully released by the onSurfaceTextureReady + onFrameAvailable events
+        surfaceFutureSemaphore = Semaphore(0)
+
+        instrumentation.runOnMainSync {
+            sessionConfig.errorListener!!.onError(
+                sessionConfig,
+                SessionConfig.SessionError.SESSION_ERROR_UNKNOWN
+            )
+        }
+
+        // Verify. preview image can be received
+        verifyPreviewStreaming()
+        // Verify. recording can work successfully
+        startAndVerifyVideoRecording(videoCapture)
+    }
+
+    private fun verifyPreviewStreaming() {
+        assertThat(surfaceFutureSemaphore.tryAcquire(10, TimeUnit.SECONDS)).isTrue()
+    }
+
+    private fun startAndVerifyVideoRecording(videoCapture: VideoCapture<Recorder>) {
+        val latchForVideoSaved = CountDownLatch(1)
+        val latchForVideoRecording = CountDownLatch(5)
+        val videoRecordEventListener =
+            Consumer<VideoRecordEvent> {
+                when (it) {
+                    is VideoRecordEvent.Finalize -> {
+                        latchForVideoSaved.countDown()
+                    }
+                    is VideoRecordEvent.Status -> {
+                        latchForVideoRecording.countDown()
+                    }
+                }
+            }
+        val fileOutputOptions = FileOutputOptions.Builder(temporaryFolder.newFile()).build()
+        val recording =
+            videoCapture.output
+                .prepareRecording(context, fileOutputOptions)
+                .start(mainThreadExecutor(), videoRecordEventListener)
+
+        try {
+            // Wait for status event to proceed recording for a while.
+            assertThat(latchForVideoRecording.await(VIDEO_TIMEOUT_SEC, TimeUnit.SECONDS)).isTrue()
+        } catch (ex: Exception) {
+            fail("Recording has started, but timed out for Status update.")
+        } finally {
+            recording.stop()
+        }
+
+        try {
+            // Wait for finalize event to saved file.
+            assertThat(latchForVideoSaved.await(VIDEO_TIMEOUT_SEC, TimeUnit.SECONDS)).isTrue()
+        } catch (ex: Exception) {
+            fail("Recording has stopped, but timed out for Finalize event.")
+        }
+    }
+}
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/camera2/PreviewTest.kt b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/camera2/PreviewTest.kt
index 52bb952..64e1b98 100644
--- a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/camera2/PreviewTest.kt
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/camera2/PreviewTest.kt
@@ -32,6 +32,8 @@
 import androidx.camera.core.UseCase
 import androidx.camera.core.impl.ImageOutputConfig
 import androidx.camera.core.impl.ImageOutputConfig.OPTION_RESOLUTION_SELECTOR
+import androidx.camera.core.impl.SessionConfig
+import androidx.camera.core.impl.utils.Threads.runOnMainSync
 import androidx.camera.core.impl.utils.executor.CameraXExecutors
 import androidx.camera.core.internal.CameraUseCaseAdapter
 import androidx.camera.core.resolutionselector.AspectRatioStrategy
@@ -63,7 +65,9 @@
 import java.util.concurrent.TimeoutException
 import java.util.concurrent.atomic.AtomicReference
 import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.withContext
 import kotlinx.coroutines.withTimeout
 import org.junit.After
 import org.junit.Assume
@@ -655,6 +659,60 @@
             .isEqualTo(PREFER_HIGHER_RESOLUTION_OVER_CAPTURE_RATE)
     }
 
+    @Test
+    fun sessionErrorListenerReceivesError_getsFrame(): Unit = runBlocking {
+        // Arrange.
+        val preview = defaultBuilder!!.build()
+        camera = CameraUtil.createCameraAndAttachUseCase(context!!, cameraSelector, preview)
+
+        // Act.
+        // TODO(b/160261462) move off of main thread when setSurfaceProvider does not need to be
+        //  done on the main thread
+        withContext(Dispatchers.Main) { preview.surfaceProvider = getSurfaceProvider(null) }
+
+        // Retrieves the initial session config
+        val initialSessionConfig = preview.sessionConfig
+
+        // Checks that image can be received successfully when onError is received.
+        triggerOnErrorAndVerifyNewImageReceived(initialSessionConfig)
+
+        // Rebinds to different camera
+        if (CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_FRONT)) {
+            withContext(Dispatchers.Main) { camera!!.removeUseCases(setOf(preview)) }
+            camera =
+                CameraUtil.createCameraAndAttachUseCase(
+                    context!!,
+                    CameraSelector.DEFAULT_FRONT_CAMERA,
+                    preview
+                )
+
+            // Checks that image can be received successfully when onError is received by the old
+            // error listener.
+            triggerOnErrorAndVerifyNewImageReceived(initialSessionConfig)
+        }
+
+        val sessionConfigBeforeValidErrorNotification = preview.sessionConfig
+        // Checks that image can be received successfully when onError is received by the new
+        // error listener.
+        triggerOnErrorAndVerifyNewImageReceived(preview.sessionConfig)
+        // Checks that triggering onError to valid listener has recreated the pipeline
+        Truth.assertThat(preview.sessionConfig)
+            .isNotEqualTo(sessionConfigBeforeValidErrorNotification)
+    }
+
+    private fun triggerOnErrorAndVerifyNewImageReceived(sessionConfig: SessionConfig) {
+        surfaceFutureSemaphore = Semaphore(0)
+        // Forces invoke the onError callback
+        runOnMainSync {
+            sessionConfig.errorListener!!.onError(
+                sessionConfig,
+                SessionConfig.SessionError.SESSION_ERROR_UNKNOWN
+            )
+        }
+        // Assert.
+        Truth.assertThat(surfaceFutureSemaphore!!.tryAcquire(10, TimeUnit.SECONDS)).isTrue()
+    }
+
     private val workExecutorWithNamedThread: Executor
         get() {
             val threadFactory = ThreadFactory { runnable: Runnable? ->
diff --git a/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/CameraXActivity.java b/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/CameraXActivity.java
index fd13201..62f607a 100644
--- a/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/CameraXActivity.java
+++ b/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/CameraXActivity.java
@@ -16,6 +16,8 @@
 
 package androidx.camera.integration.core;
 
+import static android.os.Environment.getExternalStoragePublicDirectory;
+
 import static androidx.camera.core.ImageCapture.ERROR_CAMERA_CLOSED;
 import static androidx.camera.core.ImageCapture.ERROR_CAPTURE_FAILED;
 import static androidx.camera.core.ImageCapture.ERROR_FILE_IO;
@@ -36,6 +38,7 @@
 import static androidx.camera.testing.impl.FileUtil.generateVideoFileOutputOptions;
 import static androidx.camera.testing.impl.FileUtil.generateVideoMediaStoreOptions;
 import static androidx.camera.testing.impl.FileUtil.getAbsolutePathFromUri;
+import static androidx.camera.testing.impl.FileUtil.writeTextToExternalFile;
 import static androidx.camera.video.VideoRecordEvent.Finalize.ERROR_DURATION_LIMIT_REACHED;
 import static androidx.camera.video.VideoRecordEvent.Finalize.ERROR_FILE_SIZE_LIMIT_REACHED;
 import static androidx.camera.video.VideoRecordEvent.Finalize.ERROR_INSUFFICIENT_STORAGE;
@@ -156,10 +159,7 @@
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 
-import java.io.BufferedWriter;
 import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
 import java.text.Format;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
@@ -249,6 +249,8 @@
     private static final String INTENT_EXTRA_E2E_TEST_CASE = "e2e_test_case";
     // Launch the activity with the specified video quality.
     private static final String INTENT_EXTRA_VIDEO_QUALITY = "video_quality";
+    // Launch the activity with the view finder position log into a text file.
+    private static final String INTENT_EXTRA_LOG_VIEWFINDER_POSITION = "log_view_finder_position";
     // Launch the activity with the specified video mirror mode.
     private static final String INTENT_EXTRA_VIDEO_MIRROR_MODE = "video_mirror_mode";
     public static final String INTENT_EXTRA_CAMERA_IMPLEMENTATION = "camera_implementation";
@@ -1488,17 +1490,17 @@
                         return;
                     }
 
-                    String testCase = bundle.getString(INTENT_EXTRA_E2E_TEST_CASE);
-                    if (!Objects.equals(testCase, PREVIEW_TEST_CASE)) {
+                    if (!bundle.getBoolean(INTENT_EXTRA_LOG_VIEWFINDER_POSITION)) {
                         return;
                     }
 
                     Rect rect = new Rect();
                     v.getGlobalVisibleRect(rect);
+
                     String viewFinderPositionText =
                             rect.left + "," + rect.top + "," + rect.right + "," + rect.bottom;
-                    writeTextToExternalCache(viewFinderPositionText,
-                            "camerax_view_finder_position.txt");
+                    String fileName = "camerax_view_finder_position_" + System.currentTimeMillis();
+                    writeTextToExternalStorage(viewFinderPositionText, fileName, "txt");
                 });
 
         mVideoToggle = findViewById(R.id.VideoToggle);
@@ -1652,18 +1654,12 @@
     }
 
     /**
-     * Writes text data to a cache file in primary external directory for reading during tests.
+     * Writes text data to a file in public external directory for reading during tests.
      */
-    private void writeTextToExternalCache(@NonNull String text, @NonNull String filename) {
+    private void writeTextToExternalStorage(@NonNull String text, @NonNull String filename,
+            @NonNull String extension) {
         mFileWriterExecutorService.execute(() -> {
-            File outputFile = new File(getExternalCacheDir(), filename);
-
-            try (BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile))) {
-                writer.write(text);
-                Log.d(TAG, "Wrote [" + text + "] to " + outputFile);
-            } catch (IOException e) {
-                Log.e(TAG, "writeViewFinderPositionToFile: failed to write to " + outputFile, e);
-            }
+            writeTextToExternalFile(text, filename, extension);
         });
     }
 
@@ -1999,8 +1995,7 @@
     }
 
     void createDefaultPictureFolderIfNotExist() {
-        File pictureFolder = Environment.getExternalStoragePublicDirectory(
-                Environment.DIRECTORY_PICTURES);
+        File pictureFolder = getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
         if (createFolder(pictureFolder)) {
             Log.e(TAG, "Failed to create directory: " + pictureFolder);
         }
diff --git a/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/ConcurrentCameraActivity.java b/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/ConcurrentCameraActivity.java
index 5421e2f..9a3ec50 100644
--- a/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/ConcurrentCameraActivity.java
+++ b/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/ConcurrentCameraActivity.java
@@ -20,23 +20,47 @@
 import static android.view.View.GONE;
 import static android.view.View.VISIBLE;
 
+import static androidx.camera.testing.impl.FileUtil.canDeviceWriteToMediaStore;
+import static androidx.camera.testing.impl.FileUtil.createParentFolder;
+import static androidx.camera.testing.impl.FileUtil.generateVideoFileOutputOptions;
+import static androidx.camera.testing.impl.FileUtil.generateVideoMediaStoreOptions;
+import static androidx.camera.testing.impl.FileUtil.getAbsolutePathFromUri;
+import static androidx.camera.video.VideoRecordEvent.Finalize.ERROR_DURATION_LIMIT_REACHED;
+import static androidx.camera.video.VideoRecordEvent.Finalize.ERROR_FILE_SIZE_LIMIT_REACHED;
+import static androidx.camera.video.VideoRecordEvent.Finalize.ERROR_INSUFFICIENT_STORAGE;
+import static androidx.camera.video.VideoRecordEvent.Finalize.ERROR_NONE;
+import static androidx.camera.video.VideoRecordEvent.Finalize.ERROR_SOURCE_INACTIVE;
+
+import static java.util.Objects.requireNonNull;
+
 import android.annotation.SuppressLint;
 import android.content.pm.PackageManager;
 import android.hardware.camera2.CameraCharacteristics;
+import android.media.MediaScannerConnection;
+import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
+import android.provider.MediaStore;
+import android.util.Log;
+import android.view.Menu;
 import android.view.MotionEvent;
 import android.view.ScaleGestureDetector;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.Button;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
+import android.widget.PopupMenu;
+import android.widget.TextView;
 import android.widget.Toast;
 import android.widget.ToggleButton;
 
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.activity.result.contract.ActivityResultContracts;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.OptIn;
+import androidx.annotation.UiThread;
 import androidx.appcompat.app.AppCompatActivity;
 import androidx.camera.camera2.interop.ExperimentalCamera2Interop;
 import androidx.camera.camera2.pipe.integration.CameraPipeConfig;
@@ -46,36 +70,70 @@
 import androidx.camera.core.CameraSelector;
 import androidx.camera.core.ConcurrentCamera;
 import androidx.camera.core.ConcurrentCamera.SingleCameraConfig;
+import androidx.camera.core.DynamicRange;
+import androidx.camera.core.ExperimentalCameraInfo;
 import androidx.camera.core.ExperimentalMirrorMode;
 import androidx.camera.core.FocusMeteringAction;
+import androidx.camera.core.LayoutSettings;
 import androidx.camera.core.MeteringPoint;
 import androidx.camera.core.MirrorMode;
 import androidx.camera.core.Preview;
 import androidx.camera.core.UseCaseGroup;
 import androidx.camera.lifecycle.ExperimentalCameraProviderConfiguration;
 import androidx.camera.lifecycle.ProcessCameraProvider;
+import androidx.camera.video.ExperimentalPersistentRecording;
+import androidx.camera.video.FileOutputOptions;
+import androidx.camera.video.MediaStoreOutputOptions;
+import androidx.camera.video.OutputOptions;
+import androidx.camera.video.PendingRecording;
+import androidx.camera.video.Quality;
+import androidx.camera.video.QualitySelector;
+import androidx.camera.video.Recorder;
+import androidx.camera.video.Recording;
+import androidx.camera.video.RecordingStats;
+import androidx.camera.video.VideoCapabilities;
+import androidx.camera.video.VideoCapture;
+import androidx.camera.video.VideoRecordEvent;
 import androidx.camera.view.PreviewView;
-import androidx.core.app.ActivityCompat;
 import androidx.core.content.ContextCompat;
 import androidx.core.math.MathUtils;
+import androidx.core.util.Consumer;
 import androidx.lifecycle.LifecycleOwner;
+import androidx.test.espresso.idling.CountingIdlingResource;
 
 import com.google.common.base.Objects;
 import com.google.common.collect.ImmutableList;
 import com.google.common.util.concurrent.ListenableFuture;
 
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+
 /**
  * Concurrent camera activity.
  */
 public class ConcurrentCameraActivity extends AppCompatActivity {
-    private static final String TAG = "ConcurrentCameraActivity";
+    private static final String TAG = "ConcurrentCamera";
     private static final int REQUEST_CODE_PERMISSIONS = 1001;
     private static final String[] REQUIRED_PERMISSIONS = new String[] {
             "android.permission.CAMERA"
     };
 
+    // For Video Capture
+    private RecordUi mRecordUi;
+    private VideoCapture<Recorder> mVideoCapture;
+    private final CountingIdlingResource mVideoSavedIdlingResource =
+            new CountingIdlingResource("videosaved");
+    private Recording mActiveRecording;
+    private long mVideoCaptureAutoStopLength = 0;
+    private SessionMediaUriSet
+            mSessionVideosUriSet = new SessionMediaUriSet();
+    private static final Quality QUALITY_AUTO = null;
+    private Quality mVideoQuality;
+
     @NonNull private PreviewView mSinglePreviewView;
     @NonNull private PreviewView mFrontPreviewView;
     @NonNull private PreviewView mBackPreviewView;
@@ -87,6 +145,7 @@
     @NonNull private ToggleButton mLayoutButton;
     @NonNull private ToggleButton mToggleButton;
     @NonNull private ToggleButton mDualSelfieButton;
+    @NonNull private ToggleButton mDualRecordButton;
     @NonNull private LinearLayout mSideBySideLayout;
     @NonNull private FrameLayout mPiPLayout;
     @Nullable private ProcessCameraProvider mCameraProvider;
@@ -94,6 +153,7 @@
     private boolean mIsLayoutPiP = true;
     private boolean mIsFrontPrimary = true;
     private boolean mIsDualSelfieEnabled = false;
+    private boolean mIsDualRecordEnabled = false;
     private boolean mIsCameraPipeEnabled = false;
 
     @Override
@@ -111,6 +171,22 @@
         mLayoutButton = findViewById(R.id.layout_button);
         mToggleButton = findViewById(R.id.toggle_button);
         mDualSelfieButton = findViewById(R.id.dual_selfie);
+        mDualRecordButton = findViewById(R.id.dual_record);
+
+        Recorder recorder = new Recorder.Builder()
+                .setQualitySelector(QualitySelector.from(Quality.HD))
+                .build();
+        mVideoCapture = new VideoCapture.Builder<>(recorder)
+                .setMirrorMode(MirrorMode.MIRROR_MODE_ON_FRONT_ONLY)
+                .build();
+        mRecordUi = new RecordUi(
+                findViewById(R.id.Video),
+                findViewById(R.id.video_pause),
+                findViewById(R.id.video_stats),
+                findViewById(R.id.video_quality),
+                findViewById(R.id.video_persistent),
+                (newState) -> {});
+        setUpRecordButton();
 
         boolean isConcurrentCameraSupported =
                 getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_CONCURRENT);
@@ -134,6 +210,8 @@
                 mIsConcurrentModeOn = false;
                 mIsDualSelfieEnabled = false;
                 mDualSelfieButton.setChecked(false);
+                mIsDualRecordEnabled = false;
+                mDualRecordButton.setChecked(false);
             } else {
                 mIsLayoutPiP = true;
                 bindPreviewForPiP(mCameraProvider);
@@ -165,14 +243,12 @@
             mIsDualSelfieEnabled = mDualSelfieButton.isChecked();
             mDualSelfieButton.setChecked(mIsDualSelfieEnabled);
         });
-        if (allPermissionsGranted()) {
-            if (mCameraProvider != null) {
-                mCameraProvider.unbindAll();
-            }
-            startCamera();
-        } else {
-            ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS);
-        }
+        mDualRecordButton.setOnClickListener(view -> {
+            mIsDualRecordEnabled = mDualRecordButton.isChecked();
+            mDualRecordButton.setChecked(mIsDualRecordEnabled);
+        });
+
+        setupPermissions();
     }
 
     @SuppressLint("NullAnnotationGroup")
@@ -201,6 +277,9 @@
         mFrontPreviewViewForPip.setVisibility(VISIBLE);
         mBackPreviewViewForPip.setVisibility(GONE);
         mPiPLayout.setVisibility(VISIBLE);
+        mToggleButton.setVisibility(VISIBLE);
+        mLayoutButton.setVisibility(VISIBLE);
+        mRecordUi.hideUi();
         // Front
         mSinglePreviewView = new PreviewView(this);
         mSinglePreviewView.setImplementationMode(PreviewView.ImplementationMode.COMPATIBLE);
@@ -216,7 +295,9 @@
                 this, cameraSelectorFront, previewFront);
         mDualSelfieButton.setVisibility(camera.getCameraInfo().isLogicalMultiCameraSupported()
                 ? VISIBLE : GONE);
+        mDualRecordButton.setVisibility(VISIBLE);
         mIsDualSelfieEnabled = false;
+        mIsDualRecordEnabled = false;
         setupZoomAndTapToFocus(camera, mSinglePreviewView);
     }
 
@@ -226,6 +307,14 @@
         mBackPreviewViewForPip.setVisibility(VISIBLE);
         mPiPLayout.setVisibility(VISIBLE);
         mDualSelfieButton.setVisibility(GONE);
+        mDualRecordButton.setVisibility(GONE);
+        if (mIsDualRecordEnabled) {
+            mRecordUi.showUi();
+        } else {
+            mRecordUi.hideUi();
+        }
+        mToggleButton.setVisibility(mIsDualRecordEnabled ? GONE : VISIBLE);
+        mLayoutButton.setVisibility(mIsDualRecordEnabled ? GONE : VISIBLE);
         if (mFrontPreviewView == null && mBackPreviewView == null) {
             // Front
             mFrontPreviewView = new PreviewView(this);
@@ -275,7 +364,7 @@
                 mBackPreviewView);
     }
 
-    @SuppressLint("NullAnnotationGroup")
+    @SuppressLint({"NullAnnotationGroup", "RestrictedApiAndroidX"})
     @OptIn(markerClass = {ExperimentalCamera2Interop.class, ExperimentalMirrorMode.class,
             androidx.camera.camera2.pipe.integration.interop.ExperimentalCamera2Interop.class})
     private void bindToLifecycleForConcurrentCamera(
@@ -371,29 +460,66 @@
             if (cameraSelectorPrimary == null || cameraSelectorSecondary == null) {
                 return;
             }
-            Preview previewFront = new Preview.Builder()
-                    .build();
-            previewFront.setSurfaceProvider(frontPreviewView.getSurfaceProvider());
-            SingleCameraConfig primary = new SingleCameraConfig(
-                    cameraSelectorPrimary,
-                    new UseCaseGroup.Builder()
-                            .addUseCase(previewFront)
-                            .build(),
-                    lifecycleOwner);
-            Preview previewBack = new Preview.Builder()
-                    .build();
-            previewBack.setSurfaceProvider(backPreviewView.getSurfaceProvider());
-            SingleCameraConfig secondary = new SingleCameraConfig(
-                    cameraSelectorSecondary,
-                    new UseCaseGroup.Builder()
-                            .addUseCase(previewBack)
-                            .build(),
-                    lifecycleOwner);
-            ConcurrentCamera concurrentCamera =
-                    cameraProvider.bindToLifecycle(ImmutableList.of(primary, secondary));
+            if (mIsDualRecordEnabled) {
+                mFrontPreviewViewForPip.removeAllViews();
+                mFrontPreviewViewForPip.addView(mSinglePreviewView);
+                mBackPreviewViewForPip.setVisibility(GONE);
+                Preview preview = new Preview.Builder()
+                        .build();
+                preview.setSurfaceProvider(mSinglePreviewView.getSurfaceProvider());
+                UseCaseGroup useCaseGroup = new UseCaseGroup.Builder()
+                        .addUseCase(preview)
+                        .addUseCase(mVideoCapture)
+                        .build();
+                // PiP
+                SingleCameraConfig primary = new SingleCameraConfig(
+                        cameraSelectorPrimary,
+                        useCaseGroup,
+                        new LayoutSettings.Builder()
+                                .setAlpha(1.0f)
+                                .setOffsetX(0.0f)
+                                .setOffsetY(0.0f)
+                                .setWidth(1.0f)
+                                .setHeight(1.0f)
+                                .build(),
+                        lifecycleOwner);
+                SingleCameraConfig secondary = new SingleCameraConfig(
+                        cameraSelectorSecondary,
+                        useCaseGroup,
+                        new LayoutSettings.Builder()
+                                .setAlpha(1.0f)
+                                .setOffsetX(-0.3f)
+                                .setOffsetY(-0.4f)
+                                .setWidth(0.3f)
+                                .setHeight(0.3f)
+                                .build(),
+                        lifecycleOwner);
+                cameraProvider.bindToLifecycle(ImmutableList.of(primary, secondary));
+            } else {
+                Preview previewFront = new Preview.Builder()
+                        .build();
+                previewFront.setSurfaceProvider(frontPreviewView.getSurfaceProvider());
+                SingleCameraConfig primary = new SingleCameraConfig(
+                        cameraSelectorPrimary,
+                        new UseCaseGroup.Builder()
+                                .addUseCase(previewFront)
+                                .build(),
+                        lifecycleOwner);
+                Preview previewBack = new Preview.Builder()
+                        .build();
+                previewBack.setSurfaceProvider(backPreviewView.getSurfaceProvider());
+                SingleCameraConfig secondary = new SingleCameraConfig(
+                        cameraSelectorSecondary,
+                        new UseCaseGroup.Builder()
+                                .addUseCase(previewBack)
+                                .build(),
+                        lifecycleOwner);
+                ConcurrentCamera concurrentCamera =
+                        cameraProvider.bindToLifecycle(ImmutableList.of(primary, secondary));
 
-            setupZoomAndTapToFocus(concurrentCamera.getCameras().get(0), frontPreviewView);
-            setupZoomAndTapToFocus(concurrentCamera.getCameras().get(1), backPreviewView);
+                setupZoomAndTapToFocus(concurrentCamera.getCameras().get(0), frontPreviewView);
+                setupZoomAndTapToFocus(concurrentCamera.getCameras().get(1), backPreviewView);
+            }
         }
     }
 
@@ -507,4 +633,450 @@
             }
         }
     }
+
+    private boolean isPermissionMissing() {
+        for (String permission : REQUIRED_PERMISSIONS) {
+            if (ContextCompat.checkSelfPermission(this, permission)
+                    != PackageManager.PERMISSION_GRANTED) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private void setupPermissions() {
+        if (isPermissionMissing()) {
+            ActivityResultLauncher<String[]> permissionLauncher =
+                    registerForActivityResult(
+                            new ActivityResultContracts.RequestMultiplePermissions(),
+                            result -> {
+                                for (String permission : REQUIRED_PERMISSIONS) {
+                                    if (!requireNonNull(result.get(permission))) {
+                                        Toast.makeText(getApplicationContext(),
+                                                        "Camera permission denied.",
+                                                        Toast.LENGTH_SHORT)
+                                                .show();
+                                        finish();
+                                        return;
+                                    }
+                                }
+                                startCamera();
+                            });
+
+            permissionLauncher.launch(REQUIRED_PERMISSIONS);
+        } else {
+            // Permissions already granted. Start camera.
+            startCamera();
+        }
+    }
+
+    private void createDefaultVideoFolderIfNotExist() {
+        String videoFilePath =
+                getAbsolutePathFromUri(getApplicationContext().getContentResolver(),
+                        MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
+        if (videoFilePath == null || !createParentFolder(videoFilePath)) {
+            Log.e(TAG, "Failed to create parent directory for: " + videoFilePath);
+        }
+    }
+
+    private void resetVideoSavedIdlingResource() {
+        // Make the video saved idling resource non-idle, until required video length recorded.
+        if (mVideoSavedIdlingResource.isIdleNow()) {
+            mVideoSavedIdlingResource.increment();
+        }
+    }
+
+    private boolean isPersistentRecordingEnabled() {
+        return mRecordUi.getButtonPersistent().isChecked();
+    }
+
+    private void updateRecordingStats(@NonNull RecordingStats stats) {
+        double durationMs = TimeUnit.NANOSECONDS.toMillis(stats.getRecordedDurationNanos());
+        // Show megabytes in International System of Units (SI)
+        double sizeMb = stats.getNumBytesRecorded() / (1000d * 1000d);
+        String msg = String.format("%.2f sec\n%.2f MB", durationMs / 1000d, sizeMb);
+        mRecordUi.getTextStats().setText(msg);
+
+        if (mVideoCaptureAutoStopLength > 0 && durationMs >= mVideoCaptureAutoStopLength
+                && mRecordUi.getState() == RecordUi.State.RECORDING) {
+            mRecordUi.getButtonRecord().callOnClick();
+        }
+    }
+
+    private void updateVideoSavedSessionData(@NonNull Uri uri) {
+        if (mSessionVideosUriSet != null) {
+            mSessionVideosUriSet.add(uri);
+        }
+
+        if (!mVideoSavedIdlingResource.isIdleNow()) {
+            mVideoSavedIdlingResource.decrement();
+        }
+    }
+
+    private final Consumer<VideoRecordEvent> mVideoRecordEventListener = event -> {
+        updateRecordingStats(event.getRecordingStats());
+
+        if (event instanceof VideoRecordEvent.Finalize) {
+            VideoRecordEvent.Finalize finalize = (VideoRecordEvent.Finalize) event;
+
+            switch (finalize.getError()) {
+                case ERROR_NONE:
+                case ERROR_FILE_SIZE_LIMIT_REACHED:
+                case ERROR_DURATION_LIMIT_REACHED:
+                case ERROR_INSUFFICIENT_STORAGE:
+                case ERROR_SOURCE_INACTIVE:
+                    Uri uri = finalize.getOutputResults().getOutputUri();
+                    OutputOptions outputOptions = finalize.getOutputOptions();
+                    String msg;
+                    String videoFilePath;
+                    if (outputOptions instanceof MediaStoreOutputOptions) {
+                        msg = "Saved uri " + uri;
+                        videoFilePath = getAbsolutePathFromUri(
+                                getApplicationContext().getContentResolver(),
+                                uri
+                        );
+                        updateVideoSavedSessionData(uri);
+                    } else if (outputOptions instanceof FileOutputOptions) {
+                        videoFilePath = ((FileOutputOptions) outputOptions).getFile().getPath();
+                        MediaScannerConnection.scanFile(this,
+                                new String[]{videoFilePath}, null,
+                                (path, uri1) -> {
+                                    Log.i(TAG, "Scanned " + path + " -> uri= " + uri1);
+                                    updateVideoSavedSessionData(uri1);
+                                });
+                        msg = "Saved file " + videoFilePath;
+                    } else {
+                        throw new AssertionError("Unknown or unsupported OutputOptions type: "
+                                + outputOptions.getClass().getSimpleName());
+                    }
+                    // The video file path is used in tracing e2e test log. Don't remove it.
+                    Log.d(TAG, "Saved video file: " + videoFilePath);
+
+                    if (finalize.getError() != ERROR_NONE) {
+                        msg += " with code (" + finalize.getError() + ")";
+                    }
+                    Log.d(TAG, msg, finalize.getCause());
+                    Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
+                    break;
+                default:
+                    String errMsg = "Video capture failed by (" + finalize.getError() + "): "
+                            + finalize.getCause();
+                    Log.e(TAG, errMsg, finalize.getCause());
+                    Toast.makeText(this, errMsg, Toast.LENGTH_LONG).show();
+            }
+            mRecordUi.setState(RecordUi.State.IDLE);
+        }
+    };
+
+    @NonNull
+    private static String getQualityIconName(@Nullable Quality quality) {
+        if (quality == QUALITY_AUTO) {
+            return "Auto";
+        } else if (quality == Quality.UHD) {
+            return "UHD";
+        } else if (quality == Quality.FHD) {
+            return "FHD";
+        } else if (quality == Quality.HD) {
+            return "HD";
+        } else if (quality == Quality.SD) {
+            return "SD";
+        }
+        return "?";
+    }
+
+    private static int qualityToItemId(@Nullable Quality quality) {
+        if (quality == QUALITY_AUTO) {
+            return 0;
+        } else if (quality == Quality.UHD) {
+            return 1;
+        } else if (quality == Quality.FHD) {
+            return 2;
+        } else if (quality == Quality.HD) {
+            return 3;
+        } else if (quality == Quality.SD) {
+            return 4;
+        } else {
+            throw new IllegalArgumentException("Undefined quality: " + quality);
+        }
+    }
+
+    @Nullable
+    private static Quality itemIdToQuality(int itemId) {
+        switch (itemId) {
+            case 0:
+                return QUALITY_AUTO;
+            case 1:
+                return Quality.UHD;
+            case 2:
+                return Quality.FHD;
+            case 3:
+                return Quality.HD;
+            case 4:
+                return Quality.SD;
+            default:
+                throw new IllegalArgumentException("Undefined item id: " + itemId);
+        }
+    }
+
+    @NonNull
+    private static String getQualityMenuItemName(@Nullable Quality quality) {
+        if (quality == QUALITY_AUTO) {
+            return "Auto";
+        } else if (quality == Quality.UHD) {
+            return "UHD (2160P)";
+        } else if (quality == Quality.FHD) {
+            return "FHD (1080P)";
+        } else if (quality == Quality.HD) {
+            return "HD (720P)";
+        } else if (quality == Quality.SD) {
+            return "SD (480P)";
+        }
+        return "Unknown quality";
+    }
+
+    @SuppressLint({"MissingPermission", "NullAnnotationGroup"})
+    @OptIn(markerClass = { ExperimentalCameraInfo.class, ExperimentalPersistentRecording.class})
+    private void setUpRecordButton() {
+        mRecordUi.getButtonRecord().setOnClickListener((view) -> {
+            RecordUi.State state = mRecordUi.getState();
+            switch (state) {
+                case IDLE:
+                    createDefaultVideoFolderIfNotExist();
+                    final PendingRecording pendingRecording;
+                    String fileName = "video_" + System.currentTimeMillis();
+                    String extension = "mp4";
+                    if (canDeviceWriteToMediaStore()) {
+                        // Use MediaStoreOutputOptions for public share media storage.
+                        pendingRecording = mVideoCapture.getOutput().prepareRecording(
+                                this,
+                                generateVideoMediaStoreOptions(getContentResolver(), fileName));
+                    } else {
+                        // Use FileOutputOption for devices in MediaStoreVideoCannotWrite Quirk.
+                        pendingRecording = mVideoCapture.getOutput().prepareRecording(
+                                this, generateVideoFileOutputOptions(fileName, extension));
+                    }
+
+                    resetVideoSavedIdlingResource();
+
+                    if (isPersistentRecordingEnabled()) {
+                        pendingRecording.asPersistentRecording();
+                    }
+                    mActiveRecording = pendingRecording
+                            .withAudioEnabled()
+                            .start(ContextCompat.getMainExecutor(this),
+                                    mVideoRecordEventListener);
+                    mRecordUi.setState(RecordUi.State.RECORDING);
+                    break;
+                case RECORDING:
+                case PAUSED:
+                    mActiveRecording.stop();
+                    mActiveRecording = null;
+                    mRecordUi.setState(RecordUi.State.STOPPING);
+                    break;
+                case STOPPING:
+                    // Record button should be disabled.
+                default:
+                    throw new IllegalStateException(
+                            "Unexpected state when click record button: " + state);
+            }
+        });
+
+        mRecordUi.getButtonPause().setOnClickListener(view -> {
+            RecordUi.State state = mRecordUi.getState();
+            switch (state) {
+                case RECORDING:
+                    mActiveRecording.pause();
+                    mRecordUi.setState(RecordUi.State.PAUSED);
+                    break;
+                case PAUSED:
+                    mActiveRecording.resume();
+                    mRecordUi.setState(RecordUi.State.RECORDING);
+                    break;
+                case IDLE:
+                case STOPPING:
+                    // Pause button should be invisible.
+                default:
+                    throw new IllegalStateException(
+                            "Unexpected state when click pause button: " + state);
+            }
+        });
+
+        // Final reference to this record UI
+        mRecordUi.getButtonQuality().setText(getQualityIconName(mVideoQuality));
+        mRecordUi.getButtonQuality().setOnClickListener(view -> {
+            PopupMenu popup = new PopupMenu(this, view);
+            Menu menu = popup.getMenu();
+
+            // Add Auto item
+            final int groupId = Menu.NONE;
+            final int autoOrder = 0;
+            final int autoMenuId = qualityToItemId(QUALITY_AUTO);
+            menu.add(groupId, autoMenuId, autoOrder, getQualityMenuItemName(QUALITY_AUTO));
+            if (mVideoQuality == QUALITY_AUTO) {
+                menu.findItem(autoMenuId).setChecked(true);
+            }
+
+            // Add device supported qualities
+            VideoCapabilities videoCapabilities = Recorder.getVideoCapabilities(
+                    mCameraProvider.getCameraInfo(CameraSelector.DEFAULT_BACK_CAMERA));
+            List<Quality> supportedQualities = videoCapabilities.getSupportedQualities(
+                    DynamicRange.SDR);
+            // supportedQualities has been sorted by descending order.
+            for (int i = 0; i < supportedQualities.size(); i++) {
+                Quality quality = supportedQualities.get(i);
+                int itemId = qualityToItemId(quality);
+                menu.add(groupId, itemId, autoOrder + 1 + i, getQualityMenuItemName(quality));
+                if (mVideoQuality == quality) {
+                    menu.findItem(itemId).setChecked(true);
+                }
+
+            }
+            // Make menu single checkable
+            menu.setGroupCheckable(groupId, true, true);
+
+            popup.setOnMenuItemClickListener(item -> {
+                Quality quality = itemIdToQuality(item.getItemId());
+                if (quality != mVideoQuality) {
+                    mVideoQuality = quality;
+                    mRecordUi.getButtonQuality().setText(getQualityIconName(mVideoQuality));
+                    // Quality changed, rebind UseCases
+                    startCamera();
+                }
+                return true;
+            });
+
+            popup.show();
+        });
+    }
+
+    private static class SessionMediaUriSet {
+        private final Set<Uri> mSessionMediaUris;
+
+        SessionMediaUriSet() {
+            mSessionMediaUris = Collections.synchronizedSet(new HashSet<>());
+        }
+
+        public void add(@NonNull Uri uri) {
+            mSessionMediaUris.add(uri);
+        }
+    }
+
+    @UiThread
+    private static class RecordUi {
+
+        enum State {
+            IDLE, RECORDING, PAUSED, STOPPING
+        }
+
+        private final Button mButtonRecord;
+        private final Button mButtonPause;
+        private final TextView mTextStats;
+        private final Button mButtonQuality;
+        private final ToggleButton mButtonPersistent;
+        private boolean mEnabled = false;
+        private RecordUi.State mState = RecordUi.State.IDLE;
+        private final Consumer<RecordUi.State> mNewStateConsumer;
+
+        RecordUi(@NonNull Button buttonRecord, @NonNull Button buttonPause,
+                @NonNull TextView textStats, @NonNull Button buttonQuality,
+                @NonNull ToggleButton buttonPersistent,
+                @NonNull Consumer<RecordUi.State> onNewState) {
+            mButtonRecord = buttonRecord;
+            mButtonPause = buttonPause;
+            mTextStats = textStats;
+            mButtonQuality = buttonQuality;
+            mButtonPersistent = buttonPersistent;
+            mNewStateConsumer = onNewState;
+        }
+
+        void setState(@NonNull RecordUi.State state) {
+            if (state != mState) {
+                mState = state;
+                updateUi();
+                mNewStateConsumer.accept(state);
+            }
+        }
+
+        @NonNull
+        RecordUi.State getState() {
+            return mState;
+        }
+
+        void showUi() {
+            mButtonRecord.setVisibility(VISIBLE);
+            mButtonPause.setVisibility(VISIBLE);
+            mTextStats.setVisibility(VISIBLE);
+            mButtonPersistent.setVisibility(VISIBLE);
+            mButtonQuality.setVisibility(VISIBLE);
+        }
+
+        void hideUi() {
+            mButtonRecord.setVisibility(GONE);
+            mButtonPause.setVisibility(GONE);
+            mTextStats.setVisibility(GONE);
+            mButtonPersistent.setVisibility(GONE);
+            mButtonQuality.setVisibility(GONE);
+        }
+
+        private void updateUi() {
+            if (!mEnabled) {
+                return;
+            }
+            switch (mState) {
+                case IDLE:
+                    mButtonRecord.setText("Record");
+                    mButtonRecord.setEnabled(true);
+                    mButtonPause.setText("Pause");
+                    mButtonPause.setVisibility(View.INVISIBLE);
+                    mButtonPersistent.setEnabled(true);
+                    mButtonQuality.setEnabled(true);
+                    break;
+                case RECORDING:
+                    mButtonRecord.setText("Stop");
+                    mButtonRecord.setEnabled(true);
+                    mButtonPause.setText("Pause");
+                    mButtonPause.setVisibility(View.VISIBLE);
+                    mButtonPersistent.setEnabled(false);
+                    mButtonQuality.setEnabled(false);
+                    break;
+                case STOPPING:
+                    mButtonRecord.setText("Saving");
+                    mButtonRecord.setEnabled(false);
+                    mButtonPause.setText("Pause");
+                    mButtonPause.setVisibility(View.INVISIBLE);
+                    mButtonPersistent.setEnabled(false);
+                    mButtonQuality.setEnabled(true);
+                    break;
+                case PAUSED:
+                    mButtonRecord.setText("Stop");
+                    mButtonRecord.setEnabled(true);
+                    mButtonPause.setText("Resume");
+                    mButtonPause.setVisibility(View.VISIBLE);
+                    mButtonPersistent.setEnabled(false);
+                    mButtonQuality.setEnabled(true);
+                    break;
+            }
+        }
+
+        Button getButtonRecord() {
+            return mButtonRecord;
+        }
+
+        Button getButtonPause() {
+            return mButtonPause;
+        }
+
+        TextView getTextStats() {
+            return mTextStats;
+        }
+
+        @NonNull
+        Button getButtonQuality() {
+            return mButtonQuality;
+        }
+
+        ToggleButton getButtonPersistent() {
+            return mButtonPersistent;
+        }
+    }
 }
diff --git a/camera/integration-tests/coretestapp/src/main/res/layout/activity_concurrent_camera.xml b/camera/integration-tests/coretestapp/src/main/res/layout/activity_concurrent_camera.xml
index 9c75f56..13c7764 100644
--- a/camera/integration-tests/coretestapp/src/main/res/layout/activity_concurrent_camera.xml
+++ b/camera/integration-tests/coretestapp/src/main/res/layout/activity_concurrent_camera.xml
@@ -89,56 +89,155 @@
         </LinearLayout>
 
         <LinearLayout
-            android:orientation="vertical"
             android:layout_width="match_parent"
-            android:layout_height="match_parent">
+            android:layout_height="match_parent"
+            android:orientation="vertical">
 
             <ToggleButton
                 android:id="@+id/mode_button"
-                android:textOn="@string/switch_mode"
-                android:textOff="@string/switch_mode"
                 android:layout_width="100dp"
                 android:layout_height="70dp"
-                android:layout_gravity="top|right"
-                android:layout_marginRight="15dp"
-                android:layout_marginTop="15dp" />
+                android:layout_gravity="top|left"
+                android:layout_marginLeft="15dp"
+                android:layout_marginTop="15dp"
+                android:textOff="@string/switch_mode"
+                android:textOn="@string/switch_mode" />
 
             <ToggleButton
                 android:id="@+id/layout_button"
-                android:textOn="@string/change_layout"
-                android:textOff="@string/change_layout"
                 android:layout_width="100dp"
                 android:layout_height="70dp"
-                android:layout_gravity="top|right"
-                android:layout_marginRight="15dp"
-                android:layout_marginTop="15dp" />
+                android:layout_gravity="top|left"
+                android:layout_marginLeft="15dp"
+                android:layout_marginTop="15dp"
+                android:textOff="@string/change_layout"
+                android:textOn="@string/change_layout" />
 
             <ToggleButton
                 android:id="@+id/toggle_button"
-                android:textOn="@string/toggle_camera"
-                android:textOff="@string/toggle_camera"
                 android:layout_width="100dp"
                 android:layout_height="70dp"
-                android:layout_gravity="top|right"
-                android:layout_marginRight="15dp"
-                android:layout_marginTop="15dp" />
+                android:layout_gravity="top|left"
+                android:layout_marginLeft="15dp"
+                android:layout_marginTop="15dp"
+                android:textOff="@string/toggle_camera"
+                android:textOn="@string/toggle_camera" />
 
             <ToggleButton
                 android:id="@+id/dual_selfie"
-                android:textOn="@string/dual_selfie_on"
-                android:textOff="@string/dual_selfie_off"
                 android:layout_width="46dp"
                 android:layout_height="wrap_content"
+                android:layout_gravity="top|left"
+                android:layout_marginLeft="15dp"
+                android:layout_marginTop="15dp"
+                android:background="@drawable/round_toggle_button"
+                android:checked="false"
                 android:scaleType="fitXY"
                 android:textColor="#EEEEEE"
+                android:textOff="@string/dual_selfie_off"
+                android:textOn="@string/dual_selfie_on"
                 android:textSize="10dp"
-                android:checked="false"
+                android:visibility="gone" />
+
+            <ToggleButton
+                android:id="@+id/dual_record"
+                android:layout_width="46dp"
+                android:layout_height="wrap_content"
+                android:layout_gravity="top|left"
+                android:layout_marginLeft="15dp"
+                android:layout_marginTop="15dp"
                 android:background="@drawable/round_toggle_button"
-                android:visibility="gone"
-                android:layout_gravity="top|right"
-                android:layout_marginRight="15dp"
-                android:layout_marginTop="15dp" />
+                android:checked="false"
+                android:scaleType="fitXY"
+                android:textColor="#EEEEEE"
+                android:textOff="@string/dual_recording_off"
+                android:textOn="@string/dual_recording_on"
+                android:textSize="10dp" />
         </LinearLayout>
     </FrameLayout>
+    <androidx.constraintlayout.widget.Guideline
+        android:id="@+id/guideline"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        app:layout_constraintGuide_begin="0dp"
+        app:layout_constraintGuide_percent="0.7" />
+    <androidx.constraintlayout.widget.Guideline
+        android:id="@+id/takevideo"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        app:layout_constraintGuide_begin="0dp"
+        app:layout_constraintGuide_percent="0.4" />
+        <Button
+            android:id="@+id/Video"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:scaleType="fitXY"
+            android:text="Record"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintHorizontal_bias="0.0"
+            app:layout_constraintStart_toStartOf="@+id/takevideo"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintVertical_bias="1.0" />
+
+        <Button
+            android:id="@+id/video_pause"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:scaleType="fitXY"
+            android:text="Pause"
+            app:layout_constraintBottom_toTopOf="@+id/Video"
+            app:layout_constraintEnd_toEndOf="@+id/Video"
+            app:layout_constraintStart_toStartOf="@+id/Video"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintVertical_bias="1.0" />
+
+    <ToggleButton
+        android:id="@+id/video_persistent"
+        android:layout_width="46dp"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="1dp"
+        android:scaleType="fitXY"
+        android:textColor="#EEEEEE"
+        android:textSize="14dp"
+        android:textOn="@string/toggle_video_persistent_on"
+        android:textOff="@string/toggle_video_persistent_off"
+        android:checked="false"
+        android:background="@drawable/round_toggle_button"
+        app:layout_constraintBottom_toTopOf="@+id/video_quality"
+        app:layout_constraintEnd_toEndOf="@+id/video_quality"
+        app:layout_constraintStart_toStartOf="@+id/video_quality"/>
+
+        <TextView
+            android:id="@+id/video_stats"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:background="#FFF"
+            android:elevation="2dp"
+            android:scaleType="fitXY"
+            android:src="@android:drawable/btn_radio"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintDimensionRatio="4:3"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintHorizontal_bias="1.0"
+            app:layout_constraintStart_toStartOf="@+id/guideline"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintVertical_bias="1.0" />
+
+        <Button
+            android:id="@+id/video_quality"
+            android:layout_width="46dp"
+            android:layout_height="wrap_content"
+            android:layout_marginBottom="1dp"
+            android:layout_marginLeft="5dp"
+            android:background="@drawable/round_button"
+            android:scaleType="fitXY"
+            android:textColor="#EEEEEE"
+            android:textSize="14dp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintLeft_toLeftOf="parent" />
 </androidx.constraintlayout.widget.ConstraintLayout>
 <!--</LinearLayout>-->
\ No newline at end of file
diff --git a/camera/integration-tests/coretestapp/src/main/res/values/strings.xml b/camera/integration-tests/coretestapp/src/main/res/values/strings.xml
index 2a8d205..9100424 100644
--- a/camera/integration-tests/coretestapp/src/main/res/values/strings.xml
+++ b/camera/integration-tests/coretestapp/src/main/res/values/strings.xml
@@ -22,6 +22,8 @@
     <string name="toggle_camera">Toggle Camera</string>
     <string name="dual_selfie_on">Dual Selfie On</string>
     <string name="dual_selfie_off">Dual Selfie Off</string>
+    <string name="dual_recording_on">Dual Record On</string>
+    <string name="dual_recording_off">Dual Record Off</string>
     <string name="toggle">Toggle</string>
     <string name="finish">Finish</string>
     <string name="is_front_primary">IsFrontPrimary</string>
diff --git a/camera/integration-tests/extensionstestapp/build.gradle b/camera/integration-tests/extensionstestapp/build.gradle
index 5de107f7..850c2a0 100644
--- a/camera/integration-tests/extensionstestapp/build.gradle
+++ b/camera/integration-tests/extensionstestapp/build.gradle
@@ -99,6 +99,7 @@
 
 // Copy apks to dist/apks as they are used outside of androidx test infrastructure
 ApkCopyHelperKt.setupAppApkCopy(project, "debug")
+ApkCopyHelperKt.setupAppApkCopy(project, "release")
 ApkCopyHelperKt.setupTestApkCopy(project)
 
 androidx {
diff --git a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/BindUnbindUseCasesStressTest.kt b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/BindUnbindUseCasesStressTest.kt
index 88440fc..abf3380 100644
--- a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/BindUnbindUseCasesStressTest.kt
+++ b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/BindUnbindUseCasesStressTest.kt
@@ -77,8 +77,6 @@
             PreTestCameraIdList(config.cameraXConfig)
         )
 
-    private val context = ApplicationProvider.getApplicationContext<Context>()
-
     private lateinit var cameraProvider: ProcessCameraProvider
     private lateinit var extensionsManager: ExtensionsManager
     private lateinit var camera: Camera
@@ -131,6 +129,7 @@
     companion object {
         @ClassRule @JvmField val stressTest = StressTestRule()
 
+        val context = ApplicationProvider.getApplicationContext<Context>()
         @JvmStatic
         @get:Parameterized.Parameters(name = "config = {0}")
         val parameters: Collection<CameraXExtensionTestParams>
diff --git a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/ClientVersionBackwardCompatibilityTest.kt b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/ClientVersionBackwardCompatibilityTest.kt
index 1539ac6..60d545c 100644
--- a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/ClientVersionBackwardCompatibilityTest.kt
+++ b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/ClientVersionBackwardCompatibilityTest.kt
@@ -69,6 +69,7 @@
 @SdkSuppress(minSdkVersion = 21)
 class ClientVersionBackwardCompatibilityTest(private val config: CameraXExtensionTestParams) {
     companion object {
+        val context = ApplicationProvider.getApplicationContext<Context>()
         @JvmStatic
         @get:Parameterized.Parameters(name = "config = {0}")
         val parameters: Collection<CameraXExtensionTestParams>
@@ -85,8 +86,6 @@
             CameraUtil.PreTestCameraIdList(config.cameraXConfig)
         )
 
-    private val context = ApplicationProvider.getApplicationContext<Context>()
-
     private lateinit var cameraProvider: ProcessCameraProvider
     private lateinit var extensionsManager: ExtensionsManager
     private lateinit var baseCameraSelector: CameraSelector
diff --git a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/ImageCaptureExtenderValidationTest.kt b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/ImageCaptureExtenderValidationTest.kt
index 5f262f0..4dad639 100644
--- a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/ImageCaptureExtenderValidationTest.kt
+++ b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/ImageCaptureExtenderValidationTest.kt
@@ -68,8 +68,6 @@
             PreTestCameraIdList(config.cameraXConfig)
         )
 
-    private val context = ApplicationProvider.getApplicationContext<Context>()
-
     private lateinit var cameraProvider: ProcessCameraProvider
     private lateinit var extensionsManager: ExtensionsManager
     private lateinit var cameraCharacteristics: CameraCharacteristics
@@ -115,6 +113,7 @@
     }
 
     companion object {
+        val context = ApplicationProvider.getApplicationContext<Context>()
         @JvmStatic
         @get:Parameterized.Parameters(name = "config = {0}")
         val parameters: Collection<CameraXExtensionTestParams>
diff --git a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/ImageCaptureTest.kt b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/ImageCaptureTest.kt
index 45c462b..c34de2b 100644
--- a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/ImageCaptureTest.kt
+++ b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/ImageCaptureTest.kt
@@ -83,9 +83,9 @@
             Manifest.permission.RECORD_AUDIO,
         )
 
-    private val context = ApplicationProvider.getApplicationContext<Context>()
-
     companion object {
+        val context = ApplicationProvider.getApplicationContext<Context>()
+
         @Parameterized.Parameters(name = "config = {0}")
         @JvmStatic
         fun parameters() = CameraXExtensionsTestUtil.getAllCameraIdExtensionModeCombinations()
@@ -224,7 +224,7 @@
             CameraXExecutors.mainThreadExecutor(),
             object : ImageCapture.OnImageCapturedCallback() {
                 override fun onCaptureSuccess(image: ImageProxy) {
-                    imageCapturedTimestamp = SystemClock.elapsedRealtime()
+                    imageCapturedTimestamp = SystemClock.elapsedRealtimeNanos()
                     imageCapturedLatch.countDown()
                     image.close()
                 }
@@ -232,7 +232,7 @@
                 override fun onCaptureProcessProgressed(progress: Int) {
                     processProgressData.add(progress)
                     if (progress == 100) {
-                        progress100Timestamp = SystemClock.elapsedRealtime()
+                        progress100Timestamp = SystemClock.elapsedRealtimeNanos()
                         progress100Latch.countDown()
                     }
                 }
diff --git a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/LifecycleStatusChangeStressTest.kt b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/LifecycleStatusChangeStressTest.kt
index 4126477..8e7348f 100644
--- a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/LifecycleStatusChangeStressTest.kt
+++ b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/LifecycleStatusChangeStressTest.kt
@@ -79,9 +79,9 @@
             Manifest.permission.RECORD_AUDIO,
         )
 
-    private val context = ApplicationProvider.getApplicationContext<Context>()
-
     companion object {
+        val context = ApplicationProvider.getApplicationContext<Context>()
+
         @Parameterized.Parameters(name = "config = {0}")
         @JvmStatic
         fun parameters() = CameraXExtensionsTestUtil.getAllCameraIdExtensionModeCombinations()
@@ -159,7 +159,6 @@
         with(activityScenario) {
             use {
                 waitForPreviewViewStreaming()
-
                 repeat(repeatCount) {
                     withActivity {
                         resetPreviewViewIdleStateIdlingResource()
diff --git a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/OpenCloseCameraStressTest.kt b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/OpenCloseCameraStressTest.kt
index 8a0276d..6252b12 100644
--- a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/OpenCloseCameraStressTest.kt
+++ b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/OpenCloseCameraStressTest.kt
@@ -69,8 +69,6 @@
             PreTestCameraIdList(config.cameraXConfig)
         )
 
-    private val context = ApplicationProvider.getApplicationContext<Context>()
-
     private lateinit var cameraProvider: ProcessCameraProvider
     private lateinit var extensionsManager: ExtensionsManager
     private lateinit var camera: Camera
@@ -125,6 +123,7 @@
 
     companion object {
         @ClassRule @JvmField val stressTest = StressTestRule()
+        val context = ApplicationProvider.getApplicationContext<Context>()
 
         @JvmStatic
         @get:Parameterized.Parameters(name = "config = {0}")
diff --git a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/OpenCloseCaptureSessionStressTest.kt b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/OpenCloseCaptureSessionStressTest.kt
index 3e2e546..0e0e047 100644
--- a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/OpenCloseCaptureSessionStressTest.kt
+++ b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/OpenCloseCaptureSessionStressTest.kt
@@ -71,8 +71,6 @@
             PreTestCameraIdList(config.cameraXConfig)
         )
 
-    private val context = ApplicationProvider.getApplicationContext<Context>()
-
     private lateinit var cameraProvider: ProcessCameraProvider
     private lateinit var extensionsManager: ExtensionsManager
     private lateinit var camera: Camera
@@ -227,6 +225,7 @@
 
     companion object {
         @ClassRule @JvmField val stressTest = StressTestRule()
+        val context = ApplicationProvider.getApplicationContext<Context>()
 
         @JvmStatic
         @get:Parameterized.Parameters(name = "config = {0}")
diff --git a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/PreviewExtenderValidationTest.kt b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/PreviewExtenderValidationTest.kt
index fb8f7ca..b7321cb 100644
--- a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/PreviewExtenderValidationTest.kt
+++ b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/PreviewExtenderValidationTest.kt
@@ -66,8 +66,6 @@
             PreTestCameraIdList(config.cameraXConfig)
         )
 
-    private val context = ApplicationProvider.getApplicationContext<Context>()
-
     private lateinit var cameraProvider: ProcessCameraProvider
     private lateinit var extensionsManager: ExtensionsManager
     private lateinit var cameraCharacteristics: CameraCharacteristics
@@ -114,6 +112,7 @@
     }
 
     companion object {
+        val context = ApplicationProvider.getApplicationContext<Context>()
         @JvmStatic
         @get:Parameterized.Parameters(name = "config = {0}")
         val parameters: Collection<CameraXExtensionTestParams>
diff --git a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/PreviewTest.kt b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/PreviewTest.kt
index 8f03e8e..970b257 100644
--- a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/PreviewTest.kt
+++ b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/PreviewTest.kt
@@ -70,10 +70,11 @@
             Manifest.permission.RECORD_AUDIO,
         )
 
-    private val context = ApplicationProvider.getApplicationContext<Context>()
     private lateinit var extensionsManager: ExtensionsManager
 
     companion object {
+        val context = ApplicationProvider.getApplicationContext<Context>()
+
         @Parameterized.Parameters(name = "config = {0}")
         @JvmStatic
         fun parameters() = CameraXExtensionsTestUtil.getAllCameraIdExtensionModeCombinations()
diff --git a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/camera2extensions/Camera2ExtensionsActivityTest.kt b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/camera2extensions/Camera2ExtensionsActivityTest.kt
index 8112171..c933712 100644
--- a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/camera2extensions/Camera2ExtensionsActivityTest.kt
+++ b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/camera2extensions/Camera2ExtensionsActivityTest.kt
@@ -33,7 +33,6 @@
 import androidx.camera.integration.extensions.utils.CameraIdExtensionModePair
 import androidx.camera.testing.impl.CameraUtil
 import androidx.camera.testing.impl.CoreAppTestUtil
-import androidx.camera.testing.impl.LabTestRule
 import androidx.camera.testing.impl.StressTestRule
 import androidx.lifecycle.Lifecycle
 import androidx.test.core.app.ActivityScenario
@@ -69,12 +68,11 @@
     @get:Rule
     val permissionRule = GrantPermissionRule.grant(Manifest.permission.WRITE_EXTERNAL_STORAGE)
 
-    @get:Rule val labTest: LabTestRule = LabTestRule()
-
     @Before
     fun setup() {
         Assume.assumeTrue(CameraUtil.deviceHasCamera())
         assumeTrue(CameraXExtensionsTestUtil.isTargetDeviceAvailableForExtensions())
+        assumeTrue(isCamera2ExtensionModeSupported(context, config.cameraId, config.extensionMode))
         // Clears the device UI and check if there is no dialog or lock screen on the top of the
         // window before start the test.
         CoreAppTestUtil.prepareDeviceUI(InstrumentationRegistry.getInstrumentation())
@@ -94,6 +92,7 @@
     }
 
     companion object {
+        val context = ApplicationProvider.getApplicationContext<Context>()
         @ClassRule @JvmField val stressTest = StressTestRule()
 
         @Parameterized.Parameters(name = "config = {0}")
@@ -101,7 +100,6 @@
         fun parameters() = Camera2ExtensionsTestUtil.getAllCameraIdExtensionModeCombinations()
     }
 
-    @LabTestRule.LabTestOnly
     @Test
     fun checkPreviewUpdated() {
         val activityScenario =
@@ -114,7 +112,6 @@
         }
     }
 
-    @LabTestRule.LabTestOnly
     @Test
     fun canCaptureSingleImage() {
         val activityScenario =
@@ -127,7 +124,6 @@
         }
     }
 
-    @LabTestRule.LabTestOnly
     @Test
     fun checkPreviewUpdated_afterPauseResume() {
         val activityScenario =
@@ -147,7 +143,6 @@
         }
     }
 
-    @LabTestRule.LabTestOnly
     @Test
     fun canCaptureImage_afterPauseResume() {
         val activityScenario =
@@ -170,7 +165,6 @@
         }
     }
 
-    @LabTestRule.LabTestOnly
     @Test
     fun canCaptureMultipleImages() {
         val activityScenario =
@@ -190,7 +184,6 @@
     ): ActivityScenario<Camera2ExtensionsActivity> {
         val (cameraId, extensionMode) = config
         val context = ApplicationProvider.getApplicationContext<Context>()
-        assumeTrue(isCamera2ExtensionModeSupported(context, cameraId, extensionMode))
         val intent =
             context.packageManager.getLaunchIntentForPackage(BASIC_SAMPLE_PACKAGE)!!.apply {
                 putExtra(INTENT_EXTRA_KEY_CAMERA_ID, cameraId)
diff --git a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/camera2extensions/Camera2ExtensionsCapabilitiesTest.kt b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/camera2extensions/Camera2ExtensionsCapabilitiesTest.kt
index 023da70..71eb0a4 100644
--- a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/camera2extensions/Camera2ExtensionsCapabilitiesTest.kt
+++ b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/camera2extensions/Camera2ExtensionsCapabilitiesTest.kt
@@ -52,12 +52,13 @@
         )
 
     companion object {
+        val context = ApplicationProvider.getApplicationContext<Context>()
+
         @Parameterized.Parameters(name = "config = {0}")
         @JvmStatic
         fun parameters() = Camera2ExtensionsTestUtil.getAllCameraIdExtensionModeCombinations()
     }
 
-    private val context = ApplicationProvider.getApplicationContext<Context>()
     private val cameraManager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
 
     private lateinit var extensionsCharacteristics: CameraExtensionCharacteristics
diff --git a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/camera2extensions/Camera2ExtensionsImageCaptureStressTest.kt b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/camera2extensions/Camera2ExtensionsImageCaptureStressTest.kt
index e8cd17fa..9b59985 100644
--- a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/camera2extensions/Camera2ExtensionsImageCaptureStressTest.kt
+++ b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/camera2extensions/Camera2ExtensionsImageCaptureStressTest.kt
@@ -65,12 +65,13 @@
     companion object {
         @ClassRule @JvmField val stressTest = StressTestRule()
 
+        val context = ApplicationProvider.getApplicationContext<Context>()
+
         @Parameterized.Parameters(name = "config = {0}")
         @JvmStatic
         fun parameters() = Camera2ExtensionsTestUtil.getAllCameraIdExtensionModeCombinations()
     }
 
-    private val context = ApplicationProvider.getApplicationContext<Context>()
     private val cameraManager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
 
     private lateinit var cameraDevice: CameraDevice
diff --git a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/camera2extensions/Camera2ExtensionsOpenCloseStressTest.kt b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/camera2extensions/Camera2ExtensionsOpenCloseStressTest.kt
index 6863966..9c7ff89 100644
--- a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/camera2extensions/Camera2ExtensionsOpenCloseStressTest.kt
+++ b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/camera2extensions/Camera2ExtensionsOpenCloseStressTest.kt
@@ -49,12 +49,13 @@
     companion object {
         @ClassRule @JvmField val stressTest = StressTestRule()
 
+        val context = ApplicationProvider.getApplicationContext<Context>()
+
         @Parameterized.Parameters(name = "config = {0}")
         @JvmStatic
         fun parameters() = Camera2ExtensionsTestUtil.getAllCameraIdExtensionModeCombinations()
     }
 
-    private val context = ApplicationProvider.getApplicationContext<Context>()
     private val cameraManager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
 
     @Before
diff --git a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/camera2extensions/Camera2ExtensionsSwitchCameraStressTest.kt b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/camera2extensions/Camera2ExtensionsSwitchCameraStressTest.kt
index a4eeeac..25b1847 100644
--- a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/camera2extensions/Camera2ExtensionsSwitchCameraStressTest.kt
+++ b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/camera2extensions/Camera2ExtensionsSwitchCameraStressTest.kt
@@ -50,12 +50,13 @@
     companion object {
         @ClassRule @JvmField val stressTest = StressTestRule()
 
+        val context = ApplicationProvider.getApplicationContext<Context>()
+
         @Parameterized.Parameters(name = "config = {0}")
         @JvmStatic
         fun parameters() = Camera2ExtensionsTestUtil.getAllCameraIdExtensionModeCombinations()
     }
 
-    private val context = ApplicationProvider.getApplicationContext<Context>()
     private val cameraManager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
 
     @Before
diff --git a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/camera2extensions/Camera2ExtensionsSwitchModeStressTest.kt b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/camera2extensions/Camera2ExtensionsSwitchModeStressTest.kt
index 6cc825b..0a3e1cc 100644
--- a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/camera2extensions/Camera2ExtensionsSwitchModeStressTest.kt
+++ b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/camera2extensions/Camera2ExtensionsSwitchModeStressTest.kt
@@ -49,6 +49,7 @@
 
     companion object {
         @ClassRule @JvmField val stressTest = StressTestRule()
+        val context = ApplicationProvider.getApplicationContext<Context>()
 
         @Parameterized.Parameters(name = "cameraId = {0}, extensionMode = {1}")
         @JvmStatic
diff --git a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/util/Camera2ExtensionsTestUtil.kt b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/util/Camera2ExtensionsTestUtil.kt
index 709ba13..fa34afd 100644
--- a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/util/Camera2ExtensionsTestUtil.kt
+++ b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/util/Camera2ExtensionsTestUtil.kt
@@ -37,12 +37,14 @@
 import android.view.Surface
 import androidx.annotation.RequiresApi
 import androidx.camera.core.impl.utils.executor.CameraXExecutors
+import androidx.camera.integration.extensions.utils.Camera2ExtensionsUtil
 import androidx.camera.integration.extensions.utils.Camera2ExtensionsUtil.AVAILABLE_CAMERA2_EXTENSION_MODES
 import androidx.camera.integration.extensions.utils.CameraIdExtensionModePair
 import androidx.camera.testing.impl.CameraUtil
 import androidx.camera.testing.impl.LabTestRule
 import androidx.camera.testing.impl.SurfaceTextureProvider
 import androidx.concurrent.futures.await
+import androidx.test.core.app.ApplicationProvider
 import com.google.common.truth.Truth.assertThat
 import java.util.concurrent.Executors
 import kotlinx.coroutines.CompletableDeferred
@@ -72,12 +74,22 @@
 
     /** Gets a list of all camera id and extension mode combinations. */
     @JvmStatic
-    fun getAllCameraIdExtensionModeCombinations(): List<CameraIdExtensionModePair> =
-        CameraUtil.getBackwardCompatibleCameraIdListOrThrow().flatMap { cameraId ->
-            AVAILABLE_CAMERA2_EXTENSION_MODES.map { extensionMode ->
-                CameraIdExtensionModePair(cameraId, extensionMode)
+    fun getAllCameraIdExtensionModeCombinations(
+        context: Context = ApplicationProvider.getApplicationContext()
+    ): List<CameraIdExtensionModePair> =
+        CameraUtil.getBackwardCompatibleCameraIdListOrThrow()
+            .flatMap { cameraId ->
+                AVAILABLE_CAMERA2_EXTENSION_MODES.map { extensionMode ->
+                    CameraIdExtensionModePair(cameraId, extensionMode)
+                }
             }
-        }
+            .filter {
+                Camera2ExtensionsUtil.isCamera2ExtensionModeSupported(
+                    context,
+                    it.cameraId,
+                    it.extensionMode
+                )
+            }
 
     suspend fun assertCanOpenExtensionsSession(
         cameraManager: CameraManager,
diff --git a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/util/CameraXExtensionsTestUtil.kt b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/util/CameraXExtensionsTestUtil.kt
index 36efe9d..faae745 100644
--- a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/util/CameraXExtensionsTestUtil.kt
+++ b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/util/CameraXExtensionsTestUtil.kt
@@ -58,11 +58,13 @@
 import androidx.camera.integration.extensions.IntentExtraKey
 import androidx.camera.integration.extensions.utils.CameraSelectorUtil.createCameraSelectorById
 import androidx.camera.integration.extensions.utils.ExtensionModeUtil.AVAILABLE_EXTENSION_MODES
+import androidx.camera.lifecycle.ProcessCameraProvider
 import androidx.camera.testing.impl.CameraUtil
 import androidx.camera.testing.impl.LabTestRule
 import androidx.test.core.app.ActivityScenario
 import androidx.test.core.app.ApplicationProvider
 import com.google.common.truth.Truth.assertThat
+import java.util.concurrent.TimeUnit
 import junit.framework.AssertionFailedError
 import org.junit.Assume.assumeTrue
 
@@ -77,14 +79,53 @@
 
     /** Gets a list of all camera id and extension mode combinations. */
     @JvmStatic
-    fun getAllCameraIdExtensionModeCombinations(): List<CameraXExtensionTestParams> =
-        CameraUtil.getBackwardCompatibleCameraIdListOrThrow().flatMap { cameraId ->
-            AVAILABLE_EXTENSION_MODES.flatMap { extensionMode ->
-                CAMERAX_CONFIGS.map { config ->
-                    CameraXExtensionTestParams(config.first, config.second, cameraId, extensionMode)
+    fun getAllCameraIdExtensionModeCombinations(
+        context: Context = ApplicationProvider.getApplicationContext()
+    ): List<CameraXExtensionTestParams> =
+        filterOutUnavailableMode(
+            context,
+            CameraUtil.getBackwardCompatibleCameraIdListOrThrow().flatMap { cameraId ->
+                AVAILABLE_EXTENSION_MODES.flatMap { extensionMode ->
+                    CAMERAX_CONFIGS.map { config ->
+                        CameraXExtensionTestParams(
+                            config.first,
+                            config.second,
+                            cameraId,
+                            extensionMode
+                        )
+                    }
                 }
             }
+        )
+
+    private fun filterOutUnavailableMode(
+        context: Context,
+        list: List<CameraXExtensionTestParams>
+    ): List<CameraXExtensionTestParams> {
+        var extensionsManager: ExtensionsManager? = null
+        var cameraProvider: ProcessCameraProvider? = null
+        try {
+            cameraProvider = ProcessCameraProvider.getInstance(context)[2, TimeUnit.SECONDS]
+            extensionsManager =
+                ExtensionsManager.getInstanceAsync(context, cameraProvider)[2, TimeUnit.SECONDS]
+
+            val result: MutableList<CameraXExtensionTestParams> = mutableListOf()
+            for (item in list) {
+                val cameraSelector = createCameraSelectorById(item.cameraId)
+                if (extensionsManager.isExtensionAvailable(cameraSelector, item.extensionMode)) {
+                    result.add(item)
+                }
+            }
+            return result
+        } catch (e: Exception) {
+            return list
+        } finally {
+            try {
+                cameraProvider?.shutdownAsync()?.get()
+                extensionsManager?.shutdown()?.get()
+            } catch (e: Exception) {}
         }
+    }
 
     /**
      * Gets a list of all camera id and mode combinations. Normal mode and all extension modes will
diff --git a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/ImageCaptureBaseTest.kt b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/ImageCaptureBaseTest.kt
index 1fca6eb..d934150 100644
--- a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/ImageCaptureBaseTest.kt
+++ b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/ImageCaptureBaseTest.kt
@@ -223,9 +223,17 @@
 
     protected inline fun <reified A : CameraActivity> ActivityScenario<A>.waitOnCameraFrames() {
         val analysisRunning = withActivity { mAnalysisRunning }
+        Logger.w(
+            LOG_TAG,
+            "Starting to wait for image analysis frames on thread [${Thread.currentThread().name}]"
+        )
         assertWithMessage("Timed out waiting on image analysis frames on $analysisRunning")
             .that(analysisRunning.tryAcquire(IMAGES_COUNT, TIMEOUT, TimeUnit.SECONDS))
             .isTrue()
+        Logger.w(
+            LOG_TAG,
+            "No longer waiting for image analysis frames on thread [${Thread.currentThread().name}]"
+        )
     }
 
     protected inline fun <reified A : CameraActivity> ActivityScenario<A>.resetFramesCount() {
@@ -251,13 +259,14 @@
                     try {
                         close()
                     } catch (e: Throwable) {
-                        Logger.w("ImageCaptureBaseTest", "Exception in close()", e)
+                        Logger.w(LOG_TAG, "Exception in close()", e)
                     }
             }
         }
     }
 
     companion object {
+        const val LOG_TAG = "ImageCaptureBaseTest"
         protected const val IMAGES_COUNT = 30
         protected const val TIMEOUT = 20L
         @JvmStatic
diff --git a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/ComposeUiFragment.kt b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/ComposeUiFragment.kt
index 90b98d4..aeca39b 100644
--- a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/ComposeUiFragment.kt
+++ b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/ComposeUiFragment.kt
@@ -26,6 +26,9 @@
 import androidx.camera.core.CameraSelector.DEFAULT_FRONT_CAMERA
 import androidx.camera.core.CameraSelector.LENS_FACING_BACK
 import androidx.camera.core.CameraSelector.LENS_FACING_FRONT
+import androidx.camera.integration.view.MainActivity.CAMERA_DIRECTION_BACK
+import androidx.camera.integration.view.MainActivity.CAMERA_DIRECTION_FRONT
+import androidx.camera.integration.view.MainActivity.INTENT_EXTRA_CAMERA_DIRECTION
 import androidx.camera.view.CameraController
 import androidx.camera.view.LifecycleCameraController
 import androidx.camera.view.PreviewView
@@ -70,6 +73,13 @@
                     MainActivity.DEFAULT_SCALE_TYPE_ID
                 )
             currentScaleType = PreviewView.ScaleType.values()[scaleTypeId]
+
+            lensFacing =
+                when (bundle.getString(INTENT_EXTRA_CAMERA_DIRECTION, CAMERA_DIRECTION_BACK)) {
+                    CAMERA_DIRECTION_BACK -> LENS_FACING_BACK
+                    CAMERA_DIRECTION_FRONT -> LENS_FACING_FRONT
+                    else -> LENS_FACING_BACK
+                }
         }
         val previewView = PreviewView(requireContext())
         previewView.scaleType = currentScaleType
@@ -82,6 +92,7 @@
             CameraController.VIDEO_CAPTURE or CameraController.IMAGE_CAPTURE
         )
         previewView.controller = cameraController
+        updateCameraOrientation()
         cameraController.bindToLifecycle(viewLifecycleOwner)
 
         return ComposeView(requireContext()).apply { setContent { AddPreviewView(previewView) } }
@@ -93,14 +104,8 @@
     }
 
     private fun onToggleCamera() {
-        cameraController.cameraSelector =
-            if (lensFacing == LENS_FACING_BACK) {
-                lensFacing = LENS_FACING_FRONT
-                DEFAULT_FRONT_CAMERA
-            } else {
-                lensFacing = LENS_FACING_BACK
-                DEFAULT_BACK_CAMERA
-            }
+        lensFacing = if (lensFacing == LENS_FACING_BACK) LENS_FACING_FRONT else LENS_FACING_BACK
+        updateCameraOrientation()
     }
 
     private fun onToggleEffect() {
@@ -114,6 +119,14 @@
             }
     }
 
+    private fun updateCameraOrientation() {
+        if (lensFacing == LENS_FACING_BACK) {
+            cameraController.cameraSelector = DEFAULT_BACK_CAMERA
+        } else {
+            cameraController.cameraSelector = DEFAULT_FRONT_CAMERA
+        }
+    }
+
     private fun onTakePicture() {
         TODO("Not yet implemented")
     }
diff --git a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/ToneMappingSurfaceProcessor.kt b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/ToneMappingSurfaceProcessor.kt
index 257afda..f31da72 100644
--- a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/ToneMappingSurfaceProcessor.kt
+++ b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/ToneMappingSurfaceProcessor.kt
@@ -48,15 +48,17 @@
                     #extension GL_OES_EGL_image_external : require
                     precision mediump float;
                     uniform samplerExternalOES $sampler;
+                    uniform float uAlphaScale;
                     varying vec2 $fragCoords;
                     void main() {
                       vec4 sampleColor = texture2D($sampler, $fragCoords);
-                      gl_FragColor = vec4(
+                      vec4 src = vec4(
                            sampleColor.r * 0.5 + sampleColor.g * 0.8 + sampleColor.b * 0.3,
                            sampleColor.r * 0.4 + sampleColor.g * 0.7 + sampleColor.b * 0.2,
                            sampleColor.r * 0.3 + sampleColor.g * 0.5 + sampleColor.b * 0.1,
                            1.0);
-                     }
+                      gl_FragColor = vec4(src.rgb, src.a * uAlphaScale);
+                    }
                     """
                 }
             }
diff --git a/car/app/app-samples/github_build.gradle b/car/app/app-samples/github_build.gradle
index 4f83b4b..d1360f2 100644
--- a/car/app/app-samples/github_build.gradle
+++ b/car/app/app-samples/github_build.gradle
@@ -15,17 +15,16 @@
  */
 
 buildscript {
-
     repositories {
         google()
         mavenCentral()
+        gradlePluginPortal()
     }
-    dependencies {
-        classpath 'com.android.tools.build:gradle:8.4.2'
+}
 
-        // NOTE: Do not place your application dependencies here; they belong
-        // in the individual module build.gradle files
-    }
+plugins {
+    alias libs.plugins.android.application apply false
+    alias libs.plugins.android.library apply false
 }
 
 allprojects {
diff --git a/car/app/app-samples/github_settings.gradle b/car/app/app-samples/github_settings.gradle
index b2df5296..3e12259 100644
--- a/car/app/app-samples/github_settings.gradle
+++ b/car/app/app-samples/github_settings.gradle
@@ -14,6 +14,14 @@
  * limitations under the License.
  */
 
+pluginManagement {
+    repositories {
+        google()
+        mavenCentral()
+        gradlePluginPortal()
+    }
+}
+
 rootProject.name='car_app_samples'
 include ':navigation:automotive'
 include ':navigation:common'
diff --git a/car/app/app-samples/gradle/libs.versions.toml b/car/app/app-samples/gradle/libs.versions.toml
new file mode 100644
index 0000000..6c53058
--- /dev/null
+++ b/car/app/app-samples/gradle/libs.versions.toml
@@ -0,0 +1,26 @@
+[versions]
+java = "17"
+kotlin = "2.0.0"
+gradle = "8.4.2"
+androidGradlePlugin = "8.4.2"
+androidx-annotation-experimental = "1.4.1"
+androidx-core = "1.13.1"
+androidx-car = "1.7.0-beta01"
+androidx-constraintlayout = "2.1.4"
+core-ktx = "1.13.1"
+
+[libraries]
+androidx-car-app = { module = "androidx.car.app:app", version.ref = "androidx-car" }
+androidx-app-automotive = { module = "androidx.car.app:app-automotive", version.ref = "androidx-car" }
+androidx-app-projected = { module = "androidx.car.app:app-projected", version.ref = "androidx-car" }
+androidx-annotation-experimental = { module = "androidx.annotation:annotation-experimental", version.ref = "androidx-annotation-experimental" }
+androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "androidx-constraintlayout" }
+androidx-core = { module = "androidx.core:core", version.ref = "androidx-core" }
+androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" }
+gradle = { module = "com.android.tools.build:gradle", version.ref = "gradle" }
+
+
+[plugins]
+jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
+android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
+android-library = { id = "com.android.library", version.ref = "androidGradlePlugin" }
\ No newline at end of file
diff --git a/car/app/app-samples/navigation/automotive/github_build.gradle b/car/app/app-samples/navigation/automotive/github_build.gradle
index e3e7a7f..bd2fa01 100644
--- a/car/app/app-samples/navigation/automotive/github_build.gradle
+++ b/car/app/app-samples/navigation/automotive/github_build.gradle
@@ -14,7 +14,10 @@
  * limitations under the License.
  */
 
-apply plugin: 'com.android.application'
+plugins {
+    alias(libs.plugins.jetbrains.kotlin.android)
+    alias(libs.plugins.android.application)
+}
 
 android {
     compileSdk 34
@@ -39,14 +42,19 @@
         }
     }
 
-    compileOptions {
-        targetCompatibility = JavaVersion.VERSION_19
-        sourceCompatibility = JavaVersion.VERSION_19
+    java.toolchain {
+        languageVersion.set(JavaLanguageVersion.of(libs.versions.java.get()))
     }
+
+    kotlinOptions {
+        jvmTarget = libs.versions.java.get()
+    }
+
     namespace "androidx.car.app.sample.navigation"
 }
 
 dependencies {
-    implementation "androidx.car.app:app-automotive:1.4.0"
+    implementation libs.androidx.app.automotive
     implementation project(":navigation:common")
+    implementation libs.androidx.core.ktx
 }
diff --git a/car/app/app-samples/navigation/common/github_build.gradle b/car/app/app-samples/navigation/common/github_build.gradle
index 18d741d..2158a92 100644
--- a/car/app/app-samples/navigation/common/github_build.gradle
+++ b/car/app/app-samples/navigation/common/github_build.gradle
@@ -14,7 +14,10 @@
  * limitations under the License.
  */
 
-apply plugin: 'com.android.library'
+plugins {
+    alias(libs.plugins.jetbrains.kotlin.android)
+    alias(libs.plugins.android.library)
+}
 
 android {
     compileSdk 34
@@ -25,17 +28,22 @@
         versionCode 1
         versionName "1.0"
     }
-    compileOptions {
-        targetCompatibility = JavaVersion.VERSION_19
-        sourceCompatibility = JavaVersion.VERSION_19
+    java.toolchain {
+        languageVersion.set(JavaLanguageVersion.of(libs.versions.java.get()))
     }
+
+    kotlinOptions {
+        jvmTarget = libs.versions.java.get()
+    }
+
     namespace "androidx.car.app.sample.navigation.common"
 }
 
 dependencies {
-    implementation "androidx.constraintlayout:constraintlayout:2.1.4"
-    implementation "androidx.core:core:1.13.1"
+    implementation libs.androidx.constraintlayout
+    implementation libs.androidx.core
 
-    implementation "androidx.car.app:app:1.4.0"
-    implementation "androidx.annotation:annotation-experimental:1.4.1"
+    implementation libs.androidx.car.app
+    implementation libs.androidx.annotation.experimental
+    implementation libs.androidx.core.ktx
 }
diff --git a/car/app/app-samples/navigation/mobile/github_build.gradle b/car/app/app-samples/navigation/mobile/github_build.gradle
index 6a5c6d7..538be07 100644
--- a/car/app/app-samples/navigation/mobile/github_build.gradle
+++ b/car/app/app-samples/navigation/mobile/github_build.gradle
@@ -14,15 +14,18 @@
  * limitations under the License.
  */
 
-apply plugin: 'com.android.application'
+plugins {
+    alias(libs.plugins.jetbrains.kotlin.android)
+    alias(libs.plugins.android.application)
+}
 
 android {
-    compileSdk 33
+    compileSdk 34
 
     defaultConfig {
         applicationId "androidx.car.app.sample.navigation"
         minSdkVersion 23
-        targetSdkVersion 33
+        targetSdkVersion 34
         // Increment this to generate signed builds for uploading to Playstore
         // Make sure this is different from the navigation-automotive version
         versionCode 114
@@ -39,14 +42,19 @@
         }
     }
 
-    compileOptions {
-        targetCompatibility = JavaVersion.VERSION_1_8
-        sourceCompatibility = JavaVersion.VERSION_1_8
+    java.toolchain {
+        languageVersion.set(JavaLanguageVersion.of(libs.versions.java.get()))
     }
+
+    kotlinOptions {
+        jvmTarget = libs.versions.java.get()
+    }
+
     namespace "androidx.car.app.sample.navigation"
 }
 
 dependencies {
-    implementation "androidx.car.app:app-projected:1.3.0-beta01"
+    implementation libs.androidx.app.projected
     implementation project(":navigation:common")
+    implementation libs.androidx.core.ktx
 }
diff --git a/car/app/app-samples/showcase/automotive/github_build.gradle b/car/app/app-samples/showcase/automotive/github_build.gradle
index 8d7f075..1b7c192 100644
--- a/car/app/app-samples/showcase/automotive/github_build.gradle
+++ b/car/app/app-samples/showcase/automotive/github_build.gradle
@@ -14,7 +14,10 @@
  * limitations under the License.
  */
 
-apply plugin: 'com.android.application'
+plugins {
+    alias(libs.plugins.jetbrains.kotlin.android)
+    alias(libs.plugins.android.application)
+}
 
 android {
     compileSdk 34
@@ -39,9 +42,12 @@
         }
     }
 
-    compileOptions {
-        targetCompatibility = JavaVersion.VERSION_19
-        sourceCompatibility = JavaVersion.VERSION_19
+    java.toolchain {
+        languageVersion.set(JavaLanguageVersion.of(libs.versions.java.get()))
+    }
+
+    kotlinOptions {
+        jvmTarget = libs.versions.java.get()
     }
 
     testOptions.unitTests.includeAndroidResources true
@@ -49,6 +55,7 @@
 }
 
 dependencies {
-    implementation "androidx.car.app:app-automotive:1.4.0"
+    implementation libs.androidx.app.automotive
     implementation project(":showcase:common")
+    implementation libs.androidx.core.ktx
 }
diff --git a/car/app/app-samples/showcase/common/github_build.gradle b/car/app/app-samples/showcase/common/github_build.gradle
index 38f825f..cdf5eb5 100644
--- a/car/app/app-samples/showcase/common/github_build.gradle
+++ b/car/app/app-samples/showcase/common/github_build.gradle
@@ -14,7 +14,10 @@
  * limitations under the License.
  */
 
-apply plugin: 'com.android.library'
+plugins {
+    alias(libs.plugins.jetbrains.kotlin.android)
+    alias(libs.plugins.android.library)
+}
 
 android {
     compileSdk 34
@@ -26,15 +29,20 @@
         versionName "1.0"
     }
 
-    compileOptions {
-        targetCompatibility = JavaVersion.VERSION_19
-        sourceCompatibility = JavaVersion.VERSION_19
+    java.toolchain {
+        languageVersion.set(JavaLanguageVersion.of(libs.versions.java.get()))
     }
+
+    kotlinOptions {
+        jvmTarget = libs.versions.java.get()
+    }
+
     namespace "androidx.car.app.sample.showcase.common"
 }
 
 dependencies {
-    implementation "androidx.core:core:1.13.1"
-    implementation "androidx.car.app:app:1.4.0"
-    implementation "androidx.annotation:annotation-experimental:1.4.1"
+    implementation libs.androidx.core
+    implementation(libs.androidx.car.app)
+    implementation libs.androidx.annotation.experimental
+    implementation libs.androidx.core.ktx
 }
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-as/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-as/strings.xml
index 240c3c9..affbb2f 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-as/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-as/strings.xml
@@ -334,7 +334,7 @@
     <string name="showcase_demos_title" msgid="1542092687878113304">"ডেম’ দেখুৱাওক"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"টেমপ্লে’ট লে’আউটৰ ডেম’"</string>
     <string name="grid_template_menu_demo_title" msgid="7096285873490705119">"গ্ৰিড টেমপ্লে’টৰ ডেম’"</string>
-    <string name="voice_access_demo_title" msgid="3825223890895361496">"কণ্ঠধ্বনিৰে এক্সেছ কৰাৰ ডেম’ৰ স্ক্ৰীন"</string>
+    <string name="voice_access_demo_title" msgid="3825223890895361496">"ভইচেৰে এক্সেছ কৰাৰ ডেম’ৰ স্ক্ৰীন"</string>
     <string name="user_interactions_demo_title" msgid="1356952319161314986">"ব্যৱহাৰকাৰীৰ ভাব-বিনিময়"</string>
     <string name="request_permission_menu_demo_title" msgid="4796486779527427017">"অনুমতিৰ অনুৰোধৰ ডেম’"</string>
     <string name="application_overflow_title" msgid="396427940886169325">"এপ্লিকেশ্বন অভাৰফ্ল’ৰ মান্যতা প্ৰদানকাৰী"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-pt-rPT/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-pt-rPT/strings.xml
index e334a6d..1e2606f 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-pt-rPT/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-pt-rPT/strings.xml
@@ -51,9 +51,9 @@
     <string name="zoomed_in_toast_msg" msgid="8915301497303842649">"Zoom aumentado"</string>
     <string name="zoomed_out_toast_msg" msgid="6260981223227212493">"Zoom diminuído"</string>
     <string name="triggered_toast_msg" msgid="3396166539208366382">"Acionado"</string>
-    <string name="primary_toast_msg" msgid="7153771322662005447">"Botão principal premido"</string>
-    <string name="search_toast_msg" msgid="7826530065407699347">"Botão de pesquisa premido"</string>
-    <string name="options_toast_msg" msgid="2146223786877557730">"Botão de opções premido"</string>
+    <string name="primary_toast_msg" msgid="7153771322662005447">"Botão principal pressionado"</string>
+    <string name="search_toast_msg" msgid="7826530065407699347">"Botão de pesquisa pressionado"</string>
+    <string name="options_toast_msg" msgid="2146223786877557730">"Botão de opções pressionado"</string>
     <string name="favorite_toast_msg" msgid="522064494016370117">"Favorito!"</string>
     <string name="not_favorite_toast_msg" msgid="6831181108681007428">"Não é um favorito!"</string>
     <string name="nav_requested_toast_msg" msgid="6696525973145493908">"Navegação solicitada"</string>
@@ -66,12 +66,12 @@
     <string name="settings_toast_msg" msgid="7697794473002342727">"Clicou em Definições"</string>
     <string name="parked_toast_msg" msgid="2532422265890824446">"Ação de estacionado"</string>
     <string name="more_toast_msg" msgid="5938288138225509885">"Clicou em Mais"</string>
-    <string name="commute_toast_msg" msgid="4112684360647638688">"Botão de viagem regular premido"</string>
+    <string name="commute_toast_msg" msgid="4112684360647638688">"Botão de viagem regular pressionado"</string>
     <string name="grant_location_permission_toast_msg" msgid="268046297444808010">"Conceda autorização de acesso à localização para ver a localização atual"</string>
     <string name="sign_in_with_google_toast_msg" msgid="5720947549233124775">"Iniciar sessão com o Google começa aqui"</string>
     <string name="changes_selection_to_index_toast_msg_prefix" msgid="957766225794389167">"Seleção alterada para o índice"</string>
-    <string name="yes_action_toast_msg" msgid="6216215197177241247">"Botão Sim premido!"</string>
-    <string name="no_action_toast_msg" msgid="6165492423831023809">"Botão Não premido!"</string>
+    <string name="yes_action_toast_msg" msgid="6216215197177241247">"Botão Sim pressionado!"</string>
+    <string name="no_action_toast_msg" msgid="6165492423831023809">"Botão Não pressionado!"</string>
     <string name="alert_timeout_toast_msg" msgid="5568380708832805374">"Tempo limite do alerta excedido!"</string>
     <string name="first_row_title" msgid="219428344573165351">"Linha com uma imagem grande e texto longo texto longo texto longo texto longo texto longo"</string>
     <string name="first_row_text" msgid="3887390298628338716">"Texto texto texto"</string>
diff --git a/car/app/app-samples/showcase/mobile/github_build.gradle b/car/app/app-samples/showcase/mobile/github_build.gradle
index e92419a..f07c54f 100644
--- a/car/app/app-samples/showcase/mobile/github_build.gradle
+++ b/car/app/app-samples/showcase/mobile/github_build.gradle
@@ -14,7 +14,10 @@
  * limitations under the License.
  */
 
-apply plugin: 'com.android.application'
+plugins {
+    alias(libs.plugins.jetbrains.kotlin.android)
+    alias(libs.plugins.android.application)
+}
 
 android {
     compileSdk 34
@@ -39,9 +42,12 @@
         }
     }
 
-    compileOptions {
-        targetCompatibility = JavaVersion.VERSION_19
-        sourceCompatibility = JavaVersion.VERSION_19
+    java.toolchain {
+        languageVersion.set(JavaLanguageVersion.of(libs.versions.java.get()))
+    }
+
+    kotlinOptions {
+        jvmTarget = libs.versions.java.get()
     }
 
     testOptions.unitTests.includeAndroidResources true
@@ -49,6 +55,7 @@
 }
 
 dependencies {
-    implementation "androidx.car.app:app-projected:1.4.0"
+    implementation libs.androidx.app.projected
     implementation project(":showcase:common")
+    implementation libs.androidx.core.ktx
 }
diff --git a/car/app/app/api/1.7.0-beta01.txt b/car/app/app/api/1.7.0-beta01.txt
index 90648d5..958295c 100644
--- a/car/app/app/api/1.7.0-beta01.txt
+++ b/car/app/app/api/1.7.0-beta01.txt
@@ -1061,6 +1061,7 @@
     method public androidx.core.app.Person getSelf();
     method public androidx.car.app.model.CarText getTitle();
     method public boolean isGroupConversation();
+    method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public boolean isIndexable();
   }
 
   public static final class ConversationItem.Builder {
@@ -1072,6 +1073,7 @@
     method public androidx.car.app.messaging.model.ConversationItem.Builder setGroupConversation(boolean);
     method public androidx.car.app.messaging.model.ConversationItem.Builder setIcon(androidx.car.app.model.CarIcon);
     method public androidx.car.app.messaging.model.ConversationItem.Builder setId(String);
+    method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public androidx.car.app.messaging.model.ConversationItem.Builder setIndexable(boolean);
     method public androidx.car.app.messaging.model.ConversationItem.Builder setMessages(java.util.List<androidx.car.app.messaging.model.CarMessage!>);
     method public androidx.car.app.messaging.model.ConversationItem.Builder setSelf(androidx.core.app.Person);
     method public androidx.car.app.messaging.model.ConversationItem.Builder setTitle(androidx.car.app.model.CarText);
@@ -1314,6 +1316,7 @@
     method public androidx.car.app.model.OnClickDelegate? getOnClickDelegate();
     method public androidx.car.app.model.CarText? getText();
     method public androidx.car.app.model.CarText? getTitle();
+    method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public boolean isIndexable();
     method public boolean isLoading();
     field public static final int IMAGE_TYPE_ICON = 1; // 0x1
     field public static final int IMAGE_TYPE_LARGE = 2; // 0x2
@@ -1326,6 +1329,7 @@
     method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public androidx.car.app.model.GridItem.Builder setImage(androidx.car.app.model.CarIcon, androidx.car.app.model.Badge);
     method public androidx.car.app.model.GridItem.Builder setImage(androidx.car.app.model.CarIcon, int);
     method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public androidx.car.app.model.GridItem.Builder setImage(androidx.car.app.model.CarIcon, int, androidx.car.app.model.Badge);
+    method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public androidx.car.app.model.GridItem.Builder setIndexable(boolean);
     method public androidx.car.app.model.GridItem.Builder setLoading(boolean);
     method public androidx.car.app.model.GridItem.Builder setOnClickListener(androidx.car.app.model.OnClickListener);
     method public androidx.car.app.model.GridItem.Builder setText(androidx.car.app.model.CarText);
@@ -1654,6 +1658,7 @@
     method public androidx.car.app.model.Toggle? getToggle();
     method public boolean isBrowsable();
     method @androidx.car.app.annotations.RequiresCarApi(5) public boolean isEnabled();
+    method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public boolean isIndexable();
     method public androidx.car.app.model.Row row();
     method public CharSequence yourBoat();
     field @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public static final int IMAGE_TYPE_EXTRA_SMALL = 8; // 0x8
@@ -1673,6 +1678,7 @@
     method @androidx.car.app.annotations.RequiresCarApi(5) public androidx.car.app.model.Row.Builder setEnabled(boolean);
     method public androidx.car.app.model.Row.Builder setImage(androidx.car.app.model.CarIcon);
     method public androidx.car.app.model.Row.Builder setImage(androidx.car.app.model.CarIcon, int);
+    method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public androidx.car.app.model.Row.Builder setIndexable(boolean);
     method public androidx.car.app.model.Row.Builder setMetadata(androidx.car.app.model.Metadata);
     method @IntRange(from=0) @androidx.car.app.annotations.RequiresCarApi(6) public androidx.car.app.model.Row.Builder setNumericDecoration(int);
     method public androidx.car.app.model.Row.Builder setOnClickListener(androidx.car.app.model.OnClickListener);
@@ -1757,6 +1763,7 @@
     method public java.util.List<androidx.car.app.model.Action!> getActions();
     method public androidx.car.app.model.Header? getHeader();
     method public java.util.List<androidx.car.app.model.Section<? extends java.lang.Object!>!> getSections();
+    method public boolean isAlphabeticalIndexingAllowed();
     method public boolean isLoading();
   }
 
@@ -1769,6 +1776,7 @@
     method @com.google.errorprone.annotations.CanIgnoreReturnValue public androidx.car.app.model.SectionedItemTemplate.Builder clearActions();
     method @com.google.errorprone.annotations.CanIgnoreReturnValue public androidx.car.app.model.SectionedItemTemplate.Builder clearSections();
     method @com.google.errorprone.annotations.CanIgnoreReturnValue public androidx.car.app.model.SectionedItemTemplate.Builder setActions(java.util.List<androidx.car.app.model.Action!>);
+    method @com.google.errorprone.annotations.CanIgnoreReturnValue public androidx.car.app.model.SectionedItemTemplate.Builder setAlphabeticalIndexingAllowed(boolean);
     method @com.google.errorprone.annotations.CanIgnoreReturnValue public androidx.car.app.model.SectionedItemTemplate.Builder setHeader(androidx.car.app.model.Header?);
     method @com.google.errorprone.annotations.CanIgnoreReturnValue public androidx.car.app.model.SectionedItemTemplate.Builder setLoading(boolean);
     method @com.google.errorprone.annotations.CanIgnoreReturnValue public androidx.car.app.model.SectionedItemTemplate.Builder setSections(java.util.List<androidx.car.app.model.Section<? extends java.lang.Object!>!>);
@@ -1799,6 +1807,11 @@
     field public static final String CONTENT_ID = "TAB_CONTENTS_CONTENT_ID";
   }
 
+  @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public static final class TabContents.Api8Builder {
+    ctor public TabContents.Api8Builder(androidx.car.app.model.Template);
+    method public androidx.car.app.model.TabContents build();
+  }
+
   public static final class TabContents.Builder {
     ctor public TabContents.Builder(androidx.car.app.model.Template);
     method public androidx.car.app.model.TabContents build();
diff --git a/car/app/app/api/current.txt b/car/app/app/api/current.txt
index 90648d5..958295c 100644
--- a/car/app/app/api/current.txt
+++ b/car/app/app/api/current.txt
@@ -1061,6 +1061,7 @@
     method public androidx.core.app.Person getSelf();
     method public androidx.car.app.model.CarText getTitle();
     method public boolean isGroupConversation();
+    method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public boolean isIndexable();
   }
 
   public static final class ConversationItem.Builder {
@@ -1072,6 +1073,7 @@
     method public androidx.car.app.messaging.model.ConversationItem.Builder setGroupConversation(boolean);
     method public androidx.car.app.messaging.model.ConversationItem.Builder setIcon(androidx.car.app.model.CarIcon);
     method public androidx.car.app.messaging.model.ConversationItem.Builder setId(String);
+    method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public androidx.car.app.messaging.model.ConversationItem.Builder setIndexable(boolean);
     method public androidx.car.app.messaging.model.ConversationItem.Builder setMessages(java.util.List<androidx.car.app.messaging.model.CarMessage!>);
     method public androidx.car.app.messaging.model.ConversationItem.Builder setSelf(androidx.core.app.Person);
     method public androidx.car.app.messaging.model.ConversationItem.Builder setTitle(androidx.car.app.model.CarText);
@@ -1314,6 +1316,7 @@
     method public androidx.car.app.model.OnClickDelegate? getOnClickDelegate();
     method public androidx.car.app.model.CarText? getText();
     method public androidx.car.app.model.CarText? getTitle();
+    method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public boolean isIndexable();
     method public boolean isLoading();
     field public static final int IMAGE_TYPE_ICON = 1; // 0x1
     field public static final int IMAGE_TYPE_LARGE = 2; // 0x2
@@ -1326,6 +1329,7 @@
     method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public androidx.car.app.model.GridItem.Builder setImage(androidx.car.app.model.CarIcon, androidx.car.app.model.Badge);
     method public androidx.car.app.model.GridItem.Builder setImage(androidx.car.app.model.CarIcon, int);
     method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public androidx.car.app.model.GridItem.Builder setImage(androidx.car.app.model.CarIcon, int, androidx.car.app.model.Badge);
+    method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public androidx.car.app.model.GridItem.Builder setIndexable(boolean);
     method public androidx.car.app.model.GridItem.Builder setLoading(boolean);
     method public androidx.car.app.model.GridItem.Builder setOnClickListener(androidx.car.app.model.OnClickListener);
     method public androidx.car.app.model.GridItem.Builder setText(androidx.car.app.model.CarText);
@@ -1654,6 +1658,7 @@
     method public androidx.car.app.model.Toggle? getToggle();
     method public boolean isBrowsable();
     method @androidx.car.app.annotations.RequiresCarApi(5) public boolean isEnabled();
+    method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public boolean isIndexable();
     method public androidx.car.app.model.Row row();
     method public CharSequence yourBoat();
     field @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public static final int IMAGE_TYPE_EXTRA_SMALL = 8; // 0x8
@@ -1673,6 +1678,7 @@
     method @androidx.car.app.annotations.RequiresCarApi(5) public androidx.car.app.model.Row.Builder setEnabled(boolean);
     method public androidx.car.app.model.Row.Builder setImage(androidx.car.app.model.CarIcon);
     method public androidx.car.app.model.Row.Builder setImage(androidx.car.app.model.CarIcon, int);
+    method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public androidx.car.app.model.Row.Builder setIndexable(boolean);
     method public androidx.car.app.model.Row.Builder setMetadata(androidx.car.app.model.Metadata);
     method @IntRange(from=0) @androidx.car.app.annotations.RequiresCarApi(6) public androidx.car.app.model.Row.Builder setNumericDecoration(int);
     method public androidx.car.app.model.Row.Builder setOnClickListener(androidx.car.app.model.OnClickListener);
@@ -1757,6 +1763,7 @@
     method public java.util.List<androidx.car.app.model.Action!> getActions();
     method public androidx.car.app.model.Header? getHeader();
     method public java.util.List<androidx.car.app.model.Section<? extends java.lang.Object!>!> getSections();
+    method public boolean isAlphabeticalIndexingAllowed();
     method public boolean isLoading();
   }
 
@@ -1769,6 +1776,7 @@
     method @com.google.errorprone.annotations.CanIgnoreReturnValue public androidx.car.app.model.SectionedItemTemplate.Builder clearActions();
     method @com.google.errorprone.annotations.CanIgnoreReturnValue public androidx.car.app.model.SectionedItemTemplate.Builder clearSections();
     method @com.google.errorprone.annotations.CanIgnoreReturnValue public androidx.car.app.model.SectionedItemTemplate.Builder setActions(java.util.List<androidx.car.app.model.Action!>);
+    method @com.google.errorprone.annotations.CanIgnoreReturnValue public androidx.car.app.model.SectionedItemTemplate.Builder setAlphabeticalIndexingAllowed(boolean);
     method @com.google.errorprone.annotations.CanIgnoreReturnValue public androidx.car.app.model.SectionedItemTemplate.Builder setHeader(androidx.car.app.model.Header?);
     method @com.google.errorprone.annotations.CanIgnoreReturnValue public androidx.car.app.model.SectionedItemTemplate.Builder setLoading(boolean);
     method @com.google.errorprone.annotations.CanIgnoreReturnValue public androidx.car.app.model.SectionedItemTemplate.Builder setSections(java.util.List<androidx.car.app.model.Section<? extends java.lang.Object!>!>);
@@ -1799,6 +1807,11 @@
     field public static final String CONTENT_ID = "TAB_CONTENTS_CONTENT_ID";
   }
 
+  @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public static final class TabContents.Api8Builder {
+    ctor public TabContents.Api8Builder(androidx.car.app.model.Template);
+    method public androidx.car.app.model.TabContents build();
+  }
+
   public static final class TabContents.Builder {
     ctor public TabContents.Builder(androidx.car.app.model.Template);
     method public androidx.car.app.model.TabContents build();
diff --git a/car/app/app/api/restricted_1.7.0-beta01.txt b/car/app/app/api/restricted_1.7.0-beta01.txt
index 90648d5..958295c 100644
--- a/car/app/app/api/restricted_1.7.0-beta01.txt
+++ b/car/app/app/api/restricted_1.7.0-beta01.txt
@@ -1061,6 +1061,7 @@
     method public androidx.core.app.Person getSelf();
     method public androidx.car.app.model.CarText getTitle();
     method public boolean isGroupConversation();
+    method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public boolean isIndexable();
   }
 
   public static final class ConversationItem.Builder {
@@ -1072,6 +1073,7 @@
     method public androidx.car.app.messaging.model.ConversationItem.Builder setGroupConversation(boolean);
     method public androidx.car.app.messaging.model.ConversationItem.Builder setIcon(androidx.car.app.model.CarIcon);
     method public androidx.car.app.messaging.model.ConversationItem.Builder setId(String);
+    method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public androidx.car.app.messaging.model.ConversationItem.Builder setIndexable(boolean);
     method public androidx.car.app.messaging.model.ConversationItem.Builder setMessages(java.util.List<androidx.car.app.messaging.model.CarMessage!>);
     method public androidx.car.app.messaging.model.ConversationItem.Builder setSelf(androidx.core.app.Person);
     method public androidx.car.app.messaging.model.ConversationItem.Builder setTitle(androidx.car.app.model.CarText);
@@ -1314,6 +1316,7 @@
     method public androidx.car.app.model.OnClickDelegate? getOnClickDelegate();
     method public androidx.car.app.model.CarText? getText();
     method public androidx.car.app.model.CarText? getTitle();
+    method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public boolean isIndexable();
     method public boolean isLoading();
     field public static final int IMAGE_TYPE_ICON = 1; // 0x1
     field public static final int IMAGE_TYPE_LARGE = 2; // 0x2
@@ -1326,6 +1329,7 @@
     method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public androidx.car.app.model.GridItem.Builder setImage(androidx.car.app.model.CarIcon, androidx.car.app.model.Badge);
     method public androidx.car.app.model.GridItem.Builder setImage(androidx.car.app.model.CarIcon, int);
     method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public androidx.car.app.model.GridItem.Builder setImage(androidx.car.app.model.CarIcon, int, androidx.car.app.model.Badge);
+    method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public androidx.car.app.model.GridItem.Builder setIndexable(boolean);
     method public androidx.car.app.model.GridItem.Builder setLoading(boolean);
     method public androidx.car.app.model.GridItem.Builder setOnClickListener(androidx.car.app.model.OnClickListener);
     method public androidx.car.app.model.GridItem.Builder setText(androidx.car.app.model.CarText);
@@ -1654,6 +1658,7 @@
     method public androidx.car.app.model.Toggle? getToggle();
     method public boolean isBrowsable();
     method @androidx.car.app.annotations.RequiresCarApi(5) public boolean isEnabled();
+    method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public boolean isIndexable();
     method public androidx.car.app.model.Row row();
     method public CharSequence yourBoat();
     field @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public static final int IMAGE_TYPE_EXTRA_SMALL = 8; // 0x8
@@ -1673,6 +1678,7 @@
     method @androidx.car.app.annotations.RequiresCarApi(5) public androidx.car.app.model.Row.Builder setEnabled(boolean);
     method public androidx.car.app.model.Row.Builder setImage(androidx.car.app.model.CarIcon);
     method public androidx.car.app.model.Row.Builder setImage(androidx.car.app.model.CarIcon, int);
+    method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public androidx.car.app.model.Row.Builder setIndexable(boolean);
     method public androidx.car.app.model.Row.Builder setMetadata(androidx.car.app.model.Metadata);
     method @IntRange(from=0) @androidx.car.app.annotations.RequiresCarApi(6) public androidx.car.app.model.Row.Builder setNumericDecoration(int);
     method public androidx.car.app.model.Row.Builder setOnClickListener(androidx.car.app.model.OnClickListener);
@@ -1757,6 +1763,7 @@
     method public java.util.List<androidx.car.app.model.Action!> getActions();
     method public androidx.car.app.model.Header? getHeader();
     method public java.util.List<androidx.car.app.model.Section<? extends java.lang.Object!>!> getSections();
+    method public boolean isAlphabeticalIndexingAllowed();
     method public boolean isLoading();
   }
 
@@ -1769,6 +1776,7 @@
     method @com.google.errorprone.annotations.CanIgnoreReturnValue public androidx.car.app.model.SectionedItemTemplate.Builder clearActions();
     method @com.google.errorprone.annotations.CanIgnoreReturnValue public androidx.car.app.model.SectionedItemTemplate.Builder clearSections();
     method @com.google.errorprone.annotations.CanIgnoreReturnValue public androidx.car.app.model.SectionedItemTemplate.Builder setActions(java.util.List<androidx.car.app.model.Action!>);
+    method @com.google.errorprone.annotations.CanIgnoreReturnValue public androidx.car.app.model.SectionedItemTemplate.Builder setAlphabeticalIndexingAllowed(boolean);
     method @com.google.errorprone.annotations.CanIgnoreReturnValue public androidx.car.app.model.SectionedItemTemplate.Builder setHeader(androidx.car.app.model.Header?);
     method @com.google.errorprone.annotations.CanIgnoreReturnValue public androidx.car.app.model.SectionedItemTemplate.Builder setLoading(boolean);
     method @com.google.errorprone.annotations.CanIgnoreReturnValue public androidx.car.app.model.SectionedItemTemplate.Builder setSections(java.util.List<androidx.car.app.model.Section<? extends java.lang.Object!>!>);
@@ -1799,6 +1807,11 @@
     field public static final String CONTENT_ID = "TAB_CONTENTS_CONTENT_ID";
   }
 
+  @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public static final class TabContents.Api8Builder {
+    ctor public TabContents.Api8Builder(androidx.car.app.model.Template);
+    method public androidx.car.app.model.TabContents build();
+  }
+
   public static final class TabContents.Builder {
     ctor public TabContents.Builder(androidx.car.app.model.Template);
     method public androidx.car.app.model.TabContents build();
diff --git a/car/app/app/api/restricted_current.txt b/car/app/app/api/restricted_current.txt
index 90648d5..958295c 100644
--- a/car/app/app/api/restricted_current.txt
+++ b/car/app/app/api/restricted_current.txt
@@ -1061,6 +1061,7 @@
     method public androidx.core.app.Person getSelf();
     method public androidx.car.app.model.CarText getTitle();
     method public boolean isGroupConversation();
+    method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public boolean isIndexable();
   }
 
   public static final class ConversationItem.Builder {
@@ -1072,6 +1073,7 @@
     method public androidx.car.app.messaging.model.ConversationItem.Builder setGroupConversation(boolean);
     method public androidx.car.app.messaging.model.ConversationItem.Builder setIcon(androidx.car.app.model.CarIcon);
     method public androidx.car.app.messaging.model.ConversationItem.Builder setId(String);
+    method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public androidx.car.app.messaging.model.ConversationItem.Builder setIndexable(boolean);
     method public androidx.car.app.messaging.model.ConversationItem.Builder setMessages(java.util.List<androidx.car.app.messaging.model.CarMessage!>);
     method public androidx.car.app.messaging.model.ConversationItem.Builder setSelf(androidx.core.app.Person);
     method public androidx.car.app.messaging.model.ConversationItem.Builder setTitle(androidx.car.app.model.CarText);
@@ -1314,6 +1316,7 @@
     method public androidx.car.app.model.OnClickDelegate? getOnClickDelegate();
     method public androidx.car.app.model.CarText? getText();
     method public androidx.car.app.model.CarText? getTitle();
+    method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public boolean isIndexable();
     method public boolean isLoading();
     field public static final int IMAGE_TYPE_ICON = 1; // 0x1
     field public static final int IMAGE_TYPE_LARGE = 2; // 0x2
@@ -1326,6 +1329,7 @@
     method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public androidx.car.app.model.GridItem.Builder setImage(androidx.car.app.model.CarIcon, androidx.car.app.model.Badge);
     method public androidx.car.app.model.GridItem.Builder setImage(androidx.car.app.model.CarIcon, int);
     method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public androidx.car.app.model.GridItem.Builder setImage(androidx.car.app.model.CarIcon, int, androidx.car.app.model.Badge);
+    method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public androidx.car.app.model.GridItem.Builder setIndexable(boolean);
     method public androidx.car.app.model.GridItem.Builder setLoading(boolean);
     method public androidx.car.app.model.GridItem.Builder setOnClickListener(androidx.car.app.model.OnClickListener);
     method public androidx.car.app.model.GridItem.Builder setText(androidx.car.app.model.CarText);
@@ -1654,6 +1658,7 @@
     method public androidx.car.app.model.Toggle? getToggle();
     method public boolean isBrowsable();
     method @androidx.car.app.annotations.RequiresCarApi(5) public boolean isEnabled();
+    method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public boolean isIndexable();
     method public androidx.car.app.model.Row row();
     method public CharSequence yourBoat();
     field @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public static final int IMAGE_TYPE_EXTRA_SMALL = 8; // 0x8
@@ -1673,6 +1678,7 @@
     method @androidx.car.app.annotations.RequiresCarApi(5) public androidx.car.app.model.Row.Builder setEnabled(boolean);
     method public androidx.car.app.model.Row.Builder setImage(androidx.car.app.model.CarIcon);
     method public androidx.car.app.model.Row.Builder setImage(androidx.car.app.model.CarIcon, int);
+    method @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public androidx.car.app.model.Row.Builder setIndexable(boolean);
     method public androidx.car.app.model.Row.Builder setMetadata(androidx.car.app.model.Metadata);
     method @IntRange(from=0) @androidx.car.app.annotations.RequiresCarApi(6) public androidx.car.app.model.Row.Builder setNumericDecoration(int);
     method public androidx.car.app.model.Row.Builder setOnClickListener(androidx.car.app.model.OnClickListener);
@@ -1757,6 +1763,7 @@
     method public java.util.List<androidx.car.app.model.Action!> getActions();
     method public androidx.car.app.model.Header? getHeader();
     method public java.util.List<androidx.car.app.model.Section<? extends java.lang.Object!>!> getSections();
+    method public boolean isAlphabeticalIndexingAllowed();
     method public boolean isLoading();
   }
 
@@ -1769,6 +1776,7 @@
     method @com.google.errorprone.annotations.CanIgnoreReturnValue public androidx.car.app.model.SectionedItemTemplate.Builder clearActions();
     method @com.google.errorprone.annotations.CanIgnoreReturnValue public androidx.car.app.model.SectionedItemTemplate.Builder clearSections();
     method @com.google.errorprone.annotations.CanIgnoreReturnValue public androidx.car.app.model.SectionedItemTemplate.Builder setActions(java.util.List<androidx.car.app.model.Action!>);
+    method @com.google.errorprone.annotations.CanIgnoreReturnValue public androidx.car.app.model.SectionedItemTemplate.Builder setAlphabeticalIndexingAllowed(boolean);
     method @com.google.errorprone.annotations.CanIgnoreReturnValue public androidx.car.app.model.SectionedItemTemplate.Builder setHeader(androidx.car.app.model.Header?);
     method @com.google.errorprone.annotations.CanIgnoreReturnValue public androidx.car.app.model.SectionedItemTemplate.Builder setLoading(boolean);
     method @com.google.errorprone.annotations.CanIgnoreReturnValue public androidx.car.app.model.SectionedItemTemplate.Builder setSections(java.util.List<androidx.car.app.model.Section<? extends java.lang.Object!>!>);
@@ -1799,6 +1807,11 @@
     field public static final String CONTENT_ID = "TAB_CONTENTS_CONTENT_ID";
   }
 
+  @SuppressCompatibility @androidx.car.app.annotations.ExperimentalCarApi public static final class TabContents.Api8Builder {
+    ctor public TabContents.Api8Builder(androidx.car.app.model.Template);
+    method public androidx.car.app.model.TabContents build();
+  }
+
   public static final class TabContents.Builder {
     ctor public TabContents.Builder(androidx.car.app.model.Template);
     method public androidx.car.app.model.TabContents build();
diff --git a/car/app/app/build.gradle b/car/app/app/build.gradle
index 6c9e1cb0..972e81b 100644
--- a/car/app/app/build.gradle
+++ b/car/app/app/build.gradle
@@ -83,7 +83,7 @@
 }
 
 project.ext {
-    latestCarAppApiLevel = "7"
+    latestCarAppApiLevel = "8"
 }
 
 android {
diff --git a/car/app/app/src/main/java/androidx/car/app/messaging/model/ConversationItem.java b/car/app/app/src/main/java/androidx/car/app/messaging/model/ConversationItem.java
index 4458473..b5edc77 100644
--- a/car/app/app/src/main/java/androidx/car/app/messaging/model/ConversationItem.java
+++ b/car/app/app/src/main/java/androidx/car/app/messaging/model/ConversationItem.java
@@ -32,6 +32,8 @@
 import androidx.car.app.model.CarIcon;
 import androidx.car.app.model.CarText;
 import androidx.car.app.model.Item;
+import androidx.car.app.model.Row;
+import androidx.car.app.model.Template;
 import androidx.car.app.model.constraints.ActionsConstraints;
 import androidx.car.app.utils.CollectionUtils;
 import androidx.core.app.Person;
@@ -62,6 +64,7 @@
     private final ConversationCallbackDelegate mConversationCallbackDelegate;
     @NonNull
     private final List<Action> mActions;
+    private final boolean mIndexable;
 
     @Override
     public int hashCode() {
@@ -72,7 +75,8 @@
                 mIcon,
                 mIsGroupConversation,
                 mMessages,
-                mActions
+                mActions,
+                mIndexable
         );
     }
 
@@ -95,6 +99,7 @@
                         && mIsGroupConversation == otherConversationItem.mIsGroupConversation
                         && Objects.equals(mMessages, otherConversationItem.mMessages)
                         && Objects.equals(mActions, otherConversationItem.mActions)
+                        && mIndexable == otherConversationItem.mIndexable
                 ;
     }
 
@@ -108,6 +113,7 @@
         checkState(!mMessages.isEmpty(), "Message list cannot be empty.");
         this.mConversationCallbackDelegate = requireNonNull(builder.mConversationCallbackDelegate);
         this.mActions = CollectionUtils.unmodifiableCopy(builder.mActions);
+        this.mIndexable = builder.mIndexable;
     }
 
     /** Default constructor for serialization. */
@@ -131,6 +137,7 @@
                     }
                 });
         mActions = Collections.emptyList();
+        mIndexable = true;
     }
 
     /**
@@ -193,6 +200,24 @@
     }
 
     /**
+     * Returns whether this item should be included in an indexed list.
+     *
+     * <p>"Indexing" refers to the process of examining list contents (e.g. item titles) to sort,
+     * partition, or filter a list. Indexing is generally used for features called "Accelerators",
+     * which allow a user to quickly find a particular {@link Item} in a long list.
+     *
+     * <p>To exclude a single item from indexed lists and accelerator features, use
+     * {@link Row.Builder#setIndexable(boolean)}.
+     *
+     * <p>To enable/disable accelerators for the entire list, see the API for the particular
+     * list-like {@link Template} that you are using.
+     */
+    @ExperimentalCarApi
+    public boolean isIndexable() {
+        return mIndexable;
+    }
+
+    /**
      * Verifies that a given {@link Person} has the required fields to be a message sender. Returns
      * the input {@link Person} if valid, or throws an exception if invalid.
      *
@@ -221,6 +246,7 @@
         @Nullable
         ConversationCallbackDelegate mConversationCallbackDelegate;
         final List<Action> mActions;
+        boolean mIndexable = true;
 
         /**
          * Specifies a unique identifier for the conversation
@@ -318,6 +344,14 @@
             return this;
         }
 
+        /** @see #isIndexable */
+        @ExperimentalCarApi
+        @NonNull
+        public Builder setIndexable(boolean indexable) {
+            mIndexable = indexable;
+            return this;
+        }
+
         /** Returns a new {@link ConversationItem} instance defined by this builder */
         @NonNull
         public ConversationItem build() {
diff --git a/car/app/app/src/main/java/androidx/car/app/model/GridItem.java b/car/app/app/src/main/java/androidx/car/app/model/GridItem.java
index 06304ed..0645006 100644
--- a/car/app/app/src/main/java/androidx/car/app/model/GridItem.java
+++ b/car/app/app/src/main/java/androidx/car/app/model/GridItem.java
@@ -46,7 +46,6 @@
 public final class GridItem implements Item {
     /**
      * The type of images supported within grid items.
-     *
      */
     @RestrictTo(LIBRARY)
     @IntDef(value = {IMAGE_TYPE_ICON, IMAGE_TYPE_LARGE})
@@ -88,6 +87,7 @@
     private final OnClickDelegate mOnClickDelegate;
     @Nullable
     private final Badge mBadge;
+    private final boolean mIndexable;
 
     /**
      * Returns whether the grid item is in a loading state.
@@ -156,6 +156,24 @@
         return mBadge;
     }
 
+    /**
+     * Returns whether this item should be included in an indexed list.
+     *
+     * <p>"Indexing" refers to the process of examining list contents (e.g. item titles) to sort,
+     * partition, or filter a list. Indexing is generally used for features called "Accelerators",
+     * which allow a user to quickly find a particular {@link Item} in a long list.
+     *
+     * <p>To exclude a single item from indexed lists and accelerator features, use
+     * {@link Row.Builder#setIndexable(boolean)}.
+     *
+     * <p>To enable/disable accelerators for the entire list, see the API for the particular
+     * list-like {@link Template} that you are using.
+     */
+    @ExperimentalCarApi
+    public boolean isIndexable() {
+        return mIndexable;
+    }
+
     @Override
     @NonNull
     public String toString() {
@@ -174,8 +192,15 @@
 
     @Override
     public int hashCode() {
-        return Objects.hash(mIsLoading, mTitle, mImage, mImageType, mOnClickDelegate == null,
-                mBadge);
+        return Objects.hash(
+                mIsLoading,
+                mTitle,
+                mImage,
+                mImageType,
+                mOnClickDelegate == null,
+                mBadge,
+                mIndexable
+        );
     }
 
     @Override
@@ -194,7 +219,8 @@
                 && Objects.equals(mImage, otherGridItem.mImage)
                 && Objects.equals(mOnClickDelegate == null, otherGridItem.mOnClickDelegate == null)
                 && Objects.equals(mBadge, otherGridItem.mBadge)
-                && mImageType == otherGridItem.mImageType;
+                && mImageType == otherGridItem.mImageType
+                && mIndexable == otherGridItem.mIndexable;
     }
 
     GridItem(Builder builder) {
@@ -205,6 +231,7 @@
         mImageType = builder.mImageType;
         mOnClickDelegate = builder.mOnClickDelegate;
         mBadge = builder.mBadge;
+        mIndexable = builder.mIndexable;
     }
 
     /** Constructs an empty instance, used by serialization code. */
@@ -216,6 +243,7 @@
         mImageType = IMAGE_TYPE_LARGE;
         mOnClickDelegate = null;
         mBadge = null;
+        mIndexable = true;
     }
 
     /** A builder of {@link GridItem}. */
@@ -233,6 +261,7 @@
         boolean mIsLoading;
         @Nullable
         Badge mBadge;
+        boolean mIndexable;
 
         /**
          * Sets whether the item is in a loading state.
@@ -425,6 +454,14 @@
             return this;
         }
 
+        /** @see #isIndexable */
+        @ExperimentalCarApi
+        @NonNull
+        public Builder setIndexable(boolean indexable) {
+            mIndexable = indexable;
+            return this;
+        }
+
         /**
          * Constructs the {@link GridItem} defined by this builder.
          *
diff --git a/car/app/app/src/main/java/androidx/car/app/model/Row.java b/car/app/app/src/main/java/androidx/car/app/model/Row.java
index d13ebfa..c1b5a4e 100644
--- a/car/app/app/src/main/java/androidx/car/app/model/Row.java
+++ b/car/app/app/src/main/java/androidx/car/app/model/Row.java
@@ -61,7 +61,6 @@
 
     /**
      * The type of images supported within rows.
-     *
      */
     @RestrictTo(LIBRARY)
     @IntDef(value = {IMAGE_TYPE_SMALL, IMAGE_TYPE_ICON, IMAGE_TYPE_LARGE, IMAGE_TYPE_EXTRA_SMALL})
@@ -126,6 +125,7 @@
     private final boolean mIsBrowsable;
     @RowImageType
     private final int mRowImageType;
+    private final boolean mIndexable;
 
     /**
      * Returns the title of the row or {@code null} if not set.
@@ -248,6 +248,24 @@
         return YOUR_BOAT;
     }
 
+    /**
+     * Returns whether this item should be included in an indexed list.
+     *
+     * <p>"Indexing" refers to the process of examining list contents (e.g. item titles) to sort,
+     * partition, or filter a list. Indexing is generally used for features called "Accelerators",
+     * which allow a user to quickly find a particular {@link Item} in a long list.
+     *
+     * <p>To exclude a single item from indexed lists and accelerator features, use
+     * {@link Row.Builder#setIndexable(boolean)}.
+     *
+     * <p>To enable/disable accelerators for the entire list, see the API for the particular
+     * list-like {@link Template} that you are using.
+     */
+    @ExperimentalCarApi
+    public boolean isIndexable() {
+        return mIndexable;
+    }
+
     /** Returns a {@link Row} for rowing {@link #yourBoat()} */
     @NonNull
     public Row row() {
@@ -289,7 +307,8 @@
                 mMetadata,
                 mIsBrowsable,
                 mRowImageType,
-                mIsEnabled);
+                mIsEnabled,
+                mIndexable);
     }
 
     @Override
@@ -311,7 +330,8 @@
                 && Objects.equals(mMetadata, otherRow.mMetadata)
                 && mIsBrowsable == otherRow.mIsBrowsable
                 && mRowImageType == otherRow.mRowImageType
-                && mIsEnabled == otherRow.isEnabled();
+                && mIsEnabled == otherRow.isEnabled()
+                && mIndexable == otherRow.mIndexable;
     }
 
     Row(Builder builder) {
@@ -326,6 +346,7 @@
         mIsBrowsable = builder.mIsBrowsable;
         mRowImageType = builder.mRowImageType;
         mIsEnabled = builder.mIsEnabled;
+        mIndexable = builder.mIndexable;
     }
 
     /** Constructs an empty instance, used by serialization code. */
@@ -341,6 +362,7 @@
         mIsBrowsable = false;
         mRowImageType = IMAGE_TYPE_SMALL;
         mIsEnabled = true;
+        mIndexable = true;
     }
 
     /** A builder of {@link Row}. */
@@ -361,6 +383,7 @@
         boolean mIsBrowsable;
         @RowImageType
         int mRowImageType = IMAGE_TYPE_SMALL;
+        boolean mIndexable = true;
 
         /**
          * Sets the title of the row.
@@ -671,6 +694,14 @@
             return this;
         }
 
+        /** @see #isIndexable */
+        @ExperimentalCarApi
+        @NonNull
+        public Builder setIndexable(boolean indexable) {
+            mIndexable = indexable;
+            return this;
+        }
+
         /**
          * Constructs the {@link Row} defined by this builder.
          *
diff --git a/car/app/app/src/main/java/androidx/car/app/model/SectionedItemTemplate.java b/car/app/app/src/main/java/androidx/car/app/model/SectionedItemTemplate.java
index d0b6860..9f1b19c0 100644
--- a/car/app/app/src/main/java/androidx/car/app/model/SectionedItemTemplate.java
+++ b/car/app/app/src/main/java/androidx/car/app/model/SectionedItemTemplate.java
@@ -46,12 +46,15 @@
 
     private final boolean mIsLoading;
 
+    private final boolean mIsAlphabeticalIndexingAllowed;
+
     // Empty constructor for serialization
     private SectionedItemTemplate() {
         mSections = Collections.emptyList();
         mActions = Collections.emptyList();
         mHeader = null;
         mIsLoading = false;
+        mIsAlphabeticalIndexingAllowed = false;
     }
 
     /** Creates a {@link SectionedItemTemplate} from the {@link Builder}. */
@@ -60,6 +63,7 @@
         mActions = Collections.unmodifiableList(builder.mActions);
         mHeader = builder.mHeader;
         mIsLoading = builder.mIsLoading;
+        mIsAlphabeticalIndexingAllowed = builder.mIsAlphabeticalIndexingAllowed;
     }
 
     /** Returns the list of sections within this template. */
@@ -85,9 +89,30 @@
         return mIsLoading;
     }
 
+    /**
+     * Returns whether this list can be indexed alphabetically, by item title.
+     *
+     * <p>"Indexing" refers to the process of examining list contents (e.g. item titles) to sort,
+     * partition, or filter a list. Indexing is generally used for features called "Accelerators",
+     * which allow a user to quickly find a particular {@link Item} in a long list.
+     *
+     * <p>To exclude a single item from indexing, see the relevant item's API.
+     *
+     * <p>To enable/disable accelerators for the entire list, see
+     * {@link SectionedItemTemplate.Builder#setAlphabeticalIndexingAllowed(boolean)}
+     */
+    public boolean isAlphabeticalIndexingAllowed() {
+        return mIsAlphabeticalIndexingAllowed;
+    }
+
     @Override
     public int hashCode() {
-        return Objects.hash(mSections, mActions, mHeader, mIsLoading);
+        return Objects.hash(mSections,
+                mActions,
+                mHeader,
+                mIsLoading,
+                mIsAlphabeticalIndexingAllowed
+        );
     }
 
     @Override
@@ -105,14 +130,14 @@
         return Objects.equals(mSections, template.mSections)
                 && Objects.equals(mActions, template.mActions)
                 && Objects.equals(mHeader, template.mHeader)
-                && mIsLoading == template.mIsLoading;
+                && mIsLoading == template.mIsLoading
+                && mIsAlphabeticalIndexingAllowed == template.mIsAlphabeticalIndexingAllowed;
     }
 
     @NonNull
     @Override
     public String toString() {
-        return "SectionedItemTemplate { sections: " + mSections + ", actions: " + mActions
-                + ", header: " + mHeader + ", isLoading: " + mIsLoading + " }";
+        return "SectionedItemTemplate";
     }
 
     /**
@@ -137,6 +162,7 @@
         private Header mHeader = null;
 
         private boolean mIsLoading = false;
+        private boolean mIsAlphabeticalIndexingAllowed = false;
 
         /** Create a new {@link SectionedItemTemplate} builder. */
         public Builder() {
@@ -151,6 +177,7 @@
             mActions = template.mActions;
             mHeader = template.mHeader;
             mIsLoading = template.mIsLoading;
+            mIsAlphabeticalIndexingAllowed = template.mIsAlphabeticalIndexingAllowed;
         }
 
         /**
@@ -245,6 +272,24 @@
         }
 
         /**
+         * Sets whether this list can be indexed alphabetically, by item title.
+         *
+         * <p>"Indexing" refers to the process of examining list contents (e.g. item titles) to
+         * sort,
+         * partition, or filter a list. Indexing is generally used for features called
+         * "Accelerators",
+         * which allow a user to quickly find a particular {@link Item} in a long list.
+         *
+         * <p>To exclude a single item from indexing, see the relevant item's API.
+         */
+        @NonNull
+        @CanIgnoreReturnValue
+        public Builder setAlphabeticalIndexingAllowed(boolean alphabeticalIndexingAllowed) {
+            mIsAlphabeticalIndexingAllowed = alphabeticalIndexingAllowed;
+            return this;
+        }
+
+        /**
          * Constructs a new {@link SectionedItemTemplate} from the current state of this builder,
          * throwing exceptions for any invalid state.
          *
diff --git a/car/app/app/src/main/java/androidx/car/app/model/TabContents.java b/car/app/app/src/main/java/androidx/car/app/model/TabContents.java
index 0a7b5bd..c9e3593 100644
--- a/car/app/app/src/main/java/androidx/car/app/model/TabContents.java
+++ b/car/app/app/src/main/java/androidx/car/app/model/TabContents.java
@@ -21,6 +21,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.car.app.annotations.CarProtocol;
+import androidx.car.app.annotations.ExperimentalCarApi;
 import androidx.car.app.annotations.KeepFields;
 import androidx.car.app.annotations.RequiresCarApi;
 import androidx.car.app.model.constraints.TabContentsConstraints;
@@ -91,6 +92,11 @@
         mTemplate = builder.mTemplate;
     }
 
+    @ExperimentalCarApi
+    TabContents(TabContents.Api8Builder builder) {
+        mTemplate = builder.mTemplate;
+    }
+
     /** Constructs an empty instance, used by serialization code. */
     private TabContents() {
         mTemplate = null;
@@ -139,4 +145,45 @@
             mTemplate = template;
         }
     }
+
+    /** A builder of {@link TabContents} which supports templates added in API 8. */
+    @ExperimentalCarApi
+    public static final class Api8Builder {
+        @NonNull
+        Template mTemplate;
+
+        /**
+         * Constructs the {@link TabContents} defined by this builder.
+         */
+        @NonNull
+        public TabContents build() {
+            return new TabContents(this);
+        }
+
+        /**
+         * Creates a {@link TabContents.Api8Builder} instance using the given {@link Template} to
+         * display as contents.
+         *
+         * <p>There should be no title, Header {@link Action} or {@link ActionStrip} set on the
+         * template. The host will ignore these.
+         *
+         * <p>From Car API 8, the following template types are supported as content:
+         * <ul>
+         *     <li>{@code ListTemplate}
+         *     <li>{@code PaneTemplate}
+         *     <li>{@code GridTemplate}
+         *     <li>{@code MessageTemplate}
+         *     <li>{@code SearchTemplate}
+         *     <li>{@code NavigationTemplate}
+         *     <li>{@code SectionedItemTemplate}
+         * </ul>
+         *
+         * @throws NullPointerException     if {@code template} is null
+         * @throws IllegalArgumentException if {@code template} does not meet the requirements
+         */
+        public Api8Builder(@NonNull Template template) {
+            TabContentsConstraints.API_8.validateOrThrow(requireNonNull(template));
+            mTemplate = template;
+        }
+    }
 }
diff --git a/car/app/app/src/main/java/androidx/car/app/model/constraints/TabContentsConstraints.java b/car/app/app/src/main/java/androidx/car/app/model/constraints/TabContentsConstraints.java
index 25f65df..6ee0197 100644
--- a/car/app/app/src/main/java/androidx/car/app/model/constraints/TabContentsConstraints.java
+++ b/car/app/app/src/main/java/androidx/car/app/model/constraints/TabContentsConstraints.java
@@ -18,6 +18,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.RestrictTo;
+import androidx.car.app.annotations.ExperimentalCarApi;
 import androidx.car.app.annotations.RequiresCarApi;
 import androidx.car.app.model.CarText;
 import androidx.car.app.model.GridTemplate;
@@ -25,6 +26,7 @@
 import androidx.car.app.model.MessageTemplate;
 import androidx.car.app.model.PaneTemplate;
 import androidx.car.app.model.SearchTemplate;
+import androidx.car.app.model.SectionedItemTemplate;
 import androidx.car.app.model.Template;
 import androidx.car.app.navigation.model.NavigationTemplate;
 
@@ -66,6 +68,20 @@
                     NavigationTemplate.class
             ));
 
+    /** The set of allowed templates as content within a tab template since API 8. */
+    @ExperimentalCarApi
+    @NonNull
+    public static final TabContentsConstraints API_8 =
+            new TabContentsConstraints(Arrays.asList(
+                    ListTemplate.class,
+                    PaneTemplate.class,
+                    GridTemplate.class,
+                    MessageTemplate.class,
+                    SearchTemplate.class,
+                    NavigationTemplate.class,
+                    SectionedItemTemplate.class
+            ));
+
     private HashSet<Class<? extends Template>> mAllowedTemplateTypes;
 
     /**
diff --git a/car/app/app/src/test/java/androidx/car/app/model/SectionedItemTemplateTest.kt b/car/app/app/src/test/java/androidx/car/app/model/SectionedItemTemplateTest.kt
index 1e8e95a..57d7d4e 100644
--- a/car/app/app/src/test/java/androidx/car/app/model/SectionedItemTemplateTest.kt
+++ b/car/app/app/src/test/java/androidx/car/app/model/SectionedItemTemplateTest.kt
@@ -80,6 +80,13 @@
     }
 
     @Test
+    fun isAlphabeticalIndexingAllowed() {
+        val template = SectionedItemTemplate.Builder().setAlphabeticalIndexingAllowed(true).build()
+
+        assertThat(template.isAlphabeticalIndexingAllowed).isTrue()
+    }
+
+    @Test
     fun build_throwsException_whenLoadingAndContainsSections() {
         try {
             SectionedItemTemplate.Builder()
@@ -117,73 +124,75 @@
     fun setActions_throwsException_whenNotFabConstrained() {
         try {
             // Cannot have more than 3 actions
-            val actions =
-                listOf(
-                    Action.Builder().setTitle("Action 1").setIcon(CarIcon.COMPOSE_MESSAGE).build(),
-                    Action.Builder().setTitle("Action 1").setIcon(CarIcon.COMPOSE_MESSAGE).build(),
-                    Action.Builder().setTitle("Action 1").setIcon(CarIcon.COMPOSE_MESSAGE).build()
+            SectionedItemTemplate.Builder()
+                .setActions(
+                    List(3) {
+                        Action.Builder()
+                            .setTitle("Action $it")
+                            .setIcon(CarIcon.COMPOSE_MESSAGE)
+                            .build()
+                    }
                 )
-            SectionedItemTemplate.Builder().setActions(actions)
         } catch (e: IllegalArgumentException) {
             assertThat(e.message).contains("list exceeded max number")
         }
     }
 
     @Test
-    fun equals_returnsFalse_whenPassedNull() {
-        val template = SectionedItemTemplate.Builder().build()
-
-        assertThat(template.equals(null)).isFalse()
+    fun equals_null_returnsFalse() {
+        assertThat(buildTemplate().equals(null)).isFalse()
     }
 
     @Test
-    fun equals_isReflexive() {
-        val template =
-            SectionedItemTemplate.Builder()
-                .setSections(testSections)
-                .setHeader(testHeader)
-                .setActions(testActions)
-                .build()
+    fun equals_sameInstance_returnsTrue() {
+        val template = createFullyPopulatedTemplate()
 
-        @Suppress("ReplaceCallWithBinaryOperator") assertThat(template.equals(template)).isTrue()
+        assertEqual(template, template)
     }
 
     @Test
-    fun equals_returnsTrue_whenSectionsHaveTheSameContent() {
-        val template1 =
-            SectionedItemTemplate.Builder()
-                .setSections(testSections)
-                .setHeader(testHeader)
-                .setActions(testActions)
-                .build()
-        val template2 =
-            SectionedItemTemplate.Builder()
-                .setSections(testSections)
-                .setHeader(testHeader)
-                .setActions(testActions)
-                .build()
-
-        assertThat(template1).isEqualTo(template2)
-        assertThat(template2).isEqualTo(template1)
+    fun equals_differentTemplatesSameContent_returnsTrue() {
+        assertEqual(createFullyPopulatedTemplate(), createFullyPopulatedTemplate())
     }
 
     @Test
-    fun equals_returnsFalse_whenNotEqual() {
-        val templates =
-            listOf(
-                SectionedItemTemplate.Builder().setSections(testSections).build(),
-                SectionedItemTemplate.Builder().setHeader(testHeader).build(),
-                SectionedItemTemplate.Builder().setActions(testActions).build()
-            )
+    fun equals_oneDifferingField_returnsFalse() {
+        val minimalTemplate = buildTemplate()
 
-        // Test all different sections against each other
-        for (i in templates.indices) {
-            for (j in templates.indices) {
-                if (i == j) {
-                    continue
-                }
-                assertThat(templates[i]).isNotEqualTo(templates[j])
-            }
-        }
+        assertNotEqual(minimalTemplate, buildTemplate { setSections(testSections) })
+        assertNotEqual(minimalTemplate, buildTemplate { setHeader(testHeader) })
+        assertNotEqual(minimalTemplate, buildTemplate { setActions(testActions) })
+        assertNotEqual(minimalTemplate, buildTemplate { setLoading(true) })
+        assertNotEqual(minimalTemplate, buildTemplate { setAlphabeticalIndexingAllowed(true) })
     }
+
+    @Test
+    fun toBuilder_build_returnsEquivalentObject() {
+        val template = createFullyPopulatedTemplate()
+
+        assertEqual(template, SectionedItemTemplate.Builder(template).build())
+    }
+
+    private fun assertEqual(obj1: Any, obj2: Any) {
+        assertThat(obj1).isEqualTo(obj2)
+        assertThat(obj2).isEqualTo(obj1)
+        assertThat(obj1.hashCode()).isEqualTo(obj2.hashCode())
+    }
+
+    private fun assertNotEqual(obj1: Any, obj2: Any) {
+        assertThat(obj1).isNotEqualTo(obj2)
+        assertThat(obj2).isNotEqualTo(obj1)
+        assertThat(obj1.hashCode()).isNotEqualTo(obj2.hashCode())
+    }
+
+    private fun createFullyPopulatedTemplate() =
+        SectionedItemTemplate.Builder()
+            .setSections(testSections)
+            .setHeader(testHeader)
+            .setActions(testActions)
+            .setAlphabeticalIndexingAllowed(true)
+            .build()
+
+    private fun buildTemplate(block: SectionedItemTemplate.Builder.() -> Unit = {}) =
+        SectionedItemTemplate.Builder().apply { block() }.build()
 }
diff --git a/car/app/app/src/test/java/androidx/car/app/model/TabContentsTest.java b/car/app/app/src/test/java/androidx/car/app/model/TabContentsTest.java
index a5097ef..1d3949b 100644
--- a/car/app/app/src/test/java/androidx/car/app/model/TabContentsTest.java
+++ b/car/app/app/src/test/java/androidx/car/app/model/TabContentsTest.java
@@ -88,6 +88,30 @@
     }
 
     @Test
+    public void createInstance_sectionedItemTemplate_Throws() {
+        SectionedItemTemplate template =
+                new SectionedItemTemplate.Builder().setHeader(
+                        new Header.Builder().setTitle("title").build()
+                ).build();
+
+        assertThrows(
+                IllegalArgumentException.class,
+                () -> new TabContents.Builder(template).build());
+    }
+
+    @Test
+    public void createInstance_api8_sectionedItemTemplate() {
+        SectionedItemTemplate template =
+                new SectionedItemTemplate.Builder().setHeader(
+                        new Header.Builder().setTitle("title").build()
+                ).build();
+
+        TabContents tabContents = new TabContents.Api8Builder(template).build();
+
+        assertEquals(template, tabContents.getTemplate());
+    }
+
+    @Test
     public void equals() {
         MessageTemplate template = new MessageTemplate.Builder("title")
                 .addAction(
diff --git a/collection/collection-benchmark/src/androidInstrumentedTest/kotlin/androidx/collection/ScatterMapBenchmarkTest.kt b/collection/collection-benchmark/src/androidInstrumentedTest/kotlin/androidx/collection/ScatterMapBenchmarkTest.kt
index 023ed69..53657a2 100644
--- a/collection/collection-benchmark/src/androidInstrumentedTest/kotlin/androidx/collection/ScatterMapBenchmarkTest.kt
+++ b/collection/collection-benchmark/src/androidInstrumentedTest/kotlin/androidx/collection/ScatterMapBenchmarkTest.kt
@@ -65,6 +65,11 @@
         benchmark.runCollectionBenchmark(ScatterMapComputeBenchmark(sourceSet))
     }
 
+    @Test
+    fun insert_remove() {
+        benchmark.runCollectionBenchmark(ScatterMapInsertRemoveBenchmark(badHashSourceSet))
+    }
+
     companion object {
         @JvmStatic
         @Parameters(name = "size={0}")
diff --git a/collection/collection-benchmark/src/commonMain/kotlin/androidx/collection/ScatterMapBenchmarks.kt b/collection/collection-benchmark/src/commonMain/kotlin/androidx/collection/ScatterMapBenchmarks.kt
index 20d2ba2..3471ed1b 100644
--- a/collection/collection-benchmark/src/commonMain/kotlin/androidx/collection/ScatterMapBenchmarks.kt
+++ b/collection/collection-benchmark/src/commonMain/kotlin/androidx/collection/ScatterMapBenchmarks.kt
@@ -121,6 +121,18 @@
     }
 }
 
+internal class ScatterMapInsertRemoveBenchmark(private val dataSet: Array<Int?>) :
+    CollectionBenchmark {
+    private val map = MutableScatterMap<Int?, Int?>()
+
+    override fun measuredBlock() {
+        for (testValue in dataSet) {
+            map[testValue] = testValue
+            map.remove(testValue)
+        }
+    }
+}
+
 internal fun createDataSet(size: Int): Array<String> =
     Array(size) { index -> (index * Random.Default.nextFloat()).toString() }
 
diff --git a/collection/collection/build.gradle b/collection/collection/build.gradle
index 0023864..84812dc 100644
--- a/collection/collection/build.gradle
+++ b/collection/collection/build.gradle
@@ -37,7 +37,10 @@
     }
     mac()
     linux()
+    linuxArm64()
     ios()
+    watchos()
+    tvos()
 
     defaultPlatform(PlatformIdentifier.JVM)
 
@@ -50,7 +53,7 @@
         commonMain {
             dependencies {
                 api(libs.kotlinStdlib)
-                api("androidx.annotation:annotation:1.7.0")
+                api(project(":annotation:annotation"))
             }
         }
 
@@ -90,7 +93,10 @@
             if (target.platformType == KotlinPlatformType.native) {
                 target.compilations["main"].defaultSourceSet {
                     def konanTargetFamily = target.konanTarget.family
-                    if (konanTargetFamily == Family.OSX || konanTargetFamily == Family.IOS) {
+                    if (konanTargetFamily == Family.OSX ||
+                            konanTargetFamily == Family.IOS ||
+                            konanTargetFamily == Family.WATCHOS ||
+                            konanTargetFamily == Family.TVOS) {
                         dependsOn(darwinMain)
                     } else if (konanTargetFamily == Family.LINUX) {
                         dependsOn(linuxMain)
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/FloatFloatMap.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/FloatFloatMap.kt
index 621d621..6824d27 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/FloatFloatMap.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/FloatFloatMap.kt
@@ -868,8 +868,7 @@
      */
     private fun adjustStorage() {
         if (_capacity > GroupWidth && _size.toULong() * 32UL <= _capacity.toULong() * 25UL) {
-            // TODO: Avoid resize and drop deletes instead
-            resizeStorage(nextCapacity(_capacity))
+            removeDeletedMarkers()
         } else {
             resizeStorage(nextCapacity(_capacity))
         }
@@ -899,6 +898,23 @@
         }
     }
 
+    private fun removeDeletedMarkers() {
+        val m = metadata
+        val capacity = _capacity
+        var removedDeletes = 0
+
+        // TODO: this can be done in a more efficient way
+        for (i in 0 until capacity) {
+            val slot = readRawMetadata(m, i)
+            if (slot == Deleted) {
+                writeMetadata(i, Empty)
+                removedDeletes++
+            }
+        }
+
+        growthLimit += removedDeletes
+    }
+
     /**
      * Writes the "H2" part of an entry into the metadata array at the specified [index]. The index
      * must be a valid index. This function ensures the metadata is also written in the clone area
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/FloatFloatPair.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/FloatFloatPair.kt
index 138c250..eeb89fe 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/FloatFloatPair.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/FloatFloatPair.kt
@@ -31,7 +31,10 @@
 @JvmInline
 public value class FloatFloatPair
 internal constructor(
-    /** The internal representation of the [FloatFloatPair]. */
+    /**
+     * The internal representation of the [FloatFloatPair]. [packedValue] has no guarantees for
+     * stability across library versions.
+     */
     @JvmField public val packedValue: Long
 ) {
     /**
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/FloatIntMap.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/FloatIntMap.kt
index d0e7e55..324e0d7 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/FloatIntMap.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/FloatIntMap.kt
@@ -868,8 +868,7 @@
      */
     private fun adjustStorage() {
         if (_capacity > GroupWidth && _size.toULong() * 32UL <= _capacity.toULong() * 25UL) {
-            // TODO: Avoid resize and drop deletes instead
-            resizeStorage(nextCapacity(_capacity))
+            removeDeletedMarkers()
         } else {
             resizeStorage(nextCapacity(_capacity))
         }
@@ -899,6 +898,23 @@
         }
     }
 
+    private fun removeDeletedMarkers() {
+        val m = metadata
+        val capacity = _capacity
+        var removedDeletes = 0
+
+        // TODO: this can be done in a more efficient way
+        for (i in 0 until capacity) {
+            val slot = readRawMetadata(m, i)
+            if (slot == Deleted) {
+                writeMetadata(i, Empty)
+                removedDeletes++
+            }
+        }
+
+        growthLimit += removedDeletes
+    }
+
     /**
      * Writes the "H2" part of an entry into the metadata array at the specified [index]. The index
      * must be a valid index. This function ensures the metadata is also written in the clone area
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/FloatLongMap.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/FloatLongMap.kt
index 014dd71..2f2512f 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/FloatLongMap.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/FloatLongMap.kt
@@ -868,8 +868,7 @@
      */
     private fun adjustStorage() {
         if (_capacity > GroupWidth && _size.toULong() * 32UL <= _capacity.toULong() * 25UL) {
-            // TODO: Avoid resize and drop deletes instead
-            resizeStorage(nextCapacity(_capacity))
+            removeDeletedMarkers()
         } else {
             resizeStorage(nextCapacity(_capacity))
         }
@@ -899,6 +898,23 @@
         }
     }
 
+    private fun removeDeletedMarkers() {
+        val m = metadata
+        val capacity = _capacity
+        var removedDeletes = 0
+
+        // TODO: this can be done in a more efficient way
+        for (i in 0 until capacity) {
+            val slot = readRawMetadata(m, i)
+            if (slot == Deleted) {
+                writeMetadata(i, Empty)
+                removedDeletes++
+            }
+        }
+
+        growthLimit += removedDeletes
+    }
+
     /**
      * Writes the "H2" part of an entry into the metadata array at the specified [index]. The index
      * must be a valid index. This function ensures the metadata is also written in the clone area
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/FloatObjectMap.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/FloatObjectMap.kt
index ee51aba..8582631 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/FloatObjectMap.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/FloatObjectMap.kt
@@ -851,8 +851,7 @@
      */
     private fun adjustStorage() {
         if (_capacity > GroupWidth && _size.toULong() * 32UL <= _capacity.toULong() * 25UL) {
-            // TODO: Avoid resize and drop deletes instead
-            resizeStorage(nextCapacity(_capacity))
+            removeDeletedMarkers()
         } else {
             resizeStorage(nextCapacity(_capacity))
         }
@@ -882,6 +881,23 @@
         }
     }
 
+    private fun removeDeletedMarkers() {
+        val m = metadata
+        val capacity = _capacity
+        var removedDeletes = 0
+
+        // TODO: this can be done in a more efficient way
+        for (i in 0 until capacity) {
+            val slot = readRawMetadata(m, i)
+            if (slot == Deleted) {
+                writeMetadata(i, Empty)
+                removedDeletes++
+            }
+        }
+
+        growthLimit += removedDeletes
+    }
+
     /**
      * Writes the "H2" part of an entry into the metadata array at the specified [index]. The index
      * must be a valid index. This function ensures the metadata is also written in the clone area
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/FloatSet.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/FloatSet.kt
index 154ff82..f8562c57 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/FloatSet.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/FloatSet.kt
@@ -722,8 +722,7 @@
      */
     private fun adjustStorage() {
         if (_capacity > GroupWidth && _size.toULong() * 32UL <= _capacity.toULong() * 25UL) {
-            // TODO: Avoid resize and drop deletes instead
-            resizeStorage(nextCapacity(_capacity))
+            removeDeletedMarkers()
         } else {
             resizeStorage(nextCapacity(_capacity))
         }
@@ -750,6 +749,23 @@
         }
     }
 
+    private fun removeDeletedMarkers() {
+        val m = metadata
+        val capacity = _capacity
+        var removedDeletes = 0
+
+        // TODO: this can be done in a more efficient way
+        for (i in 0 until capacity) {
+            val slot = readRawMetadata(m, i)
+            if (slot == Deleted) {
+                writeMetadata(i, Empty)
+                removedDeletes++
+            }
+        }
+
+        growthLimit += removedDeletes
+    }
+
     /**
      * Writes the "H2" part of an entry into the metadata array at the specified [index]. The index
      * must be a valid index. This function ensures the metadata is also written in the clone area
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/IntFloatMap.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/IntFloatMap.kt
index 8d5f261..71d6bb4 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/IntFloatMap.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/IntFloatMap.kt
@@ -868,8 +868,7 @@
      */
     private fun adjustStorage() {
         if (_capacity > GroupWidth && _size.toULong() * 32UL <= _capacity.toULong() * 25UL) {
-            // TODO: Avoid resize and drop deletes instead
-            resizeStorage(nextCapacity(_capacity))
+            removeDeletedMarkers()
         } else {
             resizeStorage(nextCapacity(_capacity))
         }
@@ -899,6 +898,23 @@
         }
     }
 
+    private fun removeDeletedMarkers() {
+        val m = metadata
+        val capacity = _capacity
+        var removedDeletes = 0
+
+        // TODO: this can be done in a more efficient way
+        for (i in 0 until capacity) {
+            val slot = readRawMetadata(m, i)
+            if (slot == Deleted) {
+                writeMetadata(i, Empty)
+                removedDeletes++
+            }
+        }
+
+        growthLimit += removedDeletes
+    }
+
     /**
      * Writes the "H2" part of an entry into the metadata array at the specified [index]. The index
      * must be a valid index. This function ensures the metadata is also written in the clone area
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/IntIntMap.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/IntIntMap.kt
index 1206d9a..3974053 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/IntIntMap.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/IntIntMap.kt
@@ -868,8 +868,7 @@
      */
     private fun adjustStorage() {
         if (_capacity > GroupWidth && _size.toULong() * 32UL <= _capacity.toULong() * 25UL) {
-            // TODO: Avoid resize and drop deletes instead
-            resizeStorage(nextCapacity(_capacity))
+            removeDeletedMarkers()
         } else {
             resizeStorage(nextCapacity(_capacity))
         }
@@ -899,6 +898,23 @@
         }
     }
 
+    private fun removeDeletedMarkers() {
+        val m = metadata
+        val capacity = _capacity
+        var removedDeletes = 0
+
+        // TODO: this can be done in a more efficient way
+        for (i in 0 until capacity) {
+            val slot = readRawMetadata(m, i)
+            if (slot == Deleted) {
+                writeMetadata(i, Empty)
+                removedDeletes++
+            }
+        }
+
+        growthLimit += removedDeletes
+    }
+
     /**
      * Writes the "H2" part of an entry into the metadata array at the specified [index]. The index
      * must be a valid index. This function ensures the metadata is also written in the clone area
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/IntIntPair.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/IntIntPair.kt
index ad7a88b..2d5bb2c5 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/IntIntPair.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/IntIntPair.kt
@@ -30,7 +30,10 @@
 @JvmInline
 public value class IntIntPair
 internal constructor(
-    /** The internal representation of the [IntIntPair]. */
+    /**
+     * The internal representation of the [IntIntPair]. [packedValue] has no guarantees for
+     * stability across library versions.
+     */
     @JvmField public val packedValue: Long
 ) {
     /**
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/IntLongMap.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/IntLongMap.kt
index c2b5895..b3877d5 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/IntLongMap.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/IntLongMap.kt
@@ -868,8 +868,7 @@
      */
     private fun adjustStorage() {
         if (_capacity > GroupWidth && _size.toULong() * 32UL <= _capacity.toULong() * 25UL) {
-            // TODO: Avoid resize and drop deletes instead
-            resizeStorage(nextCapacity(_capacity))
+            removeDeletedMarkers()
         } else {
             resizeStorage(nextCapacity(_capacity))
         }
@@ -899,6 +898,23 @@
         }
     }
 
+    private fun removeDeletedMarkers() {
+        val m = metadata
+        val capacity = _capacity
+        var removedDeletes = 0
+
+        // TODO: this can be done in a more efficient way
+        for (i in 0 until capacity) {
+            val slot = readRawMetadata(m, i)
+            if (slot == Deleted) {
+                writeMetadata(i, Empty)
+                removedDeletes++
+            }
+        }
+
+        growthLimit += removedDeletes
+    }
+
     /**
      * Writes the "H2" part of an entry into the metadata array at the specified [index]. The index
      * must be a valid index. This function ensures the metadata is also written in the clone area
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/IntObjectMap.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/IntObjectMap.kt
index e5e408b..313d924 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/IntObjectMap.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/IntObjectMap.kt
@@ -851,8 +851,7 @@
      */
     private fun adjustStorage() {
         if (_capacity > GroupWidth && _size.toULong() * 32UL <= _capacity.toULong() * 25UL) {
-            // TODO: Avoid resize and drop deletes instead
-            resizeStorage(nextCapacity(_capacity))
+            removeDeletedMarkers()
         } else {
             resizeStorage(nextCapacity(_capacity))
         }
@@ -882,6 +881,23 @@
         }
     }
 
+    private fun removeDeletedMarkers() {
+        val m = metadata
+        val capacity = _capacity
+        var removedDeletes = 0
+
+        // TODO: this can be done in a more efficient way
+        for (i in 0 until capacity) {
+            val slot = readRawMetadata(m, i)
+            if (slot == Deleted) {
+                writeMetadata(i, Empty)
+                removedDeletes++
+            }
+        }
+
+        growthLimit += removedDeletes
+    }
+
     /**
      * Writes the "H2" part of an entry into the metadata array at the specified [index]. The index
      * must be a valid index. This function ensures the metadata is also written in the clone area
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/IntSet.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/IntSet.kt
index 5ccadfb..8dfe391 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/IntSet.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/IntSet.kt
@@ -720,8 +720,7 @@
      */
     private fun adjustStorage() {
         if (_capacity > GroupWidth && _size.toULong() * 32UL <= _capacity.toULong() * 25UL) {
-            // TODO: Avoid resize and drop deletes instead
-            resizeStorage(nextCapacity(_capacity))
+            removeDeletedMarkers()
         } else {
             resizeStorage(nextCapacity(_capacity))
         }
@@ -748,6 +747,23 @@
         }
     }
 
+    private fun removeDeletedMarkers() {
+        val m = metadata
+        val capacity = _capacity
+        var removedDeletes = 0
+
+        // TODO: this can be done in a more efficient way
+        for (i in 0 until capacity) {
+            val slot = readRawMetadata(m, i)
+            if (slot == Deleted) {
+                writeMetadata(i, Empty)
+                removedDeletes++
+            }
+        }
+
+        growthLimit += removedDeletes
+    }
+
     /**
      * Writes the "H2" part of an entry into the metadata array at the specified [index]. The index
      * must be a valid index. This function ensures the metadata is also written in the clone area
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/LongFloatMap.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/LongFloatMap.kt
index ba4f8aa..ba21fb5 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/LongFloatMap.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/LongFloatMap.kt
@@ -868,8 +868,7 @@
      */
     private fun adjustStorage() {
         if (_capacity > GroupWidth && _size.toULong() * 32UL <= _capacity.toULong() * 25UL) {
-            // TODO: Avoid resize and drop deletes instead
-            resizeStorage(nextCapacity(_capacity))
+            removeDeletedMarkers()
         } else {
             resizeStorage(nextCapacity(_capacity))
         }
@@ -899,6 +898,23 @@
         }
     }
 
+    private fun removeDeletedMarkers() {
+        val m = metadata
+        val capacity = _capacity
+        var removedDeletes = 0
+
+        // TODO: this can be done in a more efficient way
+        for (i in 0 until capacity) {
+            val slot = readRawMetadata(m, i)
+            if (slot == Deleted) {
+                writeMetadata(i, Empty)
+                removedDeletes++
+            }
+        }
+
+        growthLimit += removedDeletes
+    }
+
     /**
      * Writes the "H2" part of an entry into the metadata array at the specified [index]. The index
      * must be a valid index. This function ensures the metadata is also written in the clone area
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/LongIntMap.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/LongIntMap.kt
index 19f417b..9e986ac 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/LongIntMap.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/LongIntMap.kt
@@ -868,8 +868,7 @@
      */
     private fun adjustStorage() {
         if (_capacity > GroupWidth && _size.toULong() * 32UL <= _capacity.toULong() * 25UL) {
-            // TODO: Avoid resize and drop deletes instead
-            resizeStorage(nextCapacity(_capacity))
+            removeDeletedMarkers()
         } else {
             resizeStorage(nextCapacity(_capacity))
         }
@@ -899,6 +898,23 @@
         }
     }
 
+    private fun removeDeletedMarkers() {
+        val m = metadata
+        val capacity = _capacity
+        var removedDeletes = 0
+
+        // TODO: this can be done in a more efficient way
+        for (i in 0 until capacity) {
+            val slot = readRawMetadata(m, i)
+            if (slot == Deleted) {
+                writeMetadata(i, Empty)
+                removedDeletes++
+            }
+        }
+
+        growthLimit += removedDeletes
+    }
+
     /**
      * Writes the "H2" part of an entry into the metadata array at the specified [index]. The index
      * must be a valid index. This function ensures the metadata is also written in the clone area
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/LongLongMap.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/LongLongMap.kt
index 4a9d99b..52ad2ef 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/LongLongMap.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/LongLongMap.kt
@@ -868,8 +868,7 @@
      */
     private fun adjustStorage() {
         if (_capacity > GroupWidth && _size.toULong() * 32UL <= _capacity.toULong() * 25UL) {
-            // TODO: Avoid resize and drop deletes instead
-            resizeStorage(nextCapacity(_capacity))
+            removeDeletedMarkers()
         } else {
             resizeStorage(nextCapacity(_capacity))
         }
@@ -899,6 +898,23 @@
         }
     }
 
+    private fun removeDeletedMarkers() {
+        val m = metadata
+        val capacity = _capacity
+        var removedDeletes = 0
+
+        // TODO: this can be done in a more efficient way
+        for (i in 0 until capacity) {
+            val slot = readRawMetadata(m, i)
+            if (slot == Deleted) {
+                writeMetadata(i, Empty)
+                removedDeletes++
+            }
+        }
+
+        growthLimit += removedDeletes
+    }
+
     /**
      * Writes the "H2" part of an entry into the metadata array at the specified [index]. The index
      * must be a valid index. This function ensures the metadata is also written in the clone area
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/LongObjectMap.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/LongObjectMap.kt
index a175b7a..aed8484 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/LongObjectMap.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/LongObjectMap.kt
@@ -851,8 +851,7 @@
      */
     private fun adjustStorage() {
         if (_capacity > GroupWidth && _size.toULong() * 32UL <= _capacity.toULong() * 25UL) {
-            // TODO: Avoid resize and drop deletes instead
-            resizeStorage(nextCapacity(_capacity))
+            removeDeletedMarkers()
         } else {
             resizeStorage(nextCapacity(_capacity))
         }
@@ -882,6 +881,23 @@
         }
     }
 
+    private fun removeDeletedMarkers() {
+        val m = metadata
+        val capacity = _capacity
+        var removedDeletes = 0
+
+        // TODO: this can be done in a more efficient way
+        for (i in 0 until capacity) {
+            val slot = readRawMetadata(m, i)
+            if (slot == Deleted) {
+                writeMetadata(i, Empty)
+                removedDeletes++
+            }
+        }
+
+        growthLimit += removedDeletes
+    }
+
     /**
      * Writes the "H2" part of an entry into the metadata array at the specified [index]. The index
      * must be a valid index. This function ensures the metadata is also written in the clone area
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/LongSet.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/LongSet.kt
index 6458cac..cdf0b3e 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/LongSet.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/LongSet.kt
@@ -721,8 +721,7 @@
      */
     private fun adjustStorage() {
         if (_capacity > GroupWidth && _size.toULong() * 32UL <= _capacity.toULong() * 25UL) {
-            // TODO: Avoid resize and drop deletes instead
-            resizeStorage(nextCapacity(_capacity))
+            removeDeletedMarkers()
         } else {
             resizeStorage(nextCapacity(_capacity))
         }
@@ -749,6 +748,23 @@
         }
     }
 
+    private fun removeDeletedMarkers() {
+        val m = metadata
+        val capacity = _capacity
+        var removedDeletes = 0
+
+        // TODO: this can be done in a more efficient way
+        for (i in 0 until capacity) {
+            val slot = readRawMetadata(m, i)
+            if (slot == Deleted) {
+                writeMetadata(i, Empty)
+                removedDeletes++
+            }
+        }
+
+        growthLimit += removedDeletes
+    }
+
     /**
      * Writes the "H2" part of an entry into the metadata array at the specified [index]. The index
      * must be a valid index. This function ensures the metadata is also written in the clone area
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/ObjectFloatMap.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/ObjectFloatMap.kt
index e167cc1..2928542 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/ObjectFloatMap.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/ObjectFloatMap.kt
@@ -884,8 +884,7 @@
      */
     private fun adjustStorage() {
         if (_capacity > GroupWidth && _size.toULong() * 32UL <= _capacity.toULong() * 25UL) {
-            // TODO: Avoid resize and drop deletes instead
-            resizeStorage(nextCapacity(_capacity))
+            removeDeletedMarkers()
         } else {
             resizeStorage(nextCapacity(_capacity))
         }
@@ -915,6 +914,23 @@
         }
     }
 
+    private fun removeDeletedMarkers() {
+        val m = metadata
+        val capacity = _capacity
+        var removedDeletes = 0
+
+        // TODO: this can be done in a more efficient way
+        for (i in 0 until capacity) {
+            val slot = readRawMetadata(m, i)
+            if (slot == Deleted) {
+                writeMetadata(i, Empty)
+                removedDeletes++
+            }
+        }
+
+        growthLimit += removedDeletes
+    }
+
     /**
      * Writes the "H2" part of an entry into the metadata array at the specified [index]. The index
      * must be a valid index. This function ensures the metadata is also written in the clone area
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/ObjectIntMap.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/ObjectIntMap.kt
index 39e299f..4d416d88 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/ObjectIntMap.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/ObjectIntMap.kt
@@ -884,8 +884,7 @@
      */
     private fun adjustStorage() {
         if (_capacity > GroupWidth && _size.toULong() * 32UL <= _capacity.toULong() * 25UL) {
-            // TODO: Avoid resize and drop deletes instead
-            resizeStorage(nextCapacity(_capacity))
+            removeDeletedMarkers()
         } else {
             resizeStorage(nextCapacity(_capacity))
         }
@@ -915,6 +914,23 @@
         }
     }
 
+    private fun removeDeletedMarkers() {
+        val m = metadata
+        val capacity = _capacity
+        var removedDeletes = 0
+
+        // TODO: this can be done in a more efficient way
+        for (i in 0 until capacity) {
+            val slot = readRawMetadata(m, i)
+            if (slot == Deleted) {
+                writeMetadata(i, Empty)
+                removedDeletes++
+            }
+        }
+
+        growthLimit += removedDeletes
+    }
+
     /**
      * Writes the "H2" part of an entry into the metadata array at the specified [index]. The index
      * must be a valid index. This function ensures the metadata is also written in the clone area
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/ObjectLongMap.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/ObjectLongMap.kt
index 48f278d..9fe0b65 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/ObjectLongMap.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/ObjectLongMap.kt
@@ -884,8 +884,7 @@
      */
     private fun adjustStorage() {
         if (_capacity > GroupWidth && _size.toULong() * 32UL <= _capacity.toULong() * 25UL) {
-            // TODO: Avoid resize and drop deletes instead
-            resizeStorage(nextCapacity(_capacity))
+            removeDeletedMarkers()
         } else {
             resizeStorage(nextCapacity(_capacity))
         }
@@ -915,6 +914,23 @@
         }
     }
 
+    private fun removeDeletedMarkers() {
+        val m = metadata
+        val capacity = _capacity
+        var removedDeletes = 0
+
+        // TODO: this can be done in a more efficient way
+        for (i in 0 until capacity) {
+            val slot = readRawMetadata(m, i)
+            if (slot == Deleted) {
+                writeMetadata(i, Empty)
+                removedDeletes++
+            }
+        }
+
+        growthLimit += removedDeletes
+    }
+
     /**
      * Writes the "H2" part of an entry into the metadata array at the specified [index]. The index
      * must be a valid index. This function ensures the metadata is also written in the clone area
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/ScatterMap.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/ScatterMap.kt
index 0665f13..023e31a 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/ScatterMap.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/ScatterMap.kt
@@ -1096,8 +1096,7 @@
      */
     private fun adjustStorage() {
         if (_capacity > GroupWidth && _size.toULong() * 32UL <= _capacity.toULong() * 25UL) {
-            // TODO: Avoid resize and drop deletes instead
-            resizeStorage(nextCapacity(_capacity))
+            resizeStorage(_capacity)
         } else {
             resizeStorage(nextCapacity(_capacity))
         }
@@ -1127,6 +1126,23 @@
         }
     }
 
+    private fun removeDeletedMarkers() {
+        val m = metadata
+        val capacity = _capacity
+        var removedDeletes = 0
+
+        // TODO: this can be done in a more efficient way
+        for (i in 0 until capacity) {
+            val slot = readRawMetadata(m, i)
+            if (slot == Deleted) {
+                writeMetadata(i, Empty)
+                removedDeletes++
+            }
+        }
+
+        growthLimit += removedDeletes
+    }
+
     /**
      * Writes the "H2" part of an entry into the metadata array at the specified [index]. The index
      * must be a valid index. This function ensures the metadata is also written in the clone area
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/ScatterSet.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/ScatterSet.kt
index 0b100ad0..c393eef 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/ScatterSet.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/ScatterSet.kt
@@ -901,8 +901,7 @@
      */
     private fun adjustStorage() {
         if (_capacity > GroupWidth && _size.toULong() * 32UL <= _capacity.toULong() * 25UL) {
-            // TODO: Avoid resize and drop deletes instead
-            resizeStorage(nextCapacity(_capacity))
+            removeDeletedMarkers()
         } else {
             resizeStorage(nextCapacity(_capacity))
         }
@@ -929,6 +928,23 @@
         }
     }
 
+    private fun removeDeletedMarkers() {
+        val m = metadata
+        val capacity = _capacity
+        var removedDeletes = 0
+
+        // TODO: this can be done in a more efficient way
+        for (i in 0 until capacity) {
+            val slot = readRawMetadata(m, i)
+            if (slot == Deleted) {
+                writeMetadata(i, Empty)
+                removedDeletes++
+            }
+        }
+
+        growthLimit += removedDeletes
+    }
+
     /**
      * Writes the "H2" part of an entry into the metadata array at the specified [index]. The index
      * must be a valid index. This function ensures the metadata is also written in the clone area
diff --git a/collection/collection/src/commonTest/kotlin/androidx/collection/FloatFloatMapTest.kt b/collection/collection/src/commonTest/kotlin/androidx/collection/FloatFloatMapTest.kt
index 5ada538..c6b52ef 100644
--- a/collection/collection/src/commonTest/kotlin/androidx/collection/FloatFloatMapTest.kt
+++ b/collection/collection/src/commonTest/kotlin/androidx/collection/FloatFloatMapTest.kt
@@ -750,4 +750,15 @@
         assertEquals(1024, map.trim())
         assertEquals(0, map.trim())
     }
+
+    @Test
+    fun insertManyRemoveMany() {
+        val map = MutableFloatFloatMap()
+
+        for (i in 0..1000000) {
+            map[i.toFloat()] = i.toFloat()
+            map.remove(i.toFloat())
+            assertTrue(map.capacity < 16, "Map grew larger than 16 after step $i")
+        }
+    }
 }
diff --git a/collection/collection/src/commonTest/kotlin/androidx/collection/FloatIntMapTest.kt b/collection/collection/src/commonTest/kotlin/androidx/collection/FloatIntMapTest.kt
index 10bbd69..4d99c61 100644
--- a/collection/collection/src/commonTest/kotlin/androidx/collection/FloatIntMapTest.kt
+++ b/collection/collection/src/commonTest/kotlin/androidx/collection/FloatIntMapTest.kt
@@ -750,4 +750,15 @@
         assertEquals(1024, map.trim())
         assertEquals(0, map.trim())
     }
+
+    @Test
+    fun insertManyRemoveMany() {
+        val map = MutableFloatIntMap()
+
+        for (i in 0..1000000) {
+            map[i.toFloat()] = i.toInt()
+            map.remove(i.toFloat())
+            assertTrue(map.capacity < 16, "Map grew larger than 16 after step $i")
+        }
+    }
 }
diff --git a/collection/collection/src/commonTest/kotlin/androidx/collection/FloatLongMapTest.kt b/collection/collection/src/commonTest/kotlin/androidx/collection/FloatLongMapTest.kt
index 528d5c2..6029c51 100644
--- a/collection/collection/src/commonTest/kotlin/androidx/collection/FloatLongMapTest.kt
+++ b/collection/collection/src/commonTest/kotlin/androidx/collection/FloatLongMapTest.kt
@@ -750,4 +750,15 @@
         assertEquals(1024, map.trim())
         assertEquals(0, map.trim())
     }
+
+    @Test
+    fun insertManyRemoveMany() {
+        val map = MutableFloatLongMap()
+
+        for (i in 0..1000000) {
+            map[i.toFloat()] = i.toLong()
+            map.remove(i.toFloat())
+            assertTrue(map.capacity < 16, "Map grew larger than 16 after step $i")
+        }
+    }
 }
diff --git a/collection/collection/src/commonTest/kotlin/androidx/collection/FloatObjectMapTest.kt b/collection/collection/src/commonTest/kotlin/androidx/collection/FloatObjectMapTest.kt
index c496da0..572dd68 100644
--- a/collection/collection/src/commonTest/kotlin/androidx/collection/FloatObjectMapTest.kt
+++ b/collection/collection/src/commonTest/kotlin/androidx/collection/FloatObjectMapTest.kt
@@ -765,4 +765,15 @@
         assertTrue(map.all { key, value -> key < 7f && value.isNotEmpty() })
         assertFalse(map.all { key, _ -> key < 6f })
     }
+
+    @Test
+    fun insertManyRemoveMany() {
+        val map = MutableFloatObjectMap<String>()
+
+        for (i in 0..1000000) {
+            map[i.toFloat()] = i.toString()
+            map.remove(i.toFloat())
+            assertTrue(map.capacity < 16, "Map grew larger than 16 after step $i")
+        }
+    }
 }
diff --git a/collection/collection/src/commonTest/kotlin/androidx/collection/FloatSetTest.kt b/collection/collection/src/commonTest/kotlin/androidx/collection/FloatSetTest.kt
index c4df752..e5a105e 100644
--- a/collection/collection/src/commonTest/kotlin/androidx/collection/FloatSetTest.kt
+++ b/collection/collection/src/commonTest/kotlin/androidx/collection/FloatSetTest.kt
@@ -550,4 +550,15 @@
         assertTrue(4f in set)
         assertFalse(5f in set)
     }
+
+    @Test
+    fun insertManyRemoveMany() {
+        val set = mutableFloatSetOf()
+
+        for (i in 0..1000000) {
+            set.add(i.toFloat())
+            set.remove(i.toFloat())
+            assertTrue(set.capacity < 16, "Set grew larger than 16 after step $i")
+        }
+    }
 }
diff --git a/collection/collection/src/commonTest/kotlin/androidx/collection/IntFloatMapTest.kt b/collection/collection/src/commonTest/kotlin/androidx/collection/IntFloatMapTest.kt
index a23a57c..cf9a934 100644
--- a/collection/collection/src/commonTest/kotlin/androidx/collection/IntFloatMapTest.kt
+++ b/collection/collection/src/commonTest/kotlin/androidx/collection/IntFloatMapTest.kt
@@ -750,4 +750,15 @@
         assertEquals(1024, map.trim())
         assertEquals(0, map.trim())
     }
+
+    @Test
+    fun insertManyRemoveMany() {
+        val map = MutableIntFloatMap()
+
+        for (i in 0..1000000) {
+            map[i.toInt()] = i.toFloat()
+            map.remove(i.toInt())
+            assertTrue(map.capacity < 16, "Map grew larger than 16 after step $i")
+        }
+    }
 }
diff --git a/collection/collection/src/commonTest/kotlin/androidx/collection/IntIntMapTest.kt b/collection/collection/src/commonTest/kotlin/androidx/collection/IntIntMapTest.kt
index 693276d5..b7d318b 100644
--- a/collection/collection/src/commonTest/kotlin/androidx/collection/IntIntMapTest.kt
+++ b/collection/collection/src/commonTest/kotlin/androidx/collection/IntIntMapTest.kt
@@ -750,4 +750,15 @@
         assertEquals(1024, map.trim())
         assertEquals(0, map.trim())
     }
+
+    @Test
+    fun insertManyRemoveMany() {
+        val map = MutableIntIntMap()
+
+        for (i in 0..1000000) {
+            map[i.toInt()] = i.toInt()
+            map.remove(i.toInt())
+            assertTrue(map.capacity < 16, "Map grew larger than 16 after step $i")
+        }
+    }
 }
diff --git a/collection/collection/src/commonTest/kotlin/androidx/collection/IntLongMapTest.kt b/collection/collection/src/commonTest/kotlin/androidx/collection/IntLongMapTest.kt
index d759538..e115dc6 100644
--- a/collection/collection/src/commonTest/kotlin/androidx/collection/IntLongMapTest.kt
+++ b/collection/collection/src/commonTest/kotlin/androidx/collection/IntLongMapTest.kt
@@ -750,4 +750,15 @@
         assertEquals(1024, map.trim())
         assertEquals(0, map.trim())
     }
+
+    @Test
+    fun insertManyRemoveMany() {
+        val map = MutableIntLongMap()
+
+        for (i in 0..1000000) {
+            map[i.toInt()] = i.toLong()
+            map.remove(i.toInt())
+            assertTrue(map.capacity < 16, "Map grew larger than 16 after step $i")
+        }
+    }
 }
diff --git a/collection/collection/src/commonTest/kotlin/androidx/collection/IntObjectMapTest.kt b/collection/collection/src/commonTest/kotlin/androidx/collection/IntObjectMapTest.kt
index 3be1f8cc..9d002e6 100644
--- a/collection/collection/src/commonTest/kotlin/androidx/collection/IntObjectMapTest.kt
+++ b/collection/collection/src/commonTest/kotlin/androidx/collection/IntObjectMapTest.kt
@@ -765,4 +765,15 @@
         assertTrue(map.all { key, value -> key < 7 && value.isNotEmpty() })
         assertFalse(map.all { key, _ -> key < 6 })
     }
+
+    @Test
+    fun insertManyRemoveMany() {
+        val map = MutableIntObjectMap<String>()
+
+        for (i in 0..1000000) {
+            map[i.toInt()] = i.toString()
+            map.remove(i.toInt())
+            assertTrue(map.capacity < 16, "Map grew larger than 16 after step $i")
+        }
+    }
 }
diff --git a/collection/collection/src/commonTest/kotlin/androidx/collection/IntSetTest.kt b/collection/collection/src/commonTest/kotlin/androidx/collection/IntSetTest.kt
index fd2de76..66c30d3 100644
--- a/collection/collection/src/commonTest/kotlin/androidx/collection/IntSetTest.kt
+++ b/collection/collection/src/commonTest/kotlin/androidx/collection/IntSetTest.kt
@@ -550,4 +550,15 @@
         assertTrue(4 in set)
         assertFalse(5 in set)
     }
+
+    @Test
+    fun insertManyRemoveMany() {
+        val set = mutableIntSetOf()
+
+        for (i in 0..1000000) {
+            set.add(i.toInt())
+            set.remove(i.toInt())
+            assertTrue(set.capacity < 16, "Set grew larger than 16 after step $i")
+        }
+    }
 }
diff --git a/collection/collection/src/commonTest/kotlin/androidx/collection/LongFloatMapTest.kt b/collection/collection/src/commonTest/kotlin/androidx/collection/LongFloatMapTest.kt
index 2312c61..507ddf0 100644
--- a/collection/collection/src/commonTest/kotlin/androidx/collection/LongFloatMapTest.kt
+++ b/collection/collection/src/commonTest/kotlin/androidx/collection/LongFloatMapTest.kt
@@ -750,4 +750,15 @@
         assertEquals(1024, map.trim())
         assertEquals(0, map.trim())
     }
+
+    @Test
+    fun insertManyRemoveMany() {
+        val map = MutableLongFloatMap()
+
+        for (i in 0..1000000) {
+            map[i.toLong()] = i.toFloat()
+            map.remove(i.toLong())
+            assertTrue(map.capacity < 16, "Map grew larger than 16 after step $i")
+        }
+    }
 }
diff --git a/collection/collection/src/commonTest/kotlin/androidx/collection/LongIntMapTest.kt b/collection/collection/src/commonTest/kotlin/androidx/collection/LongIntMapTest.kt
index 1680c00..75488a2 100644
--- a/collection/collection/src/commonTest/kotlin/androidx/collection/LongIntMapTest.kt
+++ b/collection/collection/src/commonTest/kotlin/androidx/collection/LongIntMapTest.kt
@@ -750,4 +750,15 @@
         assertEquals(1024, map.trim())
         assertEquals(0, map.trim())
     }
+
+    @Test
+    fun insertManyRemoveMany() {
+        val map = MutableLongIntMap()
+
+        for (i in 0..1000000) {
+            map[i.toLong()] = i.toInt()
+            map.remove(i.toLong())
+            assertTrue(map.capacity < 16, "Map grew larger than 16 after step $i")
+        }
+    }
 }
diff --git a/collection/collection/src/commonTest/kotlin/androidx/collection/LongLongMapTest.kt b/collection/collection/src/commonTest/kotlin/androidx/collection/LongLongMapTest.kt
index 112cc33..a22631b 100644
--- a/collection/collection/src/commonTest/kotlin/androidx/collection/LongLongMapTest.kt
+++ b/collection/collection/src/commonTest/kotlin/androidx/collection/LongLongMapTest.kt
@@ -750,4 +750,15 @@
         assertEquals(1024, map.trim())
         assertEquals(0, map.trim())
     }
+
+    @Test
+    fun insertManyRemoveMany() {
+        val map = MutableLongLongMap()
+
+        for (i in 0..1000000) {
+            map[i.toLong()] = i.toLong()
+            map.remove(i.toLong())
+            assertTrue(map.capacity < 16, "Map grew larger than 16 after step $i")
+        }
+    }
 }
diff --git a/collection/collection/src/commonTest/kotlin/androidx/collection/LongObjectMapTest.kt b/collection/collection/src/commonTest/kotlin/androidx/collection/LongObjectMapTest.kt
index 6695519..f8be517 100644
--- a/collection/collection/src/commonTest/kotlin/androidx/collection/LongObjectMapTest.kt
+++ b/collection/collection/src/commonTest/kotlin/androidx/collection/LongObjectMapTest.kt
@@ -765,4 +765,15 @@
         assertTrue(map.all { key, value -> key < 7L && value.isNotEmpty() })
         assertFalse(map.all { key, _ -> key < 6L })
     }
+
+    @Test
+    fun insertManyRemoveMany() {
+        val map = MutableLongObjectMap<String>()
+
+        for (i in 0..1000000) {
+            map[i.toLong()] = i.toString()
+            map.remove(i.toLong())
+            assertTrue(map.capacity < 16, "Map grew larger than 16 after step $i")
+        }
+    }
 }
diff --git a/collection/collection/src/commonTest/kotlin/androidx/collection/LongSetTest.kt b/collection/collection/src/commonTest/kotlin/androidx/collection/LongSetTest.kt
index 71564a1..dc5b7e7 100644
--- a/collection/collection/src/commonTest/kotlin/androidx/collection/LongSetTest.kt
+++ b/collection/collection/src/commonTest/kotlin/androidx/collection/LongSetTest.kt
@@ -550,4 +550,15 @@
         assertTrue(4L in set)
         assertFalse(5L in set)
     }
+
+    @Test
+    fun insertManyRemoveMany() {
+        val set = mutableLongSetOf()
+
+        for (i in 0..1000000) {
+            set.add(i.toLong())
+            set.remove(i.toLong())
+            assertTrue(set.capacity < 16, "Set grew larger than 16 after step $i")
+        }
+    }
 }
diff --git a/collection/collection/src/commonTest/kotlin/androidx/collection/ObjectFloatMapTest.kt b/collection/collection/src/commonTest/kotlin/androidx/collection/ObjectFloatMapTest.kt
index 0c19aab..90244ab 100644
--- a/collection/collection/src/commonTest/kotlin/androidx/collection/ObjectFloatMapTest.kt
+++ b/collection/collection/src/commonTest/kotlin/androidx/collection/ObjectFloatMapTest.kt
@@ -775,4 +775,15 @@
         assertEquals(1024, map.trim())
         assertEquals(0, map.trim())
     }
+
+    @Test
+    fun insertManyRemoveMany() {
+        val map = MutableObjectFloatMap<Int>()
+
+        for (i in 0..1000000) {
+            map[i] = i.toFloat()
+            map.remove(i)
+            assertTrue(map.capacity < 16, "Map grew larger than 16 after step $i")
+        }
+    }
 }
diff --git a/collection/collection/src/commonTest/kotlin/androidx/collection/ObjectIntMapTest.kt b/collection/collection/src/commonTest/kotlin/androidx/collection/ObjectIntMapTest.kt
index b70d05bd..bc640eb 100644
--- a/collection/collection/src/commonTest/kotlin/androidx/collection/ObjectIntMapTest.kt
+++ b/collection/collection/src/commonTest/kotlin/androidx/collection/ObjectIntMapTest.kt
@@ -775,4 +775,15 @@
         assertEquals(1024, map.trim())
         assertEquals(0, map.trim())
     }
+
+    @Test
+    fun insertManyRemoveMany() {
+        val map = MutableObjectIntMap<Int>()
+
+        for (i in 0..1000000) {
+            map[i] = i.toInt()
+            map.remove(i)
+            assertTrue(map.capacity < 16, "Map grew larger than 16 after step $i")
+        }
+    }
 }
diff --git a/collection/collection/src/commonTest/kotlin/androidx/collection/ObjectLongMapTest.kt b/collection/collection/src/commonTest/kotlin/androidx/collection/ObjectLongMapTest.kt
index 594729d3..f728b95 100644
--- a/collection/collection/src/commonTest/kotlin/androidx/collection/ObjectLongMapTest.kt
+++ b/collection/collection/src/commonTest/kotlin/androidx/collection/ObjectLongMapTest.kt
@@ -775,4 +775,15 @@
         assertEquals(1024, map.trim())
         assertEquals(0, map.trim())
     }
+
+    @Test
+    fun insertManyRemoveMany() {
+        val map = MutableObjectLongMap<Int>()
+
+        for (i in 0..1000000) {
+            map[i] = i.toLong()
+            map.remove(i)
+            assertTrue(map.capacity < 16, "Map grew larger than 16 after step $i")
+        }
+    }
 }
diff --git a/collection/collection/src/commonTest/kotlin/androidx/collection/ScatterMapTest.kt b/collection/collection/src/commonTest/kotlin/androidx/collection/ScatterMapTest.kt
index 05430d4..dd370fc 100644
--- a/collection/collection/src/commonTest/kotlin/androidx/collection/ScatterMapTest.kt
+++ b/collection/collection/src/commonTest/kotlin/androidx/collection/ScatterMapTest.kt
@@ -1394,4 +1394,53 @@
         assertEquals(1024, map.trim())
         assertEquals(0, map.trim())
     }
+
+    @Test
+    fun insertOneRemoveOne() {
+        val map = MutableScatterMap<Int, String>()
+
+        for (i in 0..1000000) {
+            map[i] = i.toString()
+            map.remove(i)
+            assertTrue(map.capacity < 16, "Map grew larger than 16 after step $i")
+        }
+    }
+
+    @Test
+    fun insertManyRemoveMany() {
+        val map = MutableScatterMap<Int, String>()
+
+        for (i in 0..100) {
+            map[i] = i.toString()
+        }
+
+        for (i in 0..100) {
+            if (i % 2 == 0) {
+                map.remove(i)
+            }
+        }
+
+        for (i in 0..100) {
+            if (i % 2 == 0) {
+                map[i] = i.toString()
+            }
+        }
+
+        for (i in 0..100) {
+            if (i % 2 != 0) {
+                map.remove(i)
+            }
+        }
+
+        for (i in 0..100) {
+            if (i % 2 != 0) {
+                map[i] = i.toString()
+            }
+        }
+
+        assertEquals(127, map.capacity)
+        for (i in 0..100) {
+            assertTrue(map.contains(i), "Map should contain element $i")
+        }
+    }
 }
diff --git a/collection/collection/src/commonTest/kotlin/androidx/collection/ScatterSetTest.kt b/collection/collection/src/commonTest/kotlin/androidx/collection/ScatterSetTest.kt
index c7879ee..721d993 100644
--- a/collection/collection/src/commonTest/kotlin/androidx/collection/ScatterSetTest.kt
+++ b/collection/collection/src/commonTest/kotlin/androidx/collection/ScatterSetTest.kt
@@ -821,4 +821,53 @@
         assertTrue(set.contains("Ciao"))
         assertTrue(set.contains("Annyeong"))
     }
+
+    @Test
+    fun insertOneRemoveOne() {
+        val set = MutableScatterSet<Int>()
+
+        for (i in 0..1000000) {
+            set.add(i)
+            set.remove(i)
+            assertTrue(set.capacity < 16, "Set grew larger than 16 after step $i")
+        }
+    }
+
+    @Test
+    fun insertManyRemoveMany() {
+        val map = MutableScatterMap<Int, String>()
+
+        for (i in 0..100) {
+            map[i] = i.toString()
+        }
+
+        for (i in 0..100) {
+            if (i % 2 == 0) {
+                map.remove(i)
+            }
+        }
+
+        for (i in 0..100) {
+            if (i % 2 == 0) {
+                map[i] = i.toString()
+            }
+        }
+
+        for (i in 0..100) {
+            if (i % 2 != 0) {
+                map.remove(i)
+            }
+        }
+
+        for (i in 0..100) {
+            if (i % 2 != 0) {
+                map[i] = i.toString()
+            }
+        }
+
+        assertEquals(127, map.capacity)
+        for (i in 0..100) {
+            assertTrue(map.contains(i), "Map should contain element $i")
+        }
+    }
 }
diff --git a/collection/collection/template/ObjectPValueMap.kt.template b/collection/collection/template/ObjectPValueMap.kt.template
index 1218b2d..5376d2f 100644
--- a/collection/collection/template/ObjectPValueMap.kt.template
+++ b/collection/collection/template/ObjectPValueMap.kt.template
@@ -1008,8 +1008,7 @@
      */
     private fun adjustStorage() {
         if (_capacity > GroupWidth && _size.toULong() * 32UL <= _capacity.toULong() * 25UL) {
-            // TODO: Avoid resize and drop deletes instead
-            resizeStorage(nextCapacity(_capacity))
+            removeDeletedMarkers()
         } else {
             resizeStorage(nextCapacity(_capacity))
         }
@@ -1039,6 +1038,23 @@
         }
     }
 
+    private fun removeDeletedMarkers() {
+        val m = metadata
+        val capacity = _capacity
+        var removedDeletes = 0
+
+        // TODO: this can be done in a more efficient way
+        for (i in 0 until capacity) {
+            val slot = readRawMetadata(m, i)
+            if (slot == Deleted) {
+                writeMetadata(i, Empty)
+                removedDeletes++
+            }
+        }
+
+        growthLimit += removedDeletes
+    }
+
     /**
      * Writes the "H2" part of an entry into the metadata array at the specified
      * [index]. The index must be a valid index. This function ensures the
diff --git a/collection/collection/template/ObjectPValueMapTest.kt.template b/collection/collection/template/ObjectPValueMapTest.kt.template
index f4c9fa5..988abb3 100644
--- a/collection/collection/template/ObjectPValueMapTest.kt.template
+++ b/collection/collection/template/ObjectPValueMapTest.kt.template
@@ -741,4 +741,18 @@
         assertEquals(1024, map.trim())
         assertEquals(0, map.trim())
     }
+
+    @Test
+    fun insertManyRemoveMany() {
+        val map = MutableObjectPValueMap<Int>()
+
+        for (i in 0 .. 1000000) {
+            map[i] = i.toPValue()
+            map.remove(i)
+            assertTrue(
+                map.capacity < 16,
+                "Map grew larger than 16 after step $i"
+            )
+        }
+    }
 }
diff --git a/collection/collection/template/PKeyObjectMap.kt.template b/collection/collection/template/PKeyObjectMap.kt.template
index b6740c0..5cf7ee5 100644
--- a/collection/collection/template/PKeyObjectMap.kt.template
+++ b/collection/collection/template/PKeyObjectMap.kt.template
@@ -968,8 +968,7 @@
      */
     private fun adjustStorage() {
         if (_capacity > GroupWidth && _size.toULong() * 32UL <= _capacity.toULong() * 25UL) {
-            // TODO: Avoid resize and drop deletes instead
-            resizeStorage(nextCapacity(_capacity))
+            removeDeletedMarkers()
         } else {
             resizeStorage(nextCapacity(_capacity))
         }
@@ -999,6 +998,23 @@
         }
     }
 
+    private fun removeDeletedMarkers() {
+        val m = metadata
+        val capacity = _capacity
+        var removedDeletes = 0
+
+        // TODO: this can be done in a more efficient way
+        for (i in 0 until capacity) {
+            val slot = readRawMetadata(m, i)
+            if (slot == Deleted) {
+                writeMetadata(i, Empty)
+                removedDeletes++
+            }
+        }
+
+        growthLimit += removedDeletes
+    }
+
     /**
      * Writes the "H2" part of an entry into the metadata array at the specified
      * [index]. The index must be a valid index. This function ensures the
diff --git a/collection/collection/template/PKeyObjectMapTest.kt.template b/collection/collection/template/PKeyObjectMapTest.kt.template
index 024c9d6..ea5cfb8 100644
--- a/collection/collection/template/PKeyObjectMapTest.kt.template
+++ b/collection/collection/template/PKeyObjectMapTest.kt.template
@@ -731,4 +731,18 @@
         assertTrue(map.all { key, value -> key < 7KeySuffix && value.isNotEmpty() })
         assertFalse(map.all { key, _ -> key < 6KeySuffix })
     }
+
+    @Test
+    fun insertManyRemoveMany() {
+        val map = MutablePKeyObjectMap<String>()
+
+        for (i in 0 .. 1000000) {
+            map[i.toPKey()] = i.toString()
+            map.remove(i.toPKey())
+            assertTrue(
+                map.capacity < 16,
+                "Map grew larger than 16 after step $i"
+            )
+        }
+    }
 }
diff --git a/collection/collection/template/PKeyPValueMap.kt.template b/collection/collection/template/PKeyPValueMap.kt.template
index 2da7dd1..d8bff84 100644
--- a/collection/collection/template/PKeyPValueMap.kt.template
+++ b/collection/collection/template/PKeyPValueMap.kt.template
@@ -981,8 +981,7 @@
      */
     private fun adjustStorage() {
         if (_capacity > GroupWidth && _size.toULong() * 32UL <= _capacity.toULong() * 25UL) {
-            // TODO: Avoid resize and drop deletes instead
-            resizeStorage(nextCapacity(_capacity))
+            removeDeletedMarkers()
         } else {
             resizeStorage(nextCapacity(_capacity))
         }
@@ -1012,6 +1011,23 @@
         }
     }
 
+    private fun removeDeletedMarkers() {
+        val m = metadata
+        val capacity = _capacity
+        var removedDeletes = 0
+
+        // TODO: this can be done in a more efficient way
+        for (i in 0 until capacity) {
+            val slot = readRawMetadata(m, i)
+            if (slot == Deleted) {
+                writeMetadata(i, Empty)
+                removedDeletes++
+            }
+        }
+
+        growthLimit += removedDeletes
+    }
+
     /**
      * Writes the "H2" part of an entry into the metadata array at the specified
      * [index]. The index must be a valid index. This function ensures the
diff --git a/collection/collection/template/PKeyPValueMapTest.kt.template b/collection/collection/template/PKeyPValueMapTest.kt.template
index e29c4ce..a61070f 100644
--- a/collection/collection/template/PKeyPValueMapTest.kt.template
+++ b/collection/collection/template/PKeyPValueMapTest.kt.template
@@ -716,4 +716,18 @@
         assertEquals(1024, map.trim())
         assertEquals(0, map.trim())
     }
+
+    @Test
+    fun insertManyRemoveMany() {
+        val map = MutablePKeyPValueMap()
+
+        for (i in 0 .. 1000000) {
+            map[i.toPKey()] = i.toPValue()
+            map.remove(i.toPKey())
+            assertTrue(
+                map.capacity < 16,
+                "Map grew larger than 16 after step $i"
+            )
+        }
+    }
 }
diff --git a/collection/collection/template/PKeySet.kt.template b/collection/collection/template/PKeySet.kt.template
index ddcbdba..ea71ba3 100644
--- a/collection/collection/template/PKeySet.kt.template
+++ b/collection/collection/template/PKeySet.kt.template
@@ -779,8 +779,7 @@
      */
     private fun adjustStorage() {
         if (_capacity > GroupWidth && _size.toULong() * 32UL <= _capacity.toULong() * 25UL) {
-            // TODO: Avoid resize and drop deletes instead
-            resizeStorage(nextCapacity(_capacity))
+            removeDeletedMarkers()
         } else {
             resizeStorage(nextCapacity(_capacity))
         }
@@ -807,6 +806,23 @@
         }
     }
 
+    private fun removeDeletedMarkers() {
+        val m = metadata
+        val capacity = _capacity
+        var removedDeletes = 0
+
+        // TODO: this can be done in a more efficient way
+        for (i in 0 until capacity) {
+            val slot = readRawMetadata(m, i)
+            if (slot == Deleted) {
+                writeMetadata(i, Empty)
+                removedDeletes++
+            }
+        }
+
+        growthLimit += removedDeletes
+    }
+
     /**
      * Writes the "H2" part of an entry into the metadata array at the specified
      * [index]. The index must be a valid index. This function ensures the
diff --git a/collection/collection/template/PKeySetTest.kt.template b/collection/collection/template/PKeySetTest.kt.template
index 192b395..f9b12d5 100644
--- a/collection/collection/template/PKeySetTest.kt.template
+++ b/collection/collection/template/PKeySetTest.kt.template
@@ -560,4 +560,18 @@
         assertTrue(4KeySuffix in set)
         assertFalse(5KeySuffix in set)
     }
+
+    @Test
+    fun insertManyRemoveMany() {
+        val set = mutablePKeySetOf()
+
+        for (i in 0 .. 1000000) {
+            set.add(i.toPKey())
+            set.remove(i.toPKey())
+            assertTrue(
+                set.capacity < 16,
+                "Set grew larger than 16 after step $i"
+            )
+        }
+    }
 }
diff --git a/compose/animation/animation-core/build.gradle b/compose/animation/animation-core/build.gradle
index 97ee3a7..d108b31 100644
--- a/compose/animation/animation-core/build.gradle
+++ b/compose/animation/animation-core/build.gradle
@@ -33,7 +33,7 @@
 
 androidXMultiplatform {
     android()
-    desktop()
+    jvmStubs()
 
     defaultPlatform(PlatformIdentifier.ANDROID)
 
@@ -46,7 +46,7 @@
                 implementation(project(":compose:ui:ui-graphics"))
                 implementation(project(":compose:ui:ui-util"))
                 implementation("androidx.collection:collection:1.4.0")
-                implementation(libs.kotlinStdlibCommon)
+                implementation(libs.kotlinStdlib)
                 api(libs.kotlinCoroutinesCore)
             }
         }
@@ -59,34 +59,24 @@
         jvmMain {
             dependsOn(commonMain)
             dependencies {
-                implementation(libs.kotlinStdlib)
-                api(libs.kotlinCoroutinesCore)
             }
         }
 
-
         androidMain {
             dependsOn(jvmMain)
             dependencies {
                 api("androidx.annotation:annotation:1.1.0")
-                implementation(libs.kotlinStdlib)
             }
         }
 
-        desktopMain {
+        jvmStubsMain {
             dependsOn(jvmMain)
             dependencies {
             }
         }
 
-        jvmTest {
-            dependsOn(commonTest)
-            dependencies {
-            }
-        }
-
         androidInstrumentedTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(libs.testRules)
                 implementation(libs.testRunner)
@@ -97,11 +87,12 @@
                 implementation(project(":compose:foundation:foundation"))
                 implementation("androidx.compose.ui:ui-test-junit4:1.2.1")
                 implementation(project(":compose:test-utils"))
+                implementation("androidx.compose.material3:material3:1.2.1")
             }
         }
 
         androidUnitTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(libs.testRules)
                 implementation(libs.testRunner)
@@ -110,10 +101,6 @@
                 implementation(libs.kotlinCoroutinesCore)
             }
         }
-
-        desktopTest {
-            dependsOn(jvmTest)
-        }
     }
 }
 
diff --git a/compose/animation/animation-core/src/androidInstrumentedTest/kotlin/androidx/compose/animation/core/SeekableTransitionStateTest.kt b/compose/animation/animation-core/src/androidInstrumentedTest/kotlin/androidx/compose/animation/core/SeekableTransitionStateTest.kt
index 7853d2e..b41a9fd 100644
--- a/compose/animation/animation-core/src/androidInstrumentedTest/kotlin/androidx/compose/animation/core/SeekableTransitionStateTest.kt
+++ b/compose/animation/animation-core/src/androidInstrumentedTest/kotlin/androidx/compose/animation/core/SeekableTransitionStateTest.kt
@@ -23,30 +23,41 @@
 import androidx.compose.animation.togetherWith
 import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.requiredSize
 import androidx.compose.foundation.layout.size
+import androidx.compose.material3.Text
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.Stable
 import androidx.compose.runtime.getValue
+import androidx.compose.runtime.key
 import androidx.compose.runtime.mutableFloatStateOf
 import androidx.compose.runtime.mutableIntStateOf
 import androidx.compose.runtime.mutableLongStateOf
+import androidx.compose.runtime.mutableStateListOf
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.runtime.setValue
+import androidx.compose.runtime.snapshotFlow
 import androidx.compose.testutils.assertPixels
+import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.drawBehind
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.assertIsNotDisplayed
 import androidx.compose.ui.test.captureToImage
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.test.onNodeWithTag
 import androidx.compose.ui.unit.Density
 import androidx.compose.ui.unit.dp
+import androidx.compose.ui.util.fastForEachReversed
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
 import androidx.test.filters.SdkSuppress
@@ -54,6 +65,7 @@
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.android.awaitFrame
 import kotlinx.coroutines.async
+import kotlinx.coroutines.flow.collectLatest
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.runBlocking
 import org.junit.Assert.assertEquals
@@ -2340,4 +2352,93 @@
         rule.waitForIdle()
         assertFalse(isObserving())
     }
+
+    @OptIn(ExperimentalTransitionApi::class)
+    @Test
+    fun quickAddAndRemove() {
+        @Stable
+        class ScreenState(
+            val label: String,
+            removing: Boolean = false,
+        ) {
+            var removing by mutableStateOf(removing)
+        }
+
+        var labelIndex = 1
+        val screenStates = mutableStateListOf(ScreenState("1"))
+        val seekableScreenTransitionState = SeekableTransitionState(screenStates.toList())
+
+        rule.setContent {
+            val screenTransition = rememberTransition(seekableScreenTransitionState)
+            LaunchedEffect(Unit) {
+                snapshotFlow { screenStates.toList().filter { !it.removing } }
+                    .collectLatest { capturedScreenStates ->
+                        seekableScreenTransitionState.animateTo(capturedScreenStates)
+                        // Done animating
+                        screenStates.fastForEachReversed {
+                            if (it.removing) {
+                                screenStates.remove(it)
+                            }
+                        }
+                    }
+            }
+
+            Column(Modifier.fillMaxSize()) {
+                Box(Modifier.fillMaxWidth().weight(1f)) {
+                    var lastVisibleIndex = screenStates.size - 1
+                    while (lastVisibleIndex >= 0 && screenStates[lastVisibleIndex].removing) {
+                        lastVisibleIndex--
+                    }
+
+                    screenStates.forEach { screenState ->
+                        key(screenState) {
+                            val visibleTransition =
+                                screenTransition.createChildTransition {
+                                    screenState === it.lastOrNull() && !screenState.removing
+                                }
+                            visibleTransition.AnimatedVisibility(
+                                visible = { it },
+                            ) {
+                                Text(
+                                    "Hello ${screenState.label}",
+                                    Modifier.testTag(screenState.label)
+                                )
+                            }
+                        }
+                    }
+                    Text(
+                        "screenStates:\n${
+                            screenStates.reversed().joinToString("\n") {
+                                it.label +
+                                    if (it.removing) " (removing)" else ""
+                            }
+                        }",
+                        Modifier.align(Alignment.BottomStart)
+                    )
+                }
+            }
+        }
+        fun removeState() {
+            rule.runOnUiThread { screenStates.last { !it.removing }.removing = true }
+        }
+        fun addState() {
+            rule.runOnUiThread { screenStates += ScreenState(label = "${++labelIndex}") }
+        }
+
+        rule.waitForIdle()
+        rule.mainClock.autoAdvance = false
+        addState()
+        rule.mainClock.advanceTimeBy(50)
+        removeState()
+        rule.mainClock.advanceTimeBy(50)
+        addState()
+        rule.mainClock.advanceTimeBy(50)
+        removeState()
+        rule.mainClock.autoAdvance = true
+        rule.waitForIdle()
+
+        rule.onNodeWithTag("1").assertIsDisplayed()
+        rule.onNodeWithTag("2").assertIsNotDisplayed()
+        rule.onNodeWithTag("3").assertIsNotDisplayed()
+    }
 }
diff --git a/compose/animation/animation-core/src/androidInstrumentedTest/kotlin/androidx/compose/animation/core/TransitionTest.kt b/compose/animation/animation-core/src/androidInstrumentedTest/kotlin/androidx/compose/animation/core/TransitionTest.kt
index de3c720..ae20509 100644
--- a/compose/animation/animation-core/src/androidInstrumentedTest/kotlin/androidx/compose/animation/core/TransitionTest.kt
+++ b/compose/animation/animation-core/src/androidInstrumentedTest/kotlin/androidx/compose/animation/core/TransitionTest.kt
@@ -16,6 +16,8 @@
 
 package androidx.compose.animation.core
 
+import androidx.collection.mutableLongListOf
+import androidx.compose.animation.AnimatedContent
 import androidx.compose.animation.VectorConverter
 import androidx.compose.animation.animateColor
 import androidx.compose.runtime.LaunchedEffect
@@ -25,11 +27,13 @@
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.runtime.setValue
+import androidx.compose.runtime.snapshotFlow
 import androidx.compose.runtime.withFrameNanos
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
+import com.google.common.truth.Truth.assertThat
 import junit.framework.TestCase.assertEquals
 import junit.framework.TestCase.assertFalse
 import junit.framework.TestCase.assertTrue
@@ -531,4 +535,30 @@
             assertEquals(200f, value3, 0.1f)
         }
     }
+
+    @Test
+    fun snapshotTotalDurationNanos() {
+        val durations = mutableLongListOf()
+        rule.mainClock.autoAdvance = false
+        rule.setContent {
+            var targetState by remember { mutableStateOf(false) }
+            val transition = updateTransition(targetState, label = "")
+
+            transition.AnimatedContent { _ -> }
+
+            LaunchedEffect(Unit) {
+                delay(200)
+                targetState = true
+
+                snapshotFlow { transition.totalDurationNanos }.collect { durations += it }
+            }
+        }
+
+        rule.mainClock.advanceTimeByFrame()
+
+        rule.runOnIdle { assertThat(durations.size).isEqualTo(0) }
+
+        rule.mainClock.advanceTimeBy(200)
+        rule.runOnIdle { assertThat(durations.size).isGreaterThan(0) }
+    }
 }
diff --git a/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/Transition.kt b/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/Transition.kt
index 9f4ff95..592ef33 100644
--- a/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/Transition.kt
+++ b/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/Transition.kt
@@ -27,6 +27,7 @@
 import androidx.compose.runtime.MutableState
 import androidx.compose.runtime.Stable
 import androidx.compose.runtime.State
+import androidx.compose.runtime.derivedStateOf
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableFloatStateOf
 import androidx.compose.runtime.mutableLongStateOf
@@ -666,9 +667,9 @@
                     currentState = targetState
                     waitForComposition()
                     fraction = 0f
-                    transition.onTransitionEnd()
                 }
             }
+            transition.onTransitionEnd()
         }
     }
 
@@ -988,8 +989,7 @@
      * to [Transition]. It's strongly recommended to query this *after* all the animations in the
      * [Transition] are set up.
      */
-    val totalDurationNanos: Long
-        get() = calculateTotalDurationNanos()
+    val totalDurationNanos: Long by derivedStateOf { calculateTotalDurationNanos() }
 
     private fun calculateTotalDurationNanos(): Long {
         var maxDurationNanos = 0L
@@ -1074,6 +1074,7 @@
         }
         playTimeNanos = 0
         transitionState.isRunning = false
+        _transitions.fastForEach { it.onTransitionEnd() }
     }
 
     /**
@@ -1342,15 +1343,8 @@
             internal set
 
         private var velocityVector: V = initialVelocityVector
-        internal val durationNanos: Long
-            get() {
-                // Ensure any change to the duration is observable, since we have an observer
-                // on the Transition for the overall duration change.
-                _durationNanos = animation.durationNanos
-                return _durationNanos
-            }
+        internal var durationNanos by mutableLongStateOf(animation.durationNanos)
 
-        private var _durationNanos by mutableLongStateOf(animation.durationNanos)
         private var isSeeking = false
 
         internal fun onPlayTimeChanged(playTimeNanos: Long, scaleToEnd: Boolean) {
@@ -1402,6 +1396,7 @@
                 this.animation.mutableTargetValue = initialValue
             }
             this.animation.mutableInitialValue = initialValue
+            durationNanos = this.animation.durationNanos
             if (resetSnapValue == ResetNoSnap || useOnlyInitialValue) {
                 value = initialValue
             } else {
@@ -1445,6 +1440,7 @@
                         velocityVector.newInstance() // 0 velocity
                     )
                 useOnlyInitialValue = true
+                durationNanos = animation.durationNanos
                 return
             }
             val specWithoutDelay =
@@ -1462,6 +1458,7 @@
                 }
             animation =
                 TargetBasedAnimation(spec, typeConverter, initialValue, targetValue, velocityVector)
+            durationNanos = animation.durationNanos
             useOnlyInitialValue = false
             onChildAnimationUpdated()
         }
@@ -1493,6 +1490,7 @@
                 animation.mutableInitialValue = animationValue
                 animation.mutableTargetValue = animationValue
                 value = animationValue
+                durationNanos = animation.durationNanos
             } else {
                 resetSnapValue = fraction
             }
@@ -1514,6 +1512,7 @@
                     value,
                     velocityVector.newInstance() // 0 velocity
                 )
+            durationNanos = animation.durationNanos
             useOnlyInitialValue = true
         }
 
diff --git a/compose/animation/animation-graphics/build.gradle b/compose/animation/animation-graphics/build.gradle
index e2e65d6..f3a0352c 100644
--- a/compose/animation/animation-graphics/build.gradle
+++ b/compose/animation/animation-graphics/build.gradle
@@ -32,14 +32,14 @@
 
 androidXMultiplatform {
     android()
-    desktop()
+    jvmStubs()
 
     defaultPlatform(PlatformIdentifier.ANDROID)
 
     sourceSets {
         commonMain {
             dependencies {
-                implementation(libs.kotlinStdlibCommon)
+                implementation(libs.kotlinStdlib)
 
                 api(project(":compose:animation:animation"))
                 api("androidx.compose.foundation:foundation-layout:1.6.0")
@@ -74,21 +74,14 @@
             }
         }
 
-        desktopMain {
+        jvmStubsMain {
             dependsOn(jvmMain)
             dependencies {
-                implementation(libs.kotlinStdlib)
-            }
-        }
-
-        jvmTest {
-            dependsOn(commonTest)
-            dependencies {
             }
         }
 
         androidInstrumentedTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(libs.testRules)
                 implementation(libs.testRunner)
@@ -101,19 +94,13 @@
         }
 
         androidUnitTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(libs.testRules)
                 implementation(libs.testRunner)
                 implementation(libs.junit)
             }
         }
-
-        desktopTest {
-            dependsOn(jvmTest)
-            dependencies {
-            }
-        }
     }
 }
 
diff --git a/compose/animation/animation-lint/src/main/java/androidx/compose/animation/lint/AnimationIssueRegistry.kt b/compose/animation/animation-lint/src/main/java/androidx/compose/animation/lint/AnimationIssueRegistry.kt
index 6392415..7862a5c 100644
--- a/compose/animation/animation-lint/src/main/java/androidx/compose/animation/lint/AnimationIssueRegistry.kt
+++ b/compose/animation/animation-lint/src/main/java/androidx/compose/animation/lint/AnimationIssueRegistry.kt
@@ -34,6 +34,7 @@
                 AnimatedContentDetector.UnusedContentLambdaTargetStateParameter,
                 AnimatedContentDetector.UnusedTargetStateInContentKeyLambda,
                 SharedTransitionScopeDetector.UnusedSharedTransitionModifierParameter,
+                SharedTransitionScopeDetector.ConstantContentStateKeyInItemsCall,
             )
 
     override val vendor =
diff --git a/compose/animation/animation-lint/src/main/java/androidx/compose/animation/lint/SharedTransitionScopeDetector.kt b/compose/animation/animation-lint/src/main/java/androidx/compose/animation/lint/SharedTransitionScopeDetector.kt
index 9c3ea08..bb2d303 100644
--- a/compose/animation/animation-lint/src/main/java/androidx/compose/animation/lint/SharedTransitionScopeDetector.kt
+++ b/compose/animation/animation-lint/src/main/java/androidx/compose/animation/lint/SharedTransitionScopeDetector.kt
@@ -36,6 +36,7 @@
 import com.android.tools.lint.detector.api.Severity
 import com.android.tools.lint.detector.api.SourceCodeScanner
 import com.android.tools.lint.detector.api.UastLintUtils.Companion.tryResolveUDeclaration
+import com.intellij.psi.PsiClassOwner
 import com.intellij.psi.PsiMethod
 import java.util.EnumSet
 import org.jetbrains.kotlin.psi.KtParameter
@@ -45,52 +46,177 @@
 import org.jetbrains.uast.UMethod
 import org.jetbrains.uast.UReturnExpression
 import org.jetbrains.uast.getParameterForArgument
+import org.jetbrains.uast.getParentOfType
 
 private const val MODIFIER_PARAMETER_NAME = "modifier"
+private const val SHARED_ELEMENT_MODIFIER_NAME = "sharedElement"
+private const val SHARED_BOUNDS_MODIFIER_NAME = "sharedBounds"
 
 /** Detector to highlight unused provided Modifier from SharedTransitionContent. */
 class SharedTransitionScopeDetector : Detector(), SourceCodeScanner {
-    override fun getApplicableMethodNames(): List<String> = listOf(SharedTransitionScope.shortName)
+    override fun getApplicableMethodNames(): List<String> =
+        listOf(SharedTransitionScope.shortName, RememberSharedContentState.shortName)
 
     override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) {
         if (method.isInPackageName(Names.Animation.PackageName)) {
-            // Only one argument expected for `SharedTransitionScope(...)`, the content lambda.
-            val lambdaArgument = node.getArgumentForParameter(0) as? ULambdaExpression ?: return
-
-            lambdaArgument.findUnreferencedParameters().forEach { unreferencedParameter ->
-                val location =
-                    unreferencedParameter.parameter?.let { context.getLocation(it) }
-                        ?: context.getLocation(lambdaArgument)
-
-                // Find a Composable call proper for a quickfix
-                val fixCandidate =
-                    (lambdaArgument.body as? UBlockExpression)?.let {
-                        findCompatibleComposableCall(it)
-                    }
-
-                val quickFix =
-                    fixCandidate?.let {
-                        buildQuickFix(
-                            context = context,
-                            node = fixCandidate,
-                            unusedModifierParameter = unreferencedParameter
-                        )
-                    }
-
-                context.report(
-                    issue = UnusedSharedTransitionModifierParameter,
-                    scope = node,
-                    location = location,
-                    message =
-                        "Supplied Modifier parameter should be used on the top most " +
-                            "Composable. Otherwise, consider using `SharedTransitionLayout`.",
-                    quickfixData = quickFix
-                )
+            when (method.name) {
+                SharedTransitionScope.shortName ->
+                    detectUnusedSharedTransitionModifierParameter(context, node)
+                RememberSharedContentState.shortName ->
+                    detectConstantLiteralInSharedContentSateWithinItemsCall(context, node)
             }
         }
     }
 
     /**
+     * Detects cases of `SharedTransitionScope` when its modifier parameter is unused. Lint check
+     * may include a quick fix when possible.
+     *
+     * @see buildUnusedSharedTransitionModifierQuickFix
+     * @see UnusedSharedTransitionModifierParameter
+     */
+    private fun detectUnusedSharedTransitionModifierParameter(
+        context: JavaContext,
+        node: UCallExpression
+    ) {
+        // Only one argument expected for `SharedTransitionScope(...)`, the content lambda.
+        val lambdaArgument = node.getArgumentForParameter(0) as? ULambdaExpression ?: return
+
+        lambdaArgument.findUnreferencedParameters().forEach { unreferencedParameter ->
+            val location =
+                unreferencedParameter.parameter?.let { context.getLocation(it) }
+                    ?: context.getLocation(lambdaArgument)
+
+            // Find a Composable call proper for a quickfix
+            val fixCandidate =
+                (lambdaArgument.body as? UBlockExpression)?.let { findCompatibleComposableCall(it) }
+
+            val quickFix =
+                fixCandidate?.let {
+                    buildUnusedSharedTransitionModifierQuickFix(
+                        context = context,
+                        node = fixCandidate,
+                        unusedModifierParameter = unreferencedParameter
+                    )
+                }
+
+            context.report(
+                issue = UnusedSharedTransitionModifierParameter,
+                scope = node,
+                location = location,
+                message =
+                    "Supplied Modifier parameter should be used on the top most " +
+                        "Composable. Otherwise, consider using `SharedTransitionLayout`.",
+                quickfixData = quickFix
+            )
+        }
+    }
+
+    /**
+     * Detects the most naive case when using a `rememberSharedContentState` call with a constant
+     * literal within `LazyListScope.items` call (and derivatives), which will result in undesired
+     * behavior. The Lint check suggests the user to have unique `SharedContentState` keys.
+     *
+     * The expected naive use case should look something like this:
+     * ```
+     * SharedTransitionLayout {
+     *  AnimatedContent(
+     *      targetState = myState
+     *  ) { targetState ->
+     *      if (predicate(targetState)) {
+     *          LazyColumn {
+     *              items(count) { index ->
+     *                  MyComposable(
+     *                      data = getData[index],
+     *                      modifier = Modifier.sharedElement(
+     *                          // Note the key is a constant value called multiple times by `items`
+     *                          state = rememberContentState("myItem"),
+     *                          animatedVisibilityScope = this@AnimatedContent
+     *                      )
+     *                  )
+     *              }
+     *          }
+     *      } else {
+     *          ...
+     *      }
+     *  }
+     * }
+     * ```
+     *
+     * So the detector looks for a matching pattern from the `rememberSharedContentState` call up to
+     * the `items` call.
+     *
+     * @see ConstantContentStateKeyInItemsCall
+     */
+    private fun detectConstantLiteralInSharedContentSateWithinItemsCall(
+        context: JavaContext,
+        node: UCallExpression
+    ) {
+        // We first check whether the key is a constant literal
+        val keyElement = node.getArgumentForParameter(0)
+        // Non evaluate-able keys are assumed to be correct (they don't resolve to a constant
+        // literal)
+        if (keyElement?.evaluate() == null) {
+            return
+        }
+
+        // Verify `sharedElement` Modifier call
+        val sharedElementCallCandidate = node.getParentOfType<UCallExpression>(strict = true)
+        val resolvedSharedElementCall =
+            sharedElementCallCandidate?.tryResolveUDeclaration() as? UMethod
+
+        if (
+            !(resolvedSharedElementCall?.name == SHARED_ELEMENT_MODIFIER_NAME ||
+                resolvedSharedElementCall?.name == SHARED_BOUNDS_MODIFIER_NAME) ||
+                !resolvedSharedElementCall.isInPackageName(Names.Animation.PackageName)
+        ) {
+            return
+        }
+
+        // Verify parent is a valid Composable
+        val composableCallCandidate =
+            sharedElementCallCandidate.getParentOfType<UCallExpression>(strict = true)
+        val resolvedComposeCall = composableCallCandidate?.tryResolveUDeclaration() as? UMethod
+        if (resolvedComposeCall?.isComposable != true) {
+            return
+        }
+
+        // Verify parent is a LazyListScope `items` or `itemsIndexed` call
+        val itemsCallCandidate =
+            composableCallCandidate.getParentOfType<UCallExpression>(strict = true)
+
+        // Need to resolve to declaration to check for package and method name
+        val resolvedItemsCall = itemsCallCandidate?.tryResolveUDeclaration() as? UMethod
+
+        if (resolvedItemsCall?.name != "items" && resolvedItemsCall?.name != "itemsIndexed") {
+            return
+        }
+
+        val itemsMethodPackage =
+            resolvedItemsCall.let { (it.containingFile as? PsiClassOwner)?.packageName }
+
+        // There's several LazyList implementations in different packages, such as
+        // `androidx.compose.foundation`, `androidx.tv.foundation`, `android.wear.compose`
+        // so we need to account for that
+        if (
+            itemsMethodPackage?.startsWith("androidx") == false ||
+                itemsMethodPackage?.contains("foundation") == false
+        ) {
+            return
+        }
+
+        context.report(
+            issue = ConstantContentStateKeyInItemsCall,
+            scope = node,
+            location = context.getLocation(node),
+            message =
+                "Each Composable within a LazyList `items` call should have unique content state " +
+                    "keys. Make sure to either associate a unique key related to the item's " +
+                    "data, or simply append the item's index to the key."
+        )
+    }
+
+    /**
      * Looks for a compatible Composable call that can be used to provide a quick fix.
      *
      * Here we look for a Composable function call that it's most likely to be a Layout. Meaning,
@@ -172,7 +298,7 @@
      * simply assign the unused modifier parameter to it. E.g.: `MyComposable(modifier = it)`. If it
      * did already have a modifier expression on it. We can just wrap around it with `.then()`.
      */
-    private fun buildQuickFix(
+    private fun buildUnusedSharedTransitionModifierQuickFix(
         context: JavaContext,
         node: UCallExpression,
         unusedModifierParameter: UnreferencedParameter
@@ -234,7 +360,7 @@
             Issue.create(
                 id = "UnusedSharedTransitionModifierParameter",
                 briefDescription =
-                    "SharedTransitionScope calls should use the provided Modifier " + "parameter.",
+                    "SharedTransitionScope calls should use the provided Modifier parameter.",
                 explanation =
                     "When using `SharedTransitionScope` the provided `Modifier` should " +
                         "always be used on the top-most child, as the `Modifier` both obtains " +
@@ -249,7 +375,32 @@
                         EnumSet.of(Scope.JAVA_FILE, Scope.TEST_SOURCES)
                     )
             )
+
+        val ConstantContentStateKeyInItemsCall =
+            Issue.create(
+                id = "ConstantContentStateKeyInItemsCall",
+                briefDescription =
+                    "Composables within an LazyList `items` call should have unique content " +
+                        "state keys.",
+                explanation =
+                    "When using shared elements (`Modifier.sharedElement` or " +
+                        "`Modifier.sharedBounds`) in a LazyList, each Composable within an " +
+                        "`items` block should have its own unique key. Otherwise, only one item " +
+                        "of the visible layout will be rendered, regardless if there's an ongoing" +
+                        " shared element transition.",
+                category = Category.CORRECTNESS,
+                priority = 3,
+                severity = Severity.ERROR,
+                implementation =
+                    Implementation(
+                        SharedTransitionScopeDetector::class.java,
+                        EnumSet.of(Scope.JAVA_FILE, Scope.TEST_SOURCES)
+                    )
+            )
     }
 }
 
 private val SharedTransitionScope = Name(Names.Animation.PackageName, "SharedTransitionScope")
+
+private val RememberSharedContentState =
+    Name(Names.Animation.PackageName, "rememberSharedContentState")
diff --git a/compose/animation/animation-lint/src/test/java/androidx/compose/animation/lint/SharedTransitionScopeDetectorTest.kt b/compose/animation/animation-lint/src/test/java/androidx/compose/animation/lint/SharedTransitionScopeDetectorTest.kt
index 1ca94ca..ec8b18d 100644
--- a/compose/animation/animation-lint/src/test/java/androidx/compose/animation/lint/SharedTransitionScopeDetectorTest.kt
+++ b/compose/animation/animation-lint/src/test/java/androidx/compose/animation/lint/SharedTransitionScopeDetectorTest.kt
@@ -30,16 +30,114 @@
     override fun getDetector(): Detector = SharedTransitionScopeDetector()
 
     override fun getIssues(): MutableList<Issue> =
-        mutableListOf(SharedTransitionScopeDetector.UnusedSharedTransitionModifierParameter)
+        mutableListOf(
+            SharedTransitionScopeDetector.UnusedSharedTransitionModifierParameter,
+            SharedTransitionScopeDetector.ConstantContentStateKeyInItemsCall,
+        )
+
+    private val AnimatedContentStub =
+        bytecodeStub(
+            filename = "AnimatedContent.kt",
+            filepath = "androidx/compose/animation",
+            checksum = 0x8604a7d6,
+            source =
+                """
+package androidx.compose.animation
+
+import androidx.compose.runtime.Composable
+
+interface AnimatedVisibilityScope
+
+interface AnimatedContentScope: AnimatedVisibilityScope
+
+@Composable
+fun <S> AnimatedContent(
+    targetState: S,
+    contentKey: (targetState: S) -> Any? = { it },
+    content: @Composable AnimatedContentScope.(targetState: S) -> Unit
+) {}
+        """,
+            """
+                META-INF/main.kotlin_module:
+                H4sIAAAAAAAA/2NgYGBmYGBgBGJOBijg8uCSSsxLKcrPTKnQS87PLcgvTtVL
+                zMvMTSzJzM8TEnQEM1NTnPPzSlLzSrxLhMSDMxKLUlNCihLzijNBioKT8wtS
+                vUu4eLmY0/LzhdhCUouB6pQYtBgA2lFPg3EAAAA=
+                """,
+            """
+                androidx/compose/animation/AnimatedContentKt$AnimatedContent$1.class:
+                H4sIAAAAAAAA/6VUXU8TQRQ9s91+UmxB5UtFRYQWkKVVebCESCqEjRUTS5oY
+                nqbdAYbuzprutsE3fou/QOIDiSaG+OiPMt5ZqjGIEmOyc+fsuR8zc8/sfv32
+                8TOAR1hmWOXK6fjSObRavvfGD4TFlfR4KH1lrUVIOFVfhUKFz8Ppc8x0KQnG
+                8KzW9kNXKuug51mSPB3FXavGvabDK7/6druqpSsH1kYflVa26xV6VisME3+u
+                koTJMPn3SkkkGBIrUslwlSFWKDYYzIJdbGSRQiaDOAaICPdlwPC09n/Hpt0m
+                pOr5bcEwU6gd8B63XK72rJfNA9EKK8XfKYZUgQ5apMFgyJBh+MKglZYbHUHv
+                Op2BgetE2lv17bWt6noWo7iSJnKMYehHZ1+IkDs85Lqu14uRskybtDZgYG0N
+                YuQ8lBotEXJKDLOnR2bGSMXzp0cTxiabMlOnR3lWTuQN/bqZ+fIuYaZieVOH
+                lxkGVrjy1VvP7wbUXlZnWPiXHiZRYBg930hH7PKuS73Yv6CJl9ycS/zlin2B
+                LnQZ5jBPvT+3k8U2bcKs+o7Quvgt7jZ4R/KmK7a1YcjVpBJbXa8pOn0mXZd7
+                iofdDuGsrZToVF0eBIKuV25dtVw/kGqPtNn3HYZM3e92WmJD6szxV10VSk80
+                ZCCp1JpSfhi1LcASaRsn0ei7wrgWW0tHg+4CMYuEpimC0ZyYM0+QPY4ktshm
+                z1gMRjlDyCFPkTpjmTwGzcb8e21pDR2nowejzJEzbz9To2FcJX8pwkO09rWf
+                q49GscDAJxivTzDyAePHERFHmWymvxQwhodkTRSx0C8Uox+Onh/gMc1PKHKC
+                sm7sIGbjpo1bNiZx28Yd3LUxhXs7YAEd9v4O4gFmAswGGA6QC5D/DiMiC4S/
+                BAAA
+                """,
+            """
+                androidx/compose/animation/AnimatedContentKt.class:
+                H4sIAAAAAAAA/7VUW28TRxT+Zn1br+3YWQIEp0AKSQnEZm2X3nAIpBYoK4yp
+                6hBVytNkvZiN7dlodx2Flyp/o6/9B+UJ8VBFfeyPqnpmsybBceXmAVk+9/PN
+                NzNn5+9/PvwJ4AEaDCUuOp7rdA4Nyx3su75tcOEMeOC4wtgILbvTcEVgi+B5
+                kAJjKOzxA270uegaL3f3bIuiMYb8WDHDq5XmeGW92XODviOMvYOB8XooLLmM
+                bzyLrOqUfK1+d5vhw1r74Xnk9ZWt9jT4tTLVrE7onbbuWrn5/4+pbbn7dr18
+                hs4r4chFJPnl80DeUATOwDYaoc93+3ad4XbT9brGnh3setwhKlwIN+AntFpu
+                0Br2+1SlWdHN2G9VaAw3zmzDoYwneN8wReARhGP5KWQZLltvbKsXYfzEPT6w
+                qZDhzqTrOo20JUiX9pDFDPIacigwpKL1VegMmYB7XTtoE02bQT+PxrA47f6n
+                ltSo5OrYgS917Nd82KeRe/MZRs48Dykvcv0i383SOONqCkUG1Wy1tzZajacM
+                Ty4wYJPw6ll8getpLODGp2MwYcspLGaRQFKDglsMs6MTeGEHvMMDTkesDA5i
+                9EIwKdJSgIH1pKFQ8tCRVoWsTpXh3fFRSTs+0pSCoilqTFPmlfAfhkhIHYVO
+                U8UhpYpKhd2Kq8dHBaWWLMSKyqZSW1aVQrx4U7+kz24qf/2ezKpJXVVTelxV
+                V2J6Uo/Ps4paSdSqhXSxrMd1pZL5j1qZYxWN4oqaDWVuMyV1YUYyr7FwU205
+                qtEBnJ3DK6Pgx0+kRYoScUF6QpOczOqFnwm6rBHQ00MK+1Q5Qtx6GxboY433
+                ezTp8YbbIRb5piPs1nCwa3tb8uWQvFyL97e550g/CqbbTlfwYOiRvfDzyXtj
+                igPHdyi9cfq0MCyNZz9u/5OyHH3lVu8F348WyJpC2F6jz33fprTWdoeeZT9z
+                ZO5aBLl9bjlUaQLjcrpIX5MjSd4P5D0nX45YblXPvMdsSb9E8o+w7CHJJF1c
+                FnnUyV48KcQcLodAOWi4Qnlp6bhKHWthXwqPok6V9Dr98+GEIz2ShTTmiQUL
+                GTwi2ATpueuJX3+D9g43j/Fl895q6T1unxB5TDIGlgsZzYQsMoSfo1+GvCfk
+                awS2ELKax0bY9D1+JP0LxZcIfnkHMRNfmbhjYgV3TdzDqokSyjtgPu7D2EHe
+                R8JHhY7Kx5wPzUfNx9c+HoRB3cc3Pr71ofr4zkfyXyUizovZBwAA
+                """,
+            """
+                androidx/compose/animation/AnimatedContentScope.class:
+                H4sIAAAAAAAA/5VQzU7CQBicr1Uo9Q8QFV/CUsLNEzExaYIxkcRLT0u7mqXt
+                LqELwRvP5cFw9qGMXxtPnPCws7Ozmdlv9vvn8wvACDeEQOh0aVS6CRJTLEwp
+                WVCFsMroYFwzmT4YbaW208QsZBNEaM/FWgS50O/B82wuE9uESxgeEPWqSjVT
+                ubIff2nHhM4kMzZXOniSVqTCinuCU6xdHpEqaFUAAmWsb1R1GjBLQ0Jvt/V8
+                p+9Uy3vr77ZDZ0DV3ZAQTv5ZjZ8dHeLZ68C27l7cXWYJ/tSslol8VLkk3L6s
+                tFWFrL25HGttbJ1aNnhcHHG9RtWS+VWNPVzzHrLOfwQvhhuhFcGPcIJTpjiL
+                cI6LGFSijU4Mp0S3xOUvVJXe6dwBAAA=
+                """,
+            """
+                androidx/compose/animation/AnimatedVisibilityScope.class:
+                H4sIAAAAAAAA/5VOTU/CQBB9s1UK9augJPgnXCDcPBETkyYYE0m89LS0q1na
+                7hJ2IXDjd3kwnP1Rxm2NP8CZ5M2beZl58/X98Qlggj5hLHS+Nirf8cxUK2Ml
+                F1pVwimj+bRhMn9VVi1Uqdx+npmVDEGEeCm2gpdCv/PnxVJmLkRA6M4K40ql
+                +ZN0IhdO3BNYtQ28G9XQqQEEKvx8p+pu6Fk+IvSPh3bEBixisWdvg+NhzIZU
+                i2PCZPb/N721d+r9qQ9GO6ndXeEI0dxs1pl8VKUk3L5stFOVbNZLOdXauOaw
+                bXl3nOA3GK4b7OHG15E/feqzlSJIECZoJ+gg8hRnCc5xkYIsLnGVglnEFt0f
+                0vO5tnUBAAA=
+                """
+        )
 
     private val SharedTransitionScopeStub =
         bytecodeStub(
             filename = "SharedTransitionScope.kt",
             filepath = "androidx/compose/animation",
-            checksum = 0xf63c8499,
-            """
+            checksum = 0x738eebab,
+            source =
+                """
 package androidx.compose.animation
 
+import androidx.compose.animation.AnimatedVisibilityScope
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
 
@@ -52,41 +150,498 @@
 
 // Note, the real version extends LookaheadScope, but not currently relevant for this
 // detector.
-interface SharedTransitionScope
+interface SharedTransitionScope {
+    fun Modifier.sharedBounds(
+        sharedContentState: SharedContentState,
+        animatedVisibilityScope: AnimatedVisibilityScope,
+    ): Modifier
+
+    fun Modifier.sharedElement(
+        state: SharedContentState,
+        animatedVisibilityScope: AnimatedVisibilityScope,
+    ): Modifier
+
+    @Composable
+    fun rememberSharedContentState(key: Any): SharedContentState
+}
+
+@Composable
+fun SharedTransitionLayout(
+    modifier: Modifier = Modifier,
+    content: @Composable SharedTransitionScope.() -> Unit
+) {}
+
+class SharedContentState internal constructor(val key: Any)
         """,
             """
                 META-INF/main.kotlin_module:
-                H4sIAAAAAAAA/2NgYGBmYGBgBGJOBijgMuWSSsxLKcrPTKnQS87PLcgvTtVL
-                zMvMTSzJzM8TEg/OSCxKTQkpSswrzgSJBCfnF6R6l3DxcjGn5ecLsYWkFpd4
-                lygxaDEAAEn9egVeAAAA
+                H4sIAAAAAAAA/2NgYGBmYGBgBGJOBijg8uCSSsxLKcrPTKnQS87PLcgvTtVL
+                zMvMTSzJzM8TEnQEM1NTnPPzSlLzSrxLhMSDMxKLUlNCihLzijNBioKT8wtS
+                vUu4eLmY0/LzhdhCUouB6pQYtBgA2lFPg3EAAAA=
+                """,
+            """
+                androidx/compose/animation/SharedContentState.class:
+                H4sIAAAAAAAA/5VRXU8TQRQ9s223y1qlrSAF/AahFGGB+IYfUYxJY0VDCS88
+                TbeTMu12luxOG3jrb/EXaKLR+GAaH/1RxjvtBgV88WXOPTf3nnPn3p+/vn0H
+                8AjrDGtcNaNQNk88P+weh7HwuJJdrmWovPoRj0RzJ1RaKF3XXIssGEO+zfvc
+                C7hqeW8bbeHrLFIM9mOppH7KMF2uXSzYXjlgWKiFUctrC92IuFQx+ahQj4xi
+                bzfUu70g2GZIdcSpA4fhdifUgVReu9/1JE0QKR54VaUj6pV+nIVLVv6R8DtJ
+                8zse8a6gQoblf4zwV6ZuRFo0VA45XHVxBdfIuGx4BnkXaRQYipclcnBwfQIW
+                phjS+kjGDF7tv/ZHH7RbQr8WpwxT5ZXLFgyFWvLxN0LzJteccla3n6KDMfNM
+                mAcMrEP5E2nYBkXNTYZnw0HOtUqWa+WHA9dy0qXhYMvaYC8mneGgaOetOSI/
+                3ttWPrVXOGOOOxzMpZ10PmNktpgRL41H3484Ldv8pe6Hx2K9oxnm93pKy66o
+                qr6MZSMQz//ckdayEzYFw2RNKrHb6zZEtM+pxqwz9HlwwCNpeJJcvKh1dsNz
+                om497EW+eCVNz2zSc3DJHZt0mvRoOUVzKcJlYjZhltAizBCzUCb2ktAizK8W
+                J75isvIFxcrqZ0x/HFWuJH02llCh+Ma4lnDGbJ+isf4qxVmWGBRQwmwi75kL
+                EWYqnzD94ZwmEs3cuCDRPD/pw9G7hDXCJ5Sdo7r5Q6SquFnFrSpu4w6FuFvF
+                Pdw/BIuxgMVD2DFmYjyI4cQmLsWY/Q02LAWq7AMAAA==
                 """,
             """
                 androidx/compose/animation/SharedTransitionScope.class:
-                H4sIAAAAAAAA/5VOu07DQBCcPUOcmJcDRDI/gR2LjooGyVIQEkY0ri72ARfb
-                d5HvEqXMd1Gg1HwU4hxaGnal2dkdaWe+vj8+AdxgQki4qjotq01c6napjYi5
-                ki23Uqs4f+edqJ47rozsD3mpl8IHEcIFX/O44eotfpwvRGl9eITxrNa2kSp+
-                EJZX3PJbAmvXnvOiHkY9gEC1u29kvyWOVVPCZLcdBixiAQsde41225Ql1Isp
-                IZ39N6Qzdj7Rn9p1bQlBrlddKe5lIwhXTytlZStepJHzRtwppe3+uRm4BDjA
-                bzFc7PEcl25OncGh60EBL4OfYZhhhMBRHGU4xkkBMjjFWQFmEBqMfwAktUe9
-                dwEAAA==
+                H4sIAAAAAAAA/51UW08TQRT+Zhd6A3QBlVIQlYuiD25teOMJiYaSAsYaXvo0
+                7Q447e4M2ZkSeDH8Ff+GD4Znf5Tx7LZGaJsSTHbm3L5z5tyyv37/+AlgCxsM
+                Za6CWMvgwm/p6Ewb4XMlI26lVn79K49F8CXmyshEUW/pM5EFY/Da/Jz7IVen
+                /lGzLVo2C5dh2qQO73VXBYbh+2ZtKHhX+gc6kCdSxNvD1sGnd7WyQtm65VaM
+                he+knAiOpZFNGUp7mea6/Xp8BgxrNR2f+m1hmzGXylBIpW0a0/iH2h52w5BQ
+                M73CPoQionQYSjExUVPEw2ky7G7WBrszKo+xtTJsDHvEXWVlJPzdVObNMMHN
+                1jrahlL5B8LygFtOOic6d2m+LLnyyQUG1iH9hUykMnHBO4Zv11erBafoFBzv
+                +qpAX8rnnEGaOyleX1WcMtv3PKfklN1KxpsgyvZe7S97k8Rl3tAhbbZvzRHN
+                770ka+GGdeq2NcmiwlC5uzUDG0gVUkH+vVvqdsQlw8pdKzFnRgx1gY/eMIat
+                /9lLhknTC1wcWeLbDm3Z0ufewKvqPHEPxc6/5WRYH7R+4jGPhBXxLVihrrtx
+                S3yUIT222Pc5HoqXoWlgIlkVuBOUHTIkvyApQ63OEl2lM+/2hRs3gXP3AedR
+                6IMTOkX0r0OW9aEO1tL7OdaJHpF2mhKaacCt4kEVD6vwMEss5qqYx6MGmMFj
+                PGnQ/wcLBkWDvMGiQclQl7FksGzw1GDFIGfw7A9vI0cV/QQAAA==
                 """,
             """
                 androidx/compose/animation/SharedTransitionScopeKt.class:
-                H4sIAAAAAAAA/5VSW08TQRT+Zlu6Za1SqigUROQiF8EtjW81JoZIbCzVUOSF
-                p+nuUKaXWbI7bfCNB3+J/8A344MhPvqjjGe2rSIQCQ975sx3vnOZs9/PX9++
-                A3iODYYiV34YSP/E9YLOcRAJlyvZ4VoGyq0d8VD4eyFXkTRAzQuOxVttgzFk
-                m7zH3TZXDfddvSk8QhMME1emMCysVFqBbkvlNnsd97CrPBOM3O2BVyyt7jN8
-                uo71YqNy03FLV6R0pbsT+PJQirA07PhBSV16GY+xdDkj7CotO8Ldiu+83hYl
-                elQlCBtuU+h6yCWNyZUKNO+PXA10tdtuE8v2AqWF0mk4DLPn3icJDhVvu2Wl
-                Q8qXXmQjQzv0joTXGhR4z0PeEURkWF6pXNx56RxSM0Ua9IAM7mDMwW1kGeau
-                WzvD+JCyIzT3ueaEWZ1eggTCjBk1BgysZRyLgifSeAXy/E2G3bPTGefs1LGy
-                VnxMWhe//Hr27DRvFVhxPmvlZ3PJnFVIxnYktqyQ+PE5ZaVTsbXf2KZykZmm
-                ueFw5ycu3lwEtPn/y8AQBq1en9Dviih12HPvY1xh8srSz1qaIbkV+KTysYpU
-                otrt1EW4ZzRi5g883t7noTT3AThakw3FdTckf3q3r6yy6slIUvjVXxExLF6M
-                /pHDPzSnFnRDT2xLU31qkLN/qR42YSGJ/u+cwghSdFuim8Fp3bDXcre+YvyL
-                +c94QjZFcAoZLJOf6VPgIEfnSsyxsTpgpelcM3ESCkbj4NPYLmKdzi1C71LH
-                ewdIlDFRxv0yHmCyTGPky5jGzAFYhIeYPUA6wkiERxGcCHMRHkeYjwy48BsH
-                UtTXtgQAAA==
+                H4sIAAAAAAAA/6VUy1IbRxQ9PRLSaCzZsoiJkLFisGxjsD1CcZ4iTggVl1UW
+                JBURNqya0YAbjXqo6RkKb1JUJR+Qbbb5g2TlyiJFZZmPSuX2aCAyUoEfi+m+
+                fe/pe+5r+p9///wLwCN8zdDgshv4ontoO35/31euzaXo81D40u4854Hb3Qi4
+                VEIrOo6/7z4Ls2AMxT1+wG2Py1372+091yFtiuHa2CsMt+bbPT/0hLT3Dvr2
+                TiQdbVT2k0RqNO9tMvx8EWr5QftNw22OuRIJe83vih3hBs0Txh+kCJuP4zBu
+                j94IIhmKvmuvxme+7blNSqrtB7v2nhtuB1xQmFxKP+SDkNf9cD3yPEJlHV+G
+                rgxNWAzVofwEqQPJPbslw4DuC0dlkacaOs9dp5c4+I4HvO8SkOHufPtszZtD
+                mo52sksJ5HEZVywUUGS4eVHZGabOlq3NX/hRyLAy/3qVG+96KS7lT+/m4236
+                PaahZj/hMzFFPTg/pAuLtkSQ6vii1bruDo88Kt7GOxavNdprncnMeU6zmGHI
+                6RGlGvmS4fwYaqfIZh5VfJDDDdzMYxLvWTAwx3D1JMg1N+RdHnJK3OgfpOjp
+                YHrJ6QUMrKcFg4yHQkt1krpLDL8cH9Ws4yPLKBrxVj7dhr+BqlIvHh9VjDpr
+                mCbhSUo1ZorpSrmULhn1TLyy+sTfv2UMMxuv5tNs5X4xF9+ZI2R1CJlK8Nar
+                eB1Xg+mQSyepDTe18ebDpqcp8fTNIf3liiwnLjdexIARKv3T3Xm9xmTxEUN5
+                LPXDHk1ZetXv0ut6pS2kux71t91gQ79NmtR3uLfJA6HPiTLXEbuSh1FA8vXv
+                By9aSx4IJci88v/jxVA7az19hl6BFTohd3prfD8hyLekdINVjyvlktnq+FHg
+                uE+Etk0nLjdH6LBE45bWo4QUpjGBDJ0+pZPWU7eQXShdeomrv+shw2e0Zkid
+                oQfuc5LzAwgslGhvxpgslhOUSfsX2k5TihwJ03q+E/8rBDVoLyyU3if/i2NY
+                8qjFLFMDIO3lONAC8U2TfcB3bYSvYCR88VrMoYLrJGvW5STbyZn0j7/C+gOz
+                x7jxbGHxJW4NuB/HhWCFOIjL0H/ULDmfI9JZOn1JZ4t8fUy/a5WC+Cq+9All
+                A7RJX6MK3t5CqoU7LdxtYR73WljAYgv38WALTOEh7C1cUphUqCtMKZQVLGqD
+                QkPBVPhQYULh0X8DbMCoJggAAA==
+                """
+        )
+
+    private val LazyListStub =
+        bytecodeStub(
+            filename = "LazyList.kt",
+            filepath = "androidx/compose/foundation/lazy",
+            checksum = 0xf4f32297,
+            source =
+                """
+package androidx.compose.foundation.lazy
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+
+@Composable
+fun LazyColumn(
+    modifier: Modifier = Modifier,
+    content: LazyListScope.() -> Unit,
+) {}
+
+interface LazyListScope {
+    fun item(
+        key: Any? = null,
+        contentType: Any? = null,
+        content: @Composable LazyItemScope.() -> Unit
+    )
+
+    fun items(
+        count: Int,
+        key: ((index: Int) -> Any)? = null,
+        contentType: (index: Int) -> Any? = { null },
+        itemContent: @Composable LazyItemScope.(index: Int) -> Unit
+    )
+}
+
+interface LazyItemScope
+
+inline fun <T> LazyListScope.items(
+    items: List<T>,
+    noinline key: ((item: T) -> Any)? = null,
+    noinline contentType: (item: T) -> Any? = { null },
+    crossinline itemContent: @Composable LazyItemScope.(item: T) -> Unit
+) = items(
+    count = items.size,
+    key = if (key != null) { index: Int -> key(items[index]) } else null,
+    contentType = { index: Int -> contentType(items[index]) }
+) {
+    itemContent(items[it])
+}
+
+inline fun <T> LazyListScope.itemsIndexed(
+    items: List<T>,
+    noinline key: ((index: Int, item: T) -> Any)? = null,
+    crossinline contentType: (index: Int, item: T) -> Any? = { _, _ -> null },
+    crossinline itemContent: @Composable LazyItemScope.(index: Int, item: T) -> Unit
+) =
+    items(
+        count = items.size,
+        key = if (key != null) { index: Int -> key(index, items[index]) } else null,
+        contentType = { index -> contentType(index, items[index]) }
+    ) {
+        itemContent(it, items[it])
+    }
+            """,
+            """
+                META-INF/main.kotlin_module:
+                H4sIAAAAAAAA/2NgYGBmYGBgBGJOBijg8uCSSsxLKcrPTKnQS87PLcgvTtVL
+                zMvMTSzJzM8TEnQEM1NTnPPzSlLzSrxLhMSDMxKLUlNCihLzijNBioKT8wtS
+                vUu49LgUMExKyy/NSwEbpZeTWFUpxOUDJH0yi4EGcfFyMafl5wuxhaSCuEoM
+                WgwA3lzNQaEAAAA=
+                """,
+            """
+                androidx/compose/foundation/lazy/LazyItemScope.class:
+                H4sIAAAAAAAA/5VOy04CQRCsHpTH4gNUEvwJBog3T15MNlljIomXPQ27gxl2
+                d4YwA0FPfJcHw9mPMvbiF9idVFd3JVX9/fP5BeAOA8JI2XztTL6TmatWzmu5
+                cBubq2CclaX6eJcJQxx0NcvcSrdAhN5SbRWL9k0+z5c6Cy00CP2kcKE0Vj7p
+                oNhA3RNEtW1wEtXQqQEEKvi+M/U2ZpZPCIPDvh2JoYhEj9lieNhPxZhqcUoY
+                J/97kWM5pVvfEuPDqAiEaOY260w/mlITbl82NphKvxpv5qV+sNaFo5lvciRO
+                8FcC10e8wg3PCXuecjdTNGK0YrRjdBAxRTfGGc5TkMcFLlMIj55H/xfnXlYi
+                ZgEAAA==
+                """,
+            """
+                androidx/compose/foundation/lazy/LazyListKt$items$1.class:
+                H4sIAAAAAAAA/8VTbW8TRxB+9uw4zsUkTspbwksDGHAc4OJA0jYO0ChNxIkj
+                IGxZqvJpbW/MJue96PbOCnzKb+kvAFUCqZWqiI/9URWz54NGIqIFPvDh5mZn
+                Zp+ZfWbm73/++AvAHfzMcJurThjIzr7TDnp7gRbOdhCrDo9koByfv3jueCQ8
+                qaOHUUlGoqdL1WEwhundIPKlcnb6PUeqSISK+xTba3X4MDIMF4/4t2PVNoDa
+                2Ug1whhiyK1IJaN7DJnybJMhW3ZnmwUMY8RGFjYZomdSMyx6X1BkjeCl6ge7
+                gqFU9nZ4n1Oo6jqPWzuiHdVmj5iahE3xp8qNxnH2kheEXWdHRK2QS3oEVyqI
+                +OBBm7Hv85YvKMySEcPkx5kYrv1H/tRUwBjGbVg4RWB7VYb8SttPGDKk5I1n
+                iozuZr2xurm2XsA5nBgh43mGCS+l+5GIOBHDTT29fobazIwYMQIMbNco1B5r
+                XxrtJWkdyjR/eGDb9FlFZlv5bPHwYDp7ls2zy9n84UHRWsgVM9PWA+uB/fa3
+                XJb8Q+beAsPoCleBet4LYk1tNAkaDHOf0a5h3GQ4MehZR2zz2CcSX5f/f8fr
+                7WBP1AZkxpGkGSRjzfv09H2lf6HmHtNQGl0H88TJ+9Ju7dJbKt5xi1IP4rAt
+                fhGtuLu+HwmlCZVaNtTnfkwDu19/tPrEPoJjP0xA7Ep95r22Yc/NVGeOxnzB
+                ltgVz65eqd5YXFomfd3s3FrQEWaOgzb3mzyUZrobRjCMe1KJzbjXEmFqGanL
+                ruJRHJJ+7mmsItkTrupLLcm9+u+eMBRcpUS45nOtBR3H11XbD7RUXZrYZ0GH
+                wR5wsiEN7snjCGKYSlM0P0qAKi1ClgYwR9+U2QyabnOmxSG5RKcSRdCMIlfJ
+                vsHoq2QffiBZGFjpb+5MmCVEJrmxRB6L/hZ7aSR+TOJM9KXk5umBN71ptEl8
+                R/6fEr2I5TR+AiiuEu7JtJJl8lpJJXOvcfpT2LkP2DmcSbDzOPvhRWeSGGD0
+                T1i/vsH077jwKg2ukbTT8kGErCR03CKa7ibpFnCP/t9sznCfst+l+i5iCN9v
+                IeNixsUlF5dxxaVOXXVxDde3wDTKmN1CTqOiMadxQ2NSY0xTjwy7YwRxm747
+                SejiO+4q0wHaBgAA
+                """,
+            """
+                androidx/compose/foundation/lazy/LazyListKt$items$2.class:
+                H4sIAAAAAAAA/8VUX1MbVRT/3c1flhUCQi2gNRaKIaFNk0KrTYqlFGQl0EqY
+                vPC0SW7TS5K7THY3E3zqZ9EvUGfaOvXBYXz0Qzmeuwk0QjRaH3zYs+ece+7v
+                /L+//f7zLwBWUGS4Y8lqyxbVTrpiN49th6ef2Z6sWq6wZbphfXeSLhApCMfd
+                cReEy5vOQjYCxlAp1G23IWT6qN1MC+nylrQaZNwsV61c/9kzT1YUmpPe6nGZ
+                fOHIalsEL2tpk67WeCvXp3pSPuIVN7eWY5j9aycRBBmu/b2jCMIM4byQwl2j
+                XBND4uoF4bmCnFDKuaUSw/6wW/mbBwe51KD4L8DlU2S45oMGF+r8hCE+LCAD
+                ozBGoOEDyqNbf4bYxTANjCOmrCYIOWEulQxE8aGOEKZI4T4XdGm18B6dpg6E
+                hWzbdc4wTcCXk2SYL9itWvqIu+WWJSh4S0rbtbqJ7NnuntdokNXYn0OOYI4h
+                UOOugU8wM4qPcY1hMXEZf4BLA1cRH0UEnzGEhKzyDgMzqSzvLPe8Zpm3IrjB
+                EKWxKVkNjzIIJJZMA58joWMRSwpmRqeipRi04wzD5KDs7g1rPrV08OhOX+y+
+                33yGiTPEXe5aVH6LdFqzHaCNZIqMKAJKqa6YAB12hOJeElelMFdOX8T00xe6
+                FlMkqhETJZmkWe02ux6MEq9lw7EAicFt/dfvw1o0pO5mGUbzlrTlSdP2HNoH
+                5eSAIfUvBiOCh6ro3Tn8IfHPZ6pYsY/5pf0auo//6TybU5vwCBuU+Fkct+ou
+                Q3Lg21W0vVaFP+Zlr7bZcbl0CIJ6E2p3p6dT3F1/qvfh6Ds+iJ4sxs+4LT0V
+                z8T7bd5j6fRkQc/MZ5ZX797P6MlNnWGkKGrScr0WhRHcsKtcDatdsRolqyWs
+                coMfKMIwXhCSd2e/p5nb96QrmtyUbeEIUq2/204Gw5SStzYaluNwEsc3ZaVh
+                O0LWaDSf21UGvVuTLaGwpgYViGGm56J0yQEytF0hmrIItFhMvWTEmzTKGtIk
+                05t1Lt9GgPgo1CP2DWke0V8NfSyZeo2x5PJrTCaDP2H6R381dojGu+e4go/U
+                vuAMX3EKWesh65hQi97D3aZbGv2nkq8I9hUm597iUw1vcV3DS9++QDTs49zw
+                /Vzp2p/7mcI8Fuh8t2c3Sw7X1YtEvPLwkOzVDSOZOsXiGyTfYPki8nwfsnGO
+                bOAmbvnV2iNJJ07z9TN4QjSIdTzu5RTAU/+/iW/p/78NJvbJ+wOKM0Ndzh4i
+                YOKOiRUTq7hr4h6+MPEl7h+COcghf4iwgwcO1hx85WDeZ676ZRwjiC36vvZN
+                t/8AKXvrop8IAAA=
+                """,
+            """
+                androidx/compose/foundation/lazy/LazyListKt$items$3.class:
+                H4sIAAAAAAAA/8VUS1MbRxD+ZvVk2YAg4PBIHMUoREjYQmBwYsnEGEPYILCD
+                VLpwWklreUCapfahEjn5tyR/wKmynXIOKSrH/KiUe1YCKyBbiXPIYXu7Z3q+
+                fszX8+dfv/0O4DaKDCuGqNkWr7UzVat5Yjlm5onliZrhcktkGsaPp5kCiQJ3
+                3F03wV2z6SRWImAM1cKx5Ta4yBy1mhkuXNMWRoOcm5Wakevde+KJqkRzMttd
+                LZsvHBktg+BFPaPT0bpp53qWHlWOzKqbW88xzLw7SARBhuvvDxRBmCGc54K7
+                61RrckBe3SQ8l1MQKjm3UGY4GHQqf7NUyqX75X8JLp8mx3UfVEtULSpHuKXT
+                E5MhPigxDcPQhqDgI6qncw8MscvpahhFTHqNMQST+kJZQxQfqwhhghbcp5wO
+                rRY+4MbpJsJctKxjynWSgK8Wy5AoWHY9c2S6FdvglLwhhOUanUL2vUbDqDRM
+                chv5e84RzDIE6qar4TNMD+NTXGeYT14N0CemhinEhxHBFwwhLmpmm4Hp1Je3
+                nvtes2LaEXzJECX+lI2GRyUEkgu6hq+QVDGPBQkzrVLX0gzKSZZhvF95dwax
+                gO62P4cnL9PAZwHD2Dninuka1H+D1pRmK0CjyaQYkgJU0rFUArTZ5lJ7TlqN
+                0lw7exZTz56pSkyKqEJKlGyyZoJTbIndCEbJUpbDscCMshTcUf/4KaxEQ/L0
+                MsNw3hCWOG1ankOjIcOUGNL/ghsR3Jdt71Dx5+Q/p1Wxap2YV0Zt4Gj+p/3l
+                nByGB9ikws/zuHXsMqT6PmNFy7Or5kOz4tW32jSmDkHQ7YRaHf60i3sbj9Ue
+                HHXXB1FTxfi5tq2m49l4r88HzJ2aKqjZuezi6trdrJraUhmGirwuDNezKY3g
+                plUzJV2tqtEoGzaXI1aSgmG0wIXZYX93ZfbAEy5vmrpocYfT0sbbAaUHSRfC
+                tDcbhuOYZI5uiWrDcrioEzmfWjUGtdOTbS6xJvo1iGG6G6J8JQCyNF8hYlkE
+                SiwmHzPSdSKzggzZ9Gxd2EsIkB6FfMe+p5UH9Je0j6XSLzGSWnyJ8VTwV0z+
+                4g/HLsl4Zx/X8ImcGJzjS00iK11kFWNy1Lu4O3RKof9E6gXBvsD47Gt8ruA1
+                bih47vsXSIZ9nHk/zrWO/0WcCcwhQft7Xb8ZCrgh3yTSZYT75C9PaKn0GeZf
+                IfUKi5eR53qQtQtkDTdxy+/WPlkqaYq/Po1HJIPYwMNuTQE89v9b+IH+/xsx
+                cUDR71GeWbrl5UMEdKzouK1jFWs67uBrHd/g7iGYgxzyhwg7uOdg3cG3DuZ8
+                Zcpv4whBbNP3ne+68wbQeeTnqggAAA==
+                """,
+            """
+                androidx/compose/foundation/lazy/LazyListKt$items$4.class:
+                H4sIAAAAAAAA/8VVbVMbVRR+7uZlwyaF8Ka8xBpLtCEBQlKotUlRSsGuhJQ2
+                KVXR6iZZwkKyy+xuMtQZZ/gF/gj9A61jq/WDw/jRH+V47iaE8CIv6owf9t6z
+                9577POece865f/z5628AZlBhuKHoZdPQyruJklHbMSw1sWHU9bJia4aeqCrf
+                PEtkachqlr1sRzRbrVmRGRGM4bvstmFXNT2x1aglNN1WTV2pknKtWFbSnXsb
+                db3E0azEUktKZbIXYpWJLl8ydtR0dktpKLShVxIyUVVUs03xWNfs9FyaYeTv
+                7RHhZrh6tk0ivAzejEZwcxSW6DkutEyq2xqRUHTS42sM3553KjN5Wc8nC4Xj
+                rh5jzsRJZc7hDzg3tGCQ97rNED7PhwD8CHRBwBVyvXm7DMHjngXQgyDX6mVw
+                R+XxtQB86JfgwQAt2JsaHZq9mF9H84guzavpDWNbZZiJXjYyMvd4LGuYlcSW
+                ahdNRSPfFF03bKXpZ86wc/VqlVj8EW5lk9aH0aO50M4VyiyTMLSSJeIthsHS
+                plraboGsKqZSU0mR4Xq0IxsfFLfUkt2Zn3kOUknzKL2NsISreIeh+2hIRYwx
+                uCoq3dEgBfQkXgDv4j0/IrjOcOtsvtbKqSBDGPdDRIxh+rLRZRA0Mo/JDFOX
+                OyoiQUl0aE2uXiuqpogkg49ivaZU63Tfrui4HMANzEhIYZabOixRir1Pl9WR
+                7SI+oFNyLl+Yzy0sMlw5UgoBpJHpwm3cIWt3CL/vZBD4Toqh+F93pJNlSXd5
+                vDKdwmToPdBcUW2FIBVuVa3hoh7M+NDFB1Cwt7ngos1djUvPSSqTW3f29wak
+                /T1JCArONNScgj6agvt7I8I0u+b2kSzEhGlXyht005LnvvT7917B5+UgFAF/
+                RtEN/VnNqFvU3zhbgSF+iaoVkWfwtJrEDxcsV360s4UfdpWzLyT5L/dTTgE+
+                BrUI/4EdU9uU0LFTn628UTdL6j21WK8s7lLztAiCLsnTaCbrbn5lflXqwJGW
+                HRAplg8fSEtSPJwMd+r8g44oxbJSciw5MXvzdlKKLUoMXXmtoit23SQz3AtG
+                WeVZbpSU6ppiakqxqhb4wNCT1XS1WWqtlcijum5rNVXWG5ql0VK7h80fNkl6
+                M2RdV82FqmJZKv32LOqlqmFRC6Nk3TTKDFIzOEsaBx04LVIMwy2utSbTEYLR
+                43Z07CJJNe+hZBQhBIP8NSL5C0p9AXfpn96d9v8CXCT7wB+iL2nlLs28SIKx
+                +Et0xyZeoi/m+RmDL5xSekpjuLmPN/Amry8c4HOJIwstZAm9vP20cJ/C7ZwL
+                xftCv+Ba7Cd0x2noC71GVMBrxF148sI59xWNvGd5EcUoxjs4Q23OEO1MOJwh
+                TGKKtL/mBS/Q0ohj0zxv0vTHqR/SYX68Pxbfx/TEPlKvcPMVbv2IuedtRq+D
+                NtbB1t9m68eH+MjZ78c8SQLFVXGspCbgaAyjSKMbBTxpee9CyZk/RZnm/y3T
+                oRI7t/0e5cPiOlwylmR8LOM+ZBmfYFlGFivrYBZyeLAO0cKqhYcWHlmYsDDp
+                yEPYIJRuQvmMvs8d7fW/AOmNErvuCgAA
+                """,
+            """
+                androidx/compose/foundation/lazy/LazyListKt$itemsIndexed$1.class:
+                H4sIAAAAAAAA/8VUW28bRRT+Zn3NxkmcEJrGhWJaFxwn1HF6ocQhrXEdsoob
+                ELYsoTyN7Yk7yXrW8u5aKS/kt/ALWiGlEkjI4pEfhTizdolRTQXlAUt75sy5
+                fGfmzPn82+8//QLgLvYZtrlq9x3ZPsu3nG7PcUX+2PFVm3vSUXmbf/csXyVR
+                la534GWkJ7qupdriTLQzhRgYQ+rU8Wyp8ieDbl4qT/QVtyml22zzGEIM1yf8
+                x75qaVw3vzfWtmKIMER3pJLeLkMou9ZgCGettUYCMcyYCMMkg/dUugw71bc/
+                a5GqSDVwTgXDraxVPeEDTimqk/+qeSJaXnFtwtSgGpRwJWvV69McmarT7+RP
+                hNfsc0m34Uo5Hh/d7NC3bd60BYU9yL5e5s2FxyaG5KXt0O82RT+Gdxji1OAG
+                t30RdMpK4F1cMbGMlQTmsWDCwCqD0SswLE0DNXpbhLHTsoNu6wbHdc4HZLQO
+                a/XSYbmSwIeYmyHjDYbF6vjpngiPU5O5hugOQjQ5TIsZLcDATrVCT22cSa09
+                J61NZ3g0PF8yh+emkWSmETdojdMaSg7PU+GrbJPdCMeH50ljK5oMpYzNMK2R
+                lLFv7Ju//hANx6PJmMahE8/ucOWoZ13Hd2lEdME6w8qlMd3jfd4VNHrpzd2/
+                8xTIs/4vxieGewzLf5mhtjjmvu0xXGT/+SDWWk5PjF/d9yRRg4zF6ptJ8R/9
+                d4rT5psY9SkeUDtfHe32Kd0lV53G35rj91visWj6ncqZJ5RLqPT6kcFo+L6v
+                PSl9bU7gmAcBiJmrpV9pe+Z6upCejHl78pq5qlm4Wdi4d3+b9Ir+Ryg7baHH
+                3Glxu8H7UlOurgXDQlUqMWLN2DJTkx3FPb9P+rVvfOXJrrDUQLqS3KVL8jIk
+                LKVEv2xz1xW0Xaiolu24UnWIA0+dNoM5as2e1LjL0/rEsDou0XitAApErTCN
+                cJS+Vc014oveExVJ7tIuQxE05YjmIi8x+yJg2EOSiZGVVp2zqAmPUJCxQR7N
+                O4M91xKPgjgdfXsi0xhnlgI9iS/GUYtAskRoS+P6B4Sl0eZy60MsX+DqxgVS
+                04HTo8AxsNau4b3AP4f3STPoUtf/vNgK7fVv9mcY375E+kfcfBEYoiiTNCls
+                FLCKx0FX7uMzVILC29ij9f+eOnxJhyjTMTOI4NYRQhY+svCxhSzWLOSwbtFT
+                fHIE5lJ/8keIu9ikF3ex5eJOoNx1Me/Su+nezxNQkb6dIOHzPwDW9W/0kwcA
+                AA==
+                """,
+            """
+                androidx/compose/foundation/lazy/LazyListKt$itemsIndexed$2.class:
+                H4sIAAAAAAAA/8VUXVcbRRh+ZhOSsKwQsCAfWmPBGhJoGqC1khRFCnZLgNpg
+                /MCbTTKkA8ksJ7ubA97Y36J/oJ5ja+uFh+OlP8rjO5uEpiQWrRde7Ow778w8
+                79fzvn/8+etvAJbwLcOyJct1W5SPUyW7dmQ7PLVve7JsucKWqar13UkqR0tO
+                OO6mOyNcXnNMWebHvDyzEAZjKOUObbcqZOqgUUsJ6fK6tKr0plYsW5nOs31P
+                lhSok9poSels7sBqWGRFVlImPa3weqZDtVM84CU3s5JhmPx7I2EEGS6/2lAY
+                IYZQVkjhrjAsxl/t10LLCc8VZIQiz8wWGPYvepWd7xHO/O5uJtkrpnMmskm6
+                uOIbCs4c8hOG2EVOGhiA0Q8Nb1BszdIwRM+7bmAIUXVrmJDj5mzBQARv6ujD
+                JVK4DwU9yuZenwRUnJCQDfuQM4wSfnesDNM5u15JHXC3WLcExWBJabtWM55t
+                2932qlW6NdyVvTCmGMINq+rxnX2GsZfh2yk28A4u63gb7zIMvhx9GO8xBCrc
+                NTCNiQFcwcxFXCFWX2W4Fe+Oo1vTI1gD44gP4APMMvQJlSQGZjJc7QHYM1fR
+                F7ptr1ZUSbjGECHSF1QeKJz4rGngOtI6UlhQ9iZ0Ku8Sg3aUZhjpBXrvIur2
+                SCvxsXcvjp6nrs9cql/byBZ3LeKORTqt1gjQpGFq6VcLKB2HSgjQ4bFQ0mOS
+                yuT50umjqH76SNeiaoloJERoT7tJ7Tq7EoyQrC2EogHaBu/qv/8Q0iJ96u0C
+                w0DWkrY8qdmeQw2ujOwyJP8Fq8OgIhmd1Gb4Mf7P+yJfso9419y4cM78p/PF
+                jOrmTeQo/rYf1w5dhkTPmZy3vXqJ3+FFr7J+7HLpEASVqK/R5NX3+a3V+3oH
+                jr7pg+iJfKwtbejJWDrWeef1B4eeyOnp6fTcjZvLaT2xrjP050VFWq5XJ2+C
+                a3aZKzbbJatasOrCKlb5rloYhnJC8mZztDRTDzzpiho3ZUM4glSrLyYMldWU
+                ktfXqpbjcNoOrctS1XaErBBRH9pUaL2Zmg2hsC71yhPDRMtEocsA0tR+fcS5
+                MLRoVA1lkh8QsTXcoj2N37P9RwiQHIGax3nSfEp/1QLRRPIJBhNzTzCSCP6C
+                0Z/8RtmlNdY8xxjeUt2DNr6SFLLWQtYxrCZBCzeHIEnAeOJnDE49Q4z+I1PP
+                8b6G50gE8Nh/8wWtIR9r0bc11nxzZmscSczReaF1b5KMrpJ2nmRl5RO6r14Y
+                ieQpUk+x+BQ3ziOnO5CNM2QDN/Ghn7EvaaeTpPn6CXxFaxD3sNWKK4Cv/f82
+                vqH//81R7JETt8ndZSp4Zg8BE1kTt02s4GOT8rFqUknX9sAc3MH6HkIONhx8
+                5uCug6QvjPvZHCSIHfru+1c//wuxpKVmkAkAAA==
+                """,
+            """
+                androidx/compose/foundation/lazy/LazyListKt$itemsIndexed$3.class:
+                H4sIAAAAAAAA/8VUW1cbVRT+ziQkYRghYEEu2sYWa0igQ4BiJSmKFOyUALWJ
+                8YIvk2RIDyRnWJmZLPDF/hb9A3UtW1sfXKw++qNc7jNJaEpi0frgw+zZZ5+z
+                v33ff/z52+8AlvAdw4opynWbl4/1kl07sh1L37c9UTZdbgu9an5/omeJZLnj
+                brnT3LVqjiHK1rFVnl4MgzGUsoe2W+VCP2jUdC5cqy7MKunUimUz3Xm374mS
+                BHX0zRaXymQPzIZJVkRFN0i1YtXTHaLd4oFVctOraYbJvzcSRpDh8usNhRFi
+                CGW44O4qw2L89X4ttJzwXE5GKPL0TIFh/yKtzFyPcOby+XSyV0znTGSS9HDV
+                N6RNl2zSFm7+5MhiiF3krIYBaP1Q8BbF2CwRQ/R8CBqGEJWvhhmCcWOmoCGC
+                t1X04RIJ3IeclDLZN28GKlKIi4Z9SC6PEn53zAzTWbte0Q8st1g3OcVgCmG7
+                ZjOeHa9aNYtVi54Nd6UxjCmGcMOsetbuPsPYq/jtXGt4D5dVvIsrDIOvhh/G
+                +wyBiuVquIaJAVzF9EVNsxDGdYZb8e5AuiU9otUwjvgAPsQMQx+XWWJgBsP1
+                HoA9kxV9KdvxakWZhBsMEer+gswDhROfMTTMI6VCx4K0N6FSfZcYlKMUw0gv
+                0HsX9XCPtFJj9h7K0fM97Lcw1a9tZNtyTWoek2RKrRGglcMk6ZcElI5DyQTo
+                8phL7jFxZfJ8+fRRVD19pCpRSSIKMRE602kyOM7m2dVghE7KQigamFTmg3fV
+                Fz+GlEif1F5gGMiYwhYnNdtzaNalmTxD8l80dhhUJq2zuxl+iv/z0ciV7COr
+                a4VcuHL+0/1iWg70FrIUf9uPG4cuQ6Lnes7ZXr1k3bGKXmXjmFaNQxBUpL5G
+                s7N+yG2v3Vc7cNQtH0RN5GJtblNNxlKxzjdvvjvURFZNXUvN3lxeSamJDZWh
+                P8crwnS9OnkTXLfLluxnu2RWC2adyzWRl4RhKMuF1RyPlmTqgSdcXrMM0eAO
+                J9HayyVDZTWEsOrrVdNxLDoObYhS1Xa4qFCrPrSp0GozNZtcYl3qlSeGiZaJ
+                QpcBpGgA+6jnwlCiUbmXiX9Ara3gFp1pA5+dP0aA+AjkSs6R5DP6yyGIJpJP
+                MJiYfYKRRPBXjP7sj0qeaKx5jzG8I+cHbXzJSWSlhaxiWO6CFm4WQeKA8cQv
+                GJx6hhj9R6ae4wMFz5EI4LGv8yXRkI+15Nsaa+qc2RpHErN0X2i9mySjaySd
+                I15a+ZTeSw0tkTyF/hSLT3HzPHKqA1k7Q9awjI/8jH1FJ5U4xZdP4GuiQdzD
+                diuuAL7x/zv4lv7/d49ij5y4Te6uUMHTewgYyBi4bWAVnxiUjzWDSrq+B+bg
+                Djb2EHKw6eBzB3cdJH1m3M/mIEHs0nfff/rFXzqdVK6bCQAA
+                """,
+            """
+                androidx/compose/foundation/lazy/LazyListKt$itemsIndexed$4.class:
+                H4sIAAAAAAAA/8VWa1MaVxh+zoIsrkTxlnpJUxptg6AiXpJUjI0x2mxEtIGQ
+                tva2wBFXYNdhF8b0S/MLOtO/0P6BpNOkTT90nH7sj+r0PQsiGuKl7Uw/cM67
+                5/I+7/U5/PnXb78DmMUew7xm5MqmntuPZM3SnmnxyLZZMXKarZtGpKh98yQS
+                pyGuW/aaParbvGSpRo7v89zorAzG8F28YNpF3YjsVksR3bB52dCKdKeUyWmx
+                5r3tipEVSq3Ial2aXoifC1wl1GTW3OOx+K5W1WjDyEdUgsrzcgPikaHbscUY
+                w9Cb7ZHhZrh6uk0yPAyeBZ3ULTLMBE93YaZuUsXWCYSCFBtLM3x/1q2FiYt6
+                PtHC9YlU6qT7J6xZCNORRccmn5O8ZZPuGjZD4Cy/fOiArx0SLlE4aoln8J/0
+                1ocu+MWpbgZ3UB1L++BFr4I29NGCvaPTpXNmuWWJUT49ulE1C5xhNnjRoKnC
+                8ZG4Wc5HdrmdKWs6uagZhmlrNXcTpp2oFIuE0jEqjK2hezF8vEwaZUSRL5MO
+                PWvJeJuhP7vDs4W6kk2trJU4HWS4HmzK1kZml2ft5tJNCiX5mAjWOwgouIp3
+                Gbpfy6+MEQa5qhUrfGOb4TKFt0UR+PAe3lcwiusMncezI2OMwZXnlO7+45fr
+                NvkQxngHQpg4qy1mZEQYHpzu1xtXWkIPINqBKUwzTF00rwySTk4xleHWuUxq
+                YQDD5MVQZdyiBjjSk6iUMiJJ8wxeKpC0yBOFOzim+rCA2wpiWBReDirUHneo
+                wpo6VcZduqUmkqmlxPIKw6VjbezDPay0Yxmr5OhelKGnlfnSHoWuchbR/AcM
+                +zrLUD2dJBqHZ6iKD0+uc1sjFE0YWqq66LVhYmgXAyh1BSG4aHNfF9IzknLk
+                6e2Dp33KwVNF8kvONFCb/F6a/AdPh6Qpds3tJVkKSVOuaY/fTUtt95U/fvBI
+                Xo9QQkHpWNAM03hSMisWUbhASzGEL0BCMj4nwmxmIoYfz8k+QkNzKI+48ozH
+                8F/uzzh88iW+Iv8P7ZgsUJeEWj7QSbNSzvJ7PFPJr+zTk2CRCspVW7VWxt8m
+                15c2lSY9ypqjRAklA4fSqhIORAPNZ/45zyuhuBIdiY7P3ZiPKqEVhaE9qecN
+                za6UyRr3spnjog3MrFZMa2VdyxR5SgwMXXHd4LVerK+MPqwYtl7iqlHVLZ2W
+                Gsy8dET9lF/VMHh5uahZFqfPrhUjWzQtImYq3R2TMq7UYrSqC6V9rQLGMFjH
+                SteQjgEMn7SjaRdRIoU2Kk0Zkt8vnlqSOTWChDX6pke18R2Hi2QvxCu7TSt3
+                aRYt4w+FX6AzNP4CPaG2X9D/3GmsPI2B2j4u4y3RbTjULyShWaprVtAt+Kmu
+                N0P2iHuBcM+VX3Et9DM6wyQESei58gqTEl5hxo3Hz527OzQKYvPgBj1iN5tw
+                Aw3cAIbpPyZzpDk6J0EXFCDR0pBj1xLB36QvAf8xXRbXe0PhA3wwfoDYS3z4
+                Eks/4aNnDUSPoy3ahNbbQOvFfajOfi8ekCRRbHcdK4kWnBODKNDoxhf4uh4B
+                F4rOrKFE8/9d9DDIiDtk7jqlIrEFl4oNFZsqxeahiiRSKh4hvQVm4TE+2YJs
+                4VMLn1nYsjBrYc6RB2CSlk7SkqFf1jmd+xtKpHKC8QsAAA==
+                """,
+            """
+                androidx/compose/foundation/lazy/LazyListKt.class:
+                H4sIAAAAAAAA/81Y61cbxxX/jR7sahG2WIxtCMY0lsNDxpJW2E4RpsXELopB
+                SQOmce3WXaQFL0grol1R7Lapk7bp+/06+dqe03xOP7ROfU4Ph5zTD/2j6t4Z
+                rRYBAvGo23K0c+dx9869v/nNnR3++a+//R3ACH7PENOtfLlk5tfjuVJxtWQb
+                8cVSxcrrjlmy4gX98aP4NBXTpu3cdiQwhsiyvqbTiLUUf2Nh2chRr59B4VqT
+                pUKlaDFMDEzvslox4zOlvLloGuX09ErJKZhWfHmtGF+sWDk+lx2/5daS6cF5
+                hveOZ2NsePfrewU2myutGp7BO5bppMeFDxd32yhXLMcsGvFJ0dYXCkaa4cJ0
+                qbwUXzachbJukhe6ZZUcvepRtuRkK4UCaclF13cZCkNvnf+m5RhlSy/EM5ZT
+                JgNmzpYQZujMPTRyK66FN/WyXjRIkaF/YHrnIqTrema5kSWKIIwTOKmgDREG
+                KVeiWSxHhkqT748tQ1+zJWJQt1Y8mjcW9UrBYZg75spndgfGF6JnP6MSzjKE
+                +ILoFhlh2N+HqKeZDqMbL4XQhZ4wgmhR4EMvQ9B0jKLN8McGdppQSDhfccxC
+                nHc2jfZ44xqHhl0ZmxvdDdr4cX0fi83N0S5oustIK9Zg+hf1onbQfZ2hNawG
+                xmdqsLej++1Z2m7u1m4Zcx6a9riMqIw+hlZ3F809WjVk9FMHJ8tkbWsNMpzY
+                jqOEGEPANh8bDP6BwUwYw7jcikuIM6QOkXqjgpRRTUKSO2VSIONkYaAphXZQ
+                kieFFEYUaLiyPQk1eFvCtSN5mZLwWQWjfIYjvD0iYax5aNoeoY0ruI7PNQuN
+                cJxguHy4PSJhkiE/kHnx2zqMPtxsxWu4RSdr1IwuRt2cxDJEuSinZK0ncdiN
+                Tif4TuSImivGo6ZZXyPFtuoaeQn/L//3SXKPI+UIxKT98EU6xjPZ2bmJ7ORN
+                hisHj33LCJ06s5gL4S3cYThdt5YPKtqIh2tYdGWsvLFu5F/8WaQdczwlzqJ3
+                /odnET8ZtqamDyljib43jnHM/MeMpY5wZu0xe4NzbPTQFHRJxc+Sewru82R5
+                dCOU6r+q4MHxjFDG15tn/NQeGT+nYAG0R9q3EqW3b9S6/eV1NklzqXSz04OC
+                NhlObYvhv5YRj79V98iIR18/SoxFhrHDZ0PPgEiKpRAsrDKc271o23Jjey3A
+                GcPRybxOC+YrrvnpSst4EeIF6LBc4RUfDa6bvJagWj7JfOmNJ9PKxhPFF/EJ
+                cdYT3iPTE+nzukWTN2TfNj1hRHbVumOk0u1LME2WyTTV/NqZSKC7Qw2ovkSL
+                KFkiuPmHFp8sTUndmx+xiMz1Xw7IG08ioSFS0sLUJXPVqVBC0S7KSqS1+7za
+                obZPhejFsBxWZblNDcjywAlh8ORZMin0Invq0dSkdZL0UnIg0t49LN7s2Mcq
+                S6jCzVOus5sfyJ8+ZRTdp39ikc79fR4VPo9w64nTO6yfaRKJSm+3UCSHe7sW
+                n6pNifhubMV3KA9Y4mzDqDff90lKUN78UEswTiGNcXapNRbWX4p7a5031+lG
+                YFNvbZTfGEiBzdGhX1PyrvRZEjQYsEiS4MxvMAH//jrg597WUcLvs3wPNbDH
+                E90rB7sqS/gRfXjWtu/lFdqFgclSnpw9OW1aRrZSXDDKc/zOxOcp5fTCvF42
+                edvtDM2aS5buVMpUf+mt6j9RMtaaaZs0PLF196KL2c5RD6Vtam2zjp5bmdFX
+                3QnCGcsyypMF3bYNGlZmS5Vyzrhl8rEu1+T8rumQpDt/gKcLtKCL/xOAWj+l
+                1gT1+0i2DamtT9EeUzuo/JinE/xMKNOMaMXPqX66qggFp4ShNqjopPFfCG0J
+                v3T1ZZK/4uM+aoREhqIyEiIDZ6jOZx1zvenoCbz7IZQ/49wGum4PxZ7ifHXu
+                X1PpB2sTTpwAz2oyGQ/RpDL534fPUB9ZYq2iH5gfUi8K/1+hclgdoLIroA6R
+                8F8NDsU+4Unx0j+gPoN291Lsr7i6gVc/QoA9w+jdYWqnqf0M1+92Bajx+Q3c
+                +ARfCOJj4QZ3Jg3fc1xFi4TXJFyS8Kr43aBtQj3sOQ9915CfD1FDBNFLCPXg
+                As4hSuVF9FN5leQ1kncwKBAep1B66D45hQwtEQWF13FbYD1PIU8TeLw2Q6j7
+                RK2fan5RG0SWAK2uxMsC/fPBevSpvFBXr67HG3izuh5snFCUaKTYGQzSggTZ
+                TGdQqq7MPAGTfcHgTiIQanuOK5B2YihRVB7CDUe3gawRWatQ91GMvYgQT86Q
+                TFH0IwT8KAE+TvUZklmShTrgU3XAF/ElF/iiB3zRA77oAV90ge/C27h7ZEbe
+                F6B9xQPtgQDtawK0hSpoRnNG3hC/5UaM9IYaMDJJjNQIihQFlSR7KWJkkhh5
+                bRsjFz1GLjVkZNZjZNZj5EOPkV8+KCNXaEWaMvIdwuLgjDwauLsZWcOwMSPr
+                RxswMkaxDFOMMWLkZWJkjGBOEiM1gjZFICcJwhRBl6T4r21j5KLHyHJDRmY9
+                RmY9RnLg/fgNtV4Hv3/zvy6aqypHXXndlZYr77vygSsXXPljerrp+a1Yyp/g
+                dyTXaH6b/HLuwZ9BJYO1DL6O9Qwe4XEG38A374HZ+BbevYcu0rPxbRuKjVM2
+                VBtPbNy28Z6NPhvvi6EZG9+x8V0b3xPNfhuDNj6w8X0bso23RecPbPzw39km
+                pwbQGQAA
+                """,
+            """
+                androidx/compose/foundation/lazy/LazyListScope$DefaultImpls.class:
+                H4sIAAAAAAAA/7VV3U4TQRT+pj9sW1oKSIGKwqII5XcBlRhrTAyC2aQUY5HE
+                mJgs7QBD29mmO4vohQ/gG/gEXuuNQRP1ygsfynimtELwL424F3POnDnzfWfP
+                OXv267f3HwFcwxJD1pGluitKB1bRrdZcj1vbri9LjhKutCrO82dWjpac8FSh
+                6Nb42F2+7fgVZVdrFc8AY+jec/Yd8pQ71vrWHi8qA0GGuFC8OlY6cmZ4mcm1
+                x5PNnYb9laXsqoqQ1t5+1dr2ZVFjedZqU1vI2j9fmdxkmDi2PpSeX6u5dcVL
+                6zVeb0SzclDkNa0YMBjWCz4dmEWnUvHMp0Ltms2XMp36jl/lUnmmdJX5A8cU
+                0lS7wjMVOXA1Y7Yiu2nqnEQQZei4JaRQtxlSmRMhFlRdyB0KMY5OxGOIIMEw
+                117eDCQZQpqI4V7mLJKow+lBbye6cY4hoaG948K+bruw9t8I/+188XdVv3/G
+                hfQiGGBYavPzOUrfgoE0Q8TOFzbu5JdXGG60mcUWTjaOIVyI4jwuMgz/OXEG
+                RhjCjYsMpcx/r4NunFFc0o1zmaGn5b7GlUPv5WQZAtX9IM0hppeoXsDAylqh
+                CRI4EFqbp1lycuYwdLYyMVemBgwtuyVOfVlQTrG85tQ2nK0K7ZM5IXner27x
+                etMSt6Xk9eWK43mcUGIF168X+arQZ+kHvlSiyjeFJ8j5jqRGaKTewwICCOnQ
+                EOiOIowOinGedk/I2kFyOh3+gsQHRB71xt6h61MqFHrxCmGWS4XCDWVtanpm
+                9hB9IbzRIAQIggkmIxEsktpPG6CLZBKDJEcoXaPoIq4U2Y64OPkYJBfTHS2u
+                wQZXuEmRChukxN5i+DPM/NTQzGw6dIix8GnKxAnKPpL9RNlHlAMYJxnEVbL3
+                0oUABTGHNLWVfgbpT6FhLFwnOUxBXSHf8ccI2piwkbExiSkb05ixMfsd3CPV
+                CVwGAAA=
+                """,
+            """
+                androidx/compose/foundation/lazy/LazyListScope$items$1.class:
+                H4sIAAAAAAAA/6VTW08TQRT+Zru0paxQQO7erVpQWEDES/GCiHGTiomQJoan
+                aTvgwO4M6e426BO/xRdfNSaYaGKIj/4o45ltVRKMCfqwZ07P+c53zpz5+u37
+                py8A5rDEMM9VvaFlfdet6WBHh8Ld0LGq80hq5fr89Su3TKYsw2i1pndEQUYi
+                CAszGTCG0W0d+VK5W83AlSoSDcV9ggfVOs8gxXDmUH4jVjXDGbqP2x5xdDCk
+                F6SS0T2GVHG8wmAXvfGKgww6c7CRo0D0UoYMt8r/NmeJOkjV1NuCoZ+4y1u8
+                yQmvNt0KsVG6UNaNTXdLRNUGlzQeV0pHvDXqSuz7vOoLglkyYmAew+XiIY5n
+                1S1Ri0rjR0MM+d+xlTioikYGJxmytKgK92OR3NhzMIihHAYw7KAbPTlYGKVm
+                OzMMfX8izS7U/GRhZkdZAz9LQW9ldW1xZWnZwXmc6KTgBYbecnv7T0XEaU/c
+                XCJopujhmTGdxoDutG0cei1rVxpvmrw6tZ882OvOHezlrDxrHVk68gd7o/Yw
+                m2az6bw1ak2nnuS+vklbWdsUzTJ0LXCl1atAxyE9KbGXjvlsj8QGj/3IC3b8
+                MANiPNF6yHorzvC2eEwllLzy32VY+r/8LDU4KgjS8BxuMEwdb9gMbjI4h5dA
+                O/2JmNqm+9tLui6MOHSN+xXekEafa8Yw9JSlEi2ttSNjz2MVyUB4qilDSaHF
+                3+qmRp5SorHk8zAU9LNnWdV8HUq1SZJ5qesMuVUdN2risTRcI22uyhEmTJPk
+                bHrtNH0jRoOkI5s+kqjRAHkFQpAgkJ6wP6LrfaK8BbJOK0qnqek1/wFCmop5
+                ylh0Wuydsbib4Ax6KKkcbGXblcbrRR/l77VxeSC/SHz97QkeEMJUOBNXDzCw
+                j5F9jP2N2fnF7OAUTlM+izO/7jOUYICuz7BefMS5D7j4PgnYuE+2j9LXcQu3
+                aR0t4DANYLLX6WKLSds7eEjnHSIsoAOX1pHycNnDFQ9FjHuYwFUP1zC5DhZi
+                Cu46OmjRIWZC9Ca2+wcsMXo8xwUAAA==
+                """,
+            """
+                androidx/compose/foundation/lazy/LazyListScope.class:
+                H4sIAAAAAAAA/61UT1PTQBR/m4Q2Df/SIFgqAkrBIkJCx/FShxkHRcNUdES5
+                cFrabSdtuulkU6Z44ubZr+DH8OAwHP1Qji/bFlBAYGSmffve7m9/79++/Pz1
+                /QcAPAWHwArllTDwKh27HDRbgWB2NWjzCo28gNs+/Xxgl1CUPBFtl4MWSwIh
+                YNbpPsVDXrPf7dVZOUqCSkDzItYk8Dpf+vu4eMFOI4h8j9v1/aZdbfNy7E7Y
+                Gz1ttbi4Q+DLbTA9Xy5dK0MXg5cZnhB+4l5UXJOR5EpBWLPrLNoLqYfslPMg
+                ol1PW23fp3s+KxKY+xcsiGIkogbiOgkClbx7VRX+77wQx06MK91giU6r6vKI
+                1VhYXDpf6bVr1PpWiAo3b9pFni9oZLq/95ZFFNko9kNp7qs4DSQWqVgAAdLA
+                /Y4XWzgjSmWVkNmjw2eGklEMxTw6NPCnmKjranfv7F+PMXpPl+d6NXN0WFAc
+                srlmKlnFUQuGrphaVssQh0h9oKdPmYlsxtIsxdGlVJ3k8beEoqekNN4sbB5/
+                Jeag5EiYQ7gOF+Yl14w1ZqWdYcQN6SOWro9amq7nTclCkDspcQOX4hKWjABx
+                q2Y6u9yL4XJO1bH+jCyuU4GAc73WnXxRsANYcLXBDggMlgPsHY8+HrQYgWTP
+                ImD123b69K/t6PSNEJg/fyVs88hrMntd2r1Bnu77e9XBAATy9R3HkcUzXEZP
+                GNhEH/iehrTJIhZu4YIAjeMazzqvsA4mFs/8+qXpFPBG8WZly71kVdr2I7fZ
+                8kUSHhEYOruDLvvwlQa6TG17NU6jdohB5T50c3b5vic8zPgk+BenHyzkczln
+                4bpPhWBoGttBOyyzDc9HiskexU6X4My9BD4D0OIpAkXDAkAC7aXYgiQ8wXVM
+                xXbrcsq6MgWAQAMGT4BDEjiu/QnqSRWWURpo5RG6CJOwIi89BhvXCu4Po9eR
+                XVBdGHXBdCENFqow5sIdGN8FImAC7u7CmICMgEkBA1JmBdwTMCXgvoBpATMC
+                ZgUYAh7I04cC5gTkBMwLWPgNvv/FeEAHAAA=
                 """
         )
 
@@ -111,6 +666,7 @@
                 """
                 ),
                 SharedTransitionScopeStub,
+                AnimatedContentStub,
                 Stubs.Composable,
                 Stubs.Modifier
             )
@@ -144,6 +700,7 @@
                 """
                 ),
                 SharedTransitionScopeStub,
+                AnimatedContentStub,
                 Stubs.Composable,
                 Stubs.Modifier
             )
@@ -184,6 +741,7 @@
                 """
                 ),
                 SharedTransitionScopeStub,
+                AnimatedContentStub,
                 Stubs.Composable,
                 Stubs.Modifier
             )
@@ -228,6 +786,7 @@
                 """
                 ),
                 SharedTransitionScopeStub,
+                AnimatedContentStub,
                 Stubs.Composable,
                 Stubs.Modifier
             )
@@ -275,6 +834,7 @@
                 """
                 ),
                 SharedTransitionScopeStub,
+                AnimatedContentStub,
                 Stubs.Composable,
                 Stubs.Modifier
             )
@@ -337,6 +897,7 @@
                 """
                 ),
                 SharedTransitionScopeStub,
+                AnimatedContentStub,
                 Stubs.Composable,
                 Stubs.Modifier
             )
@@ -375,6 +936,305 @@
                 """
                 ),
                 SharedTransitionScopeStub,
+                AnimatedContentStub,
+                Stubs.Composable,
+                Stubs.Modifier
+            )
+            .run()
+            .expectClean()
+    }
+
+    @Test
+    fun constantLiteralInItemsCall_shouldWarn() {
+        lint()
+            .files(
+                kotlin(
+                    """
+package foo
+
+import androidx.compose.animation.*
+import androidx.compose.foundation.lazy.*
+import androidx.compose.runtime.*
+import androidx.compose.ui.*
+
+@Composable
+fun Test() {
+    SharedTransitionLayout {
+        AnimatedContent(
+            true,
+        ) { targetState ->
+            if (targetState) {
+                items(10) {
+                    MyLayoutComposable(
+                        modifier = Modifier
+                            .sharedElement(
+                                state = rememberSharedContentState("Foo"),
+                                animatedVisibilityScope = this@AnimatedContent
+                            )
+                    )
+                    MyLayoutComposable(
+                        modifier = Modifier
+                            .sharedBounds(
+                                sharedContentState = rememberSharedContentState("Foo" + "Bar"),
+                                animatedVisibilityScope = this@AnimatedContent
+                            )
+                    )
+                    MyLayoutComposable(
+                        modifier = Modifier
+                            .sharedElement(
+                                state = rememberSharedContentState(0),
+                                animatedVisibilityScope = this@AnimatedContent
+                            )
+                    )
+                }
+                items(List(10) { it }) {
+                    MyLayoutComposable(
+                        modifier = Modifier
+                            .sharedElement(
+                                state = rememberSharedContentState("Foo"),
+                                animatedVisibilityScope = this@AnimatedContent
+                            )
+                    )
+                    MyLayoutComposable(
+                        modifier = Modifier
+                            .sharedBounds(
+                                sharedContentState = rememberSharedContentState("Foo" + "Bar"),
+                                animatedVisibilityScope = this@AnimatedContent
+                            )
+                    )
+                    MyLayoutComposable(
+                        modifier = Modifier
+                            .sharedElement(
+                                state = rememberSharedContentState(0),
+                                animatedVisibilityScope = this@AnimatedContent
+                            )
+                    )
+                }
+                itemsIndexed(List(10) { it }) { _, _ ->
+                    MyLayoutComposable(
+                        modifier = Modifier
+                            .sharedElement(
+                                state = rememberSharedContentState("Foo"),
+                                animatedVisibilityScope = this@AnimatedContent
+                            )
+                    )
+                    MyLayoutComposable(
+                        modifier = Modifier
+                            .sharedBounds(
+                                sharedContentState = rememberSharedContentState("Foo" + "Bar"),
+                                animatedVisibilityScope = this@AnimatedContent
+                            )
+                    )
+                    MyLayoutComposable(
+                        modifier = Modifier
+                            .sharedElement(
+                                state = rememberSharedContentState(0),
+                                animatedVisibilityScope = this@AnimatedContent
+                            )
+                    )
+                }
+            } else {
+                // Do Nothing
+            }
+        }
+    }
+}
+
+@Composable
+fun MyLayoutComposable(modifier: Modifier = Modifier) {
+    // Do Nothing
+}
+                    """
+                ),
+                SharedTransitionScopeStub,
+                AnimatedContentStub,
+                LazyListStub,
+                Stubs.Composable,
+                Stubs.Modifier
+            )
+            .run()
+            .expect(
+                """src/foo/test.kt:20: Error: Each Composable within a LazyList items call should have unique content state keys. Make sure to either associate a unique key related to the item's data, or simply append the item's index to the key. [ConstantContentStateKeyInItemsCall]
+                                state = rememberSharedContentState("Foo"),
+                                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+src/foo/test.kt:27: Error: Each Composable within a LazyList items call should have unique content state keys. Make sure to either associate a unique key related to the item's data, or simply append the item's index to the key. [ConstantContentStateKeyInItemsCall]
+                                sharedContentState = rememberSharedContentState("Foo" + "Bar"),
+                                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+src/foo/test.kt:34: Error: Each Composable within a LazyList items call should have unique content state keys. Make sure to either associate a unique key related to the item's data, or simply append the item's index to the key. [ConstantContentStateKeyInItemsCall]
+                                state = rememberSharedContentState(0),
+                                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+src/foo/test.kt:43: Error: Each Composable within a LazyList items call should have unique content state keys. Make sure to either associate a unique key related to the item's data, or simply append the item's index to the key. [ConstantContentStateKeyInItemsCall]
+                                state = rememberSharedContentState("Foo"),
+                                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+src/foo/test.kt:50: Error: Each Composable within a LazyList items call should have unique content state keys. Make sure to either associate a unique key related to the item's data, or simply append the item's index to the key. [ConstantContentStateKeyInItemsCall]
+                                sharedContentState = rememberSharedContentState("Foo" + "Bar"),
+                                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+src/foo/test.kt:57: Error: Each Composable within a LazyList items call should have unique content state keys. Make sure to either associate a unique key related to the item's data, or simply append the item's index to the key. [ConstantContentStateKeyInItemsCall]
+                                state = rememberSharedContentState(0),
+                                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+src/foo/test.kt:66: Error: Each Composable within a LazyList items call should have unique content state keys. Make sure to either associate a unique key related to the item's data, or simply append the item's index to the key. [ConstantContentStateKeyInItemsCall]
+                                state = rememberSharedContentState("Foo"),
+                                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+src/foo/test.kt:73: Error: Each Composable within a LazyList items call should have unique content state keys. Make sure to either associate a unique key related to the item's data, or simply append the item's index to the key. [ConstantContentStateKeyInItemsCall]
+                                sharedContentState = rememberSharedContentState("Foo" + "Bar"),
+                                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+src/foo/test.kt:80: Error: Each Composable within a LazyList items call should have unique content state keys. Make sure to either associate a unique key related to the item's data, or simply append the item's index to the key. [ConstantContentStateKeyInItemsCall]
+                                state = rememberSharedContentState(0),
+                                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+9 errors, 0 warnings"""
+            )
+    }
+
+    @Test
+    fun constantLiteralInIndividualItemCall_shouldNotWarn() {
+        lint()
+            .files(
+                kotlin(
+                    """
+package foo
+
+import androidx.compose.animation.*
+import androidx.compose.foundation.lazy.*
+import androidx.compose.runtime.*
+import androidx.compose.ui.*
+
+@Composable
+fun Test() {
+    SharedTransitionLayout {
+        AnimatedContent(
+            true,
+        ) { targetState ->
+            if (targetState) {
+                item {
+                    MyLayoutComposable(
+                        modifier = Modifier
+                            .sharedElement(
+                                state = rememberSharedContentState("Foo"),
+                                animatedVisibilityScope = this@AnimatedContent
+                            )
+                    )
+                    MyLayoutComposable(
+                        modifier = Modifier
+                            .sharedBounds(
+                                sharedContentState = rememberSharedContentState("Foo" + "Bar"),
+                                animatedVisibilityScope = this@AnimatedContent
+                            )
+                    )
+                    MyLayoutComposable(
+                        modifier = Modifier
+                            .sharedElement(
+                                state = rememberSharedContentState(0),
+                                animatedVisibilityScope = this@AnimatedContent
+                            )
+                    )
+                }
+            } else {
+                // Do Nothing
+            }
+        }
+    }
+}
+
+@Composable
+fun MyLayoutComposable(modifier: Modifier = Modifier) {
+    // Do Nothing
+}
+                    """
+                ),
+                SharedTransitionScopeStub,
+                AnimatedContentStub,
+                LazyListStub,
+                Stubs.Composable,
+                Stubs.Modifier
+            )
+            .run()
+            .expectClean()
+    }
+
+    @Test
+    fun complexExpressionKeysInItemsCall_shouldNotWarn() {
+        lint()
+            .files(
+                kotlin(
+                    """
+package foo
+
+import androidx.compose.animation.*
+import androidx.compose.foundation.lazy.*
+import androidx.compose.runtime.*
+import androidx.compose.ui.*
+
+@Composable
+fun Test() {
+    SharedTransitionLayout {
+        AnimatedContent(
+            true,
+        ) { targetState ->
+            if (targetState) {
+                items(10) { index ->
+                    MyLayoutComposable(
+                        modifier = Modifier
+                            .sharedElement(
+                                state = rememberSharedContentState(10 + index),
+                                animatedVisibilityScope = this@AnimatedContent
+                            )
+                    )
+                    MyLayoutComposable(
+                        modifier = Modifier
+                            .sharedBounds(
+                                sharedContentState = rememberSharedContentState("Foo" + index),
+                                animatedVisibilityScope = this@AnimatedContent
+                            )
+                    )
+                }
+                items(List(10) { it }) { index ->
+                    MyLayoutComposable(
+                        modifier = Modifier
+                            .sharedElement(
+                                state = rememberSharedContentState(10 + index),
+                                animatedVisibilityScope = this@AnimatedContent
+                            )
+                    )
+                    MyLayoutComposable(
+                        modifier = Modifier
+                            .sharedBounds(
+                                sharedContentState = rememberSharedContentState("Foo" + index),
+                                animatedVisibilityScope = this@AnimatedContent
+                            )
+                    )
+                }
+                itemsIndexed(List(10) { it }) { index, _ ->
+                    MyLayoutComposable(
+                        modifier = Modifier
+                            .sharedElement(
+                                state = rememberSharedContentState(10 + index),
+                                animatedVisibilityScope = this@AnimatedContent
+                            )
+                    )
+                    MyLayoutComposable(
+                        modifier = Modifier
+                            .sharedBounds(
+                                sharedContentState = rememberSharedContentState("Foo" + index),
+                                animatedVisibilityScope = this@AnimatedContent
+                            )
+                    )
+                }
+            } else {
+                // Do Nothing
+            }
+        }
+    }
+}
+
+@Composable
+fun MyLayoutComposable(modifier: Modifier = Modifier) {
+    // Do Nothing
+}
+                    """
+                ),
+                SharedTransitionScopeStub,
+                AnimatedContentStub,
+                LazyListStub,
                 Stubs.Composable,
                 Stubs.Modifier
             )
diff --git a/compose/animation/animation/build.gradle b/compose/animation/animation/build.gradle
index 412e1be..6dd8e8b5 100644
--- a/compose/animation/animation/build.gradle
+++ b/compose/animation/animation/build.gradle
@@ -33,14 +33,14 @@
 
 androidXMultiplatform {
     android()
-    desktop()
+    jvmStubs()
 
     defaultPlatform(PlatformIdentifier.ANDROID)
 
     sourceSets {
         commonMain {
             dependencies {
-                implementation(libs.kotlinStdlibCommon)
+                implementation(libs.kotlinStdlib)
 
                 api(project(":compose:animation:animation-core"))
                 api("androidx.compose.foundation:foundation-layout:1.6.0")
@@ -75,26 +75,21 @@
             }
         }
 
-        desktopMain {
+        jvmStubsMain {
             dependsOn(jvmMain)
             dependencies {
-                implementation(libs.kotlinStdlib)
-            }
-        }
-
-        jvmTest {
-            dependsOn(commonTest)
-            dependencies {
             }
         }
 
         androidInstrumentedTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(libs.testRules)
                 implementation(libs.testRunner)
                 implementation(libs.junit)
                 implementation(libs.truth)
+                implementation(libs.leakcanary)
+                implementation(libs.leakcanaryInstrumentation)
                 implementation("androidx.compose.foundation:foundation:1.2.1")
                 implementation(project(":compose:material3:material3"))
                 implementation("androidx.compose.ui:ui-test-junit4:1.2.1")
@@ -103,17 +98,13 @@
         }
 
         androidUnitTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(libs.testRules)
                 implementation(libs.testRunner)
                 implementation(libs.junit)
             }
         }
-
-        desktopTest {
-            dependsOn(jvmTest)
-        }
     }
 }
 
diff --git a/compose/animation/animation/src/androidInstrumentedTest/kotlin/androidx/compose/animation/AnimatedContentTest.kt b/compose/animation/animation/src/androidInstrumentedTest/kotlin/androidx/compose/animation/AnimatedContentTest.kt
index b0d1f53..1bb80e5 100644
--- a/compose/animation/animation/src/androidInstrumentedTest/kotlin/androidx/compose/animation/AnimatedContentTest.kt
+++ b/compose/animation/animation/src/androidInstrumentedTest/kotlin/androidx/compose/animation/AnimatedContentTest.kt
@@ -73,6 +73,7 @@
 import com.google.common.truth.Truth.assertThat
 import kotlin.math.roundToInt
 import kotlinx.coroutines.delay
+import leakcanary.DetectLeaksAfterTestSuccess
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertNotEquals
@@ -81,13 +82,16 @@
 import org.junit.Assert.assertTrue
 import org.junit.Rule
 import org.junit.Test
+import org.junit.rules.RuleChain
 import org.junit.runner.RunWith
 
 @RunWith(AndroidJUnit4::class)
 @LargeTest
 class AnimatedContentTest {
-
-    @get:Rule val rule = createComposeRule()
+    val rule = createComposeRule()
+    // Detect leaks BEFORE and AFTER compose rule work
+    @get:Rule
+    val ruleChain: RuleChain = RuleChain.outerRule(DetectLeaksAfterTestSuccess()).around(rule)
 
     @OptIn(InternalAnimationApi::class)
     @Test
diff --git a/compose/animation/animation/src/androidInstrumentedTest/kotlin/androidx/compose/animation/AnimatedVisibilityTest.kt b/compose/animation/animation/src/androidInstrumentedTest/kotlin/androidx/compose/animation/AnimatedVisibilityTest.kt
index 2363ca0..95e29c3a 100644
--- a/compose/animation/animation/src/androidInstrumentedTest/kotlin/androidx/compose/animation/AnimatedVisibilityTest.kt
+++ b/compose/animation/animation/src/androidInstrumentedTest/kotlin/androidx/compose/animation/AnimatedVisibilityTest.kt
@@ -59,19 +59,23 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
 import com.google.common.truth.Truth.assertThat
+import leakcanary.DetectLeaksAfterTestSuccess
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertTrue
 import org.junit.Rule
 import org.junit.Test
+import org.junit.rules.RuleChain
 import org.junit.runner.RunWith
 
 @RunWith(AndroidJUnit4::class)
 @LargeTest
 @OptIn(InternalAnimationApi::class)
 class AnimatedVisibilityTest {
-
-    @get:Rule val rule = createComposeRule()
+    val rule = createComposeRule()
+    // Detect leaks BEFORE and AFTER compose rule work
+    @get:Rule
+    val ruleChain: RuleChain = RuleChain.outerRule(DetectLeaksAfterTestSuccess()).around(rule)
 
     private val frameDuration = 16
 
diff --git a/compose/animation/animation/src/androidInstrumentedTest/kotlin/androidx/compose/animation/AnimationModifierTest.kt b/compose/animation/animation/src/androidInstrumentedTest/kotlin/androidx/compose/animation/AnimationModifierTest.kt
index e1dbd9d..078ecf5 100644
--- a/compose/animation/animation/src/androidInstrumentedTest/kotlin/androidx/compose/animation/AnimationModifierTest.kt
+++ b/compose/animation/animation/src/androidInstrumentedTest/kotlin/androidx/compose/animation/AnimationModifierTest.kt
@@ -61,6 +61,7 @@
 import junit.framework.TestCase.assertTrue
 import kotlin.math.roundToInt
 import kotlin.random.Random
+import leakcanary.DetectLeaksAfterTestSuccess
 import org.hamcrest.CoreMatchers.`is`
 import org.hamcrest.CoreMatchers.nullValue
 import org.hamcrest.MatcherAssert.assertThat
@@ -68,13 +69,16 @@
 import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
+import org.junit.rules.RuleChain
 import org.junit.runner.RunWith
 
 @RunWith(AndroidJUnit4::class)
 @LargeTest
 class AnimationModifierTest {
-
-    @get:Rule val rule = createComposeRule()
+    val rule = createComposeRule()
+    // Detect leaks BEFORE and AFTER compose rule work
+    @get:Rule
+    val ruleChain: RuleChain = RuleChain.outerRule(DetectLeaksAfterTestSuccess()).around(rule)
 
     @Before
     fun before() {
diff --git a/compose/animation/animation/src/androidInstrumentedTest/kotlin/androidx/compose/animation/CrossfadeTest.kt b/compose/animation/animation/src/androidInstrumentedTest/kotlin/androidx/compose/animation/CrossfadeTest.kt
index d09b4a4..6abc2d0 100644
--- a/compose/animation/animation/src/androidInstrumentedTest/kotlin/androidx/compose/animation/CrossfadeTest.kt
+++ b/compose/animation/animation/src/androidInstrumentedTest/kotlin/androidx/compose/animation/CrossfadeTest.kt
@@ -36,18 +36,22 @@
 import androidx.compose.ui.unit.dp
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
+import leakcanary.DetectLeaksAfterTestSuccess
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertTrue
 import org.junit.Rule
 import org.junit.Test
+import org.junit.rules.RuleChain
 import org.junit.runner.RunWith
 
 @RunWith(AndroidJUnit4::class)
 @MediumTest
 class CrossfadeTest {
-
-    @get:Rule val rule = createComposeRule()
+    val rule = createComposeRule()
+    // Detect leaks BEFORE and AFTER compose rule work
+    @get:Rule
+    val ruleChain: RuleChain = RuleChain.outerRule(DetectLeaksAfterTestSuccess()).around(rule)
 
     @Test
     fun crossfadeTest_showsContent() {
diff --git a/compose/animation/animation/src/androidInstrumentedTest/kotlin/androidx/compose/animation/SharedTransitionTest.kt b/compose/animation/animation/src/androidInstrumentedTest/kotlin/androidx/compose/animation/SharedTransitionTest.kt
index c79bee0..b76bd88 100644
--- a/compose/animation/animation/src/androidInstrumentedTest/kotlin/androidx/compose/animation/SharedTransitionTest.kt
+++ b/compose/animation/animation/src/androidInstrumentedTest/kotlin/androidx/compose/animation/SharedTransitionTest.kt
@@ -99,15 +99,19 @@
 import kotlin.math.sqrt
 import kotlin.random.Random
 import kotlinx.coroutines.runBlocking
+import leakcanary.DetectLeaksAfterTestSuccess
 import org.junit.Rule
 import org.junit.Test
+import org.junit.rules.RuleChain
 import org.junit.runner.RunWith
 
 @RunWith(AndroidJUnit4::class)
 @LargeTest
 class SharedTransitionTest {
-
-    @get:Rule val rule = createComposeRule()
+    val rule = createComposeRule()
+    // Detect leaks BEFORE and AFTER compose rule work
+    @get:Rule
+    val ruleChain: RuleChain = RuleChain.outerRule(DetectLeaksAfterTestSuccess()).around(rule)
 
     @Test
     fun transitionInterruption() {
diff --git a/compose/animation/animation/src/desktopMain/kotlin/androidx/compose/animation/DesktopActualDefaultDecayAnimationSpec.desktop.kt b/compose/animation/animation/src/desktopMain/kotlin/androidx/compose/animation/DesktopActualDefaultDecayAnimationSpec.desktop.kt
deleted file mode 100644
index f1fe969..0000000
--- a/compose/animation/animation/src/desktopMain/kotlin/androidx/compose/animation/DesktopActualDefaultDecayAnimationSpec.desktop.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.animation
-
-import androidx.compose.animation.core.DecayAnimationSpec
-import androidx.compose.runtime.Composable
-
-@Composable
-@Deprecated("Replace with rememberSplineBasedDecay<Float>")
-actual fun defaultDecayAnimationSpec(): DecayAnimationSpec<Float> {
-    return rememberSplineBasedDecay()
-}
diff --git a/compose/animation/animation/src/desktopMain/kotlin/androidx/compose/animation/SplineBasedDecayAnimationSpec.desktop.kt b/compose/animation/animation/src/desktopMain/kotlin/androidx/compose/animation/SplineBasedDecayAnimationSpec.desktop.kt
deleted file mode 100644
index de2a36a..0000000
--- a/compose/animation/animation/src/desktopMain/kotlin/androidx/compose/animation/SplineBasedDecayAnimationSpec.desktop.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.animation
-
-import androidx.compose.animation.core.DecayAnimationSpec
-import androidx.compose.animation.core.generateDecayAnimationSpec
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
-import androidx.compose.ui.platform.LocalDensity
-
-internal actual val platformFlingScrollFriction = 0.015f
-
-@Composable
-actual fun <T> rememberSplineBasedDecay(): DecayAnimationSpec<T> {
-    // This function will internally update the calculation of fling decay when the density changes,
-    // but the reference to the returned spec will not change across calls.
-    val density = LocalDensity.current
-    return remember(density.density) {
-        SplineBasedFloatDecayAnimationSpec(density).generateDecayAnimationSpec()
-    }
-}
diff --git a/compose/animation/animation/src/jvmStubsMain/kotlin/androidx/compose/animation/DesktopActualDefaultDecayAnimationSpec.jvmStubs.kt b/compose/animation/animation/src/jvmStubsMain/kotlin/androidx/compose/animation/DesktopActualDefaultDecayAnimationSpec.jvmStubs.kt
new file mode 100644
index 0000000..5d4919c
--- /dev/null
+++ b/compose/animation/animation/src/jvmStubsMain/kotlin/androidx/compose/animation/DesktopActualDefaultDecayAnimationSpec.jvmStubs.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.animation
+
+import androidx.compose.animation.core.DecayAnimationSpec
+import androidx.compose.runtime.Composable
+
+@Composable
+actual fun defaultDecayAnimationSpec(): DecayAnimationSpec<Float> = implementedInJetBrainsFork()
diff --git a/compose/animation/animation/src/jvmStubsMain/kotlin/androidx/compose/animation/NotImplemented.jvmStubs.kt b/compose/animation/animation/src/jvmStubsMain/kotlin/androidx/compose/animation/NotImplemented.jvmStubs.kt
new file mode 100644
index 0000000..d134533
--- /dev/null
+++ b/compose/animation/animation/src/jvmStubsMain/kotlin/androidx/compose/animation/NotImplemented.jvmStubs.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.animation
+
+@Suppress("NOTHING_TO_INLINE")
+internal inline fun implementedInJetBrainsFork(): Nothing =
+    throw NotImplementedError(
+        """
+        Implemented only in JetBrains fork.
+        Please use `org.jetbrains.compose.animation:animation` package instead.
+        """
+            .trimIndent()
+    )
diff --git a/compose/animation/animation/src/jvmStubsMain/kotlin/androidx/compose/animation/SplineBasedDecayAnimationSpec.jvmStubs.kt b/compose/animation/animation/src/jvmStubsMain/kotlin/androidx/compose/animation/SplineBasedDecayAnimationSpec.jvmStubs.kt
new file mode 100644
index 0000000..3c8f6b7
--- /dev/null
+++ b/compose/animation/animation/src/jvmStubsMain/kotlin/androidx/compose/animation/SplineBasedDecayAnimationSpec.jvmStubs.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.animation
+
+import androidx.compose.animation.core.DecayAnimationSpec
+import androidx.compose.runtime.Composable
+
+internal actual val platformFlingScrollFriction: Float = implementedInJetBrainsFork()
+
+@Composable
+actual fun <T> rememberSplineBasedDecay(): DecayAnimationSpec<T> = implementedInJetBrainsFork()
diff --git a/compose/compiler/OWNERS b/compose/compiler/OWNERS
index 51ec95d..48bdf50 100644
--- a/compose/compiler/OWNERS
+++ b/compose/compiler/OWNERS
@@ -1,5 +1,4 @@
 # Bug component: 343210
[email protected]
 [email protected]
 [email protected]
 [email protected]
diff --git a/compose/foundation/foundation-layout/build.gradle b/compose/foundation/foundation-layout/build.gradle
index a177d4b..5019aed 100644
--- a/compose/foundation/foundation-layout/build.gradle
+++ b/compose/foundation/foundation-layout/build.gradle
@@ -32,15 +32,14 @@
 
 androidXMultiplatform {
     android()
-    desktop()
+    jvmStubs()
 
     defaultPlatform(PlatformIdentifier.ANDROID)
 
     sourceSets {
         commonMain {
             dependencies {
-                implementation(libs.kotlinStdlibCommon)
-
+                implementation(libs.kotlinStdlib)
                 api("androidx.compose.ui:ui:1.6.0")
                 implementation(project(":compose:runtime:runtime"))
                 implementation(project(":compose:ui:ui-util"))
@@ -70,21 +69,14 @@
             }
         }
 
-        desktopMain {
+        jvmStubsMain {
             dependsOn(jvmMain)
             dependencies {
-                implementation(libs.kotlinStdlib)
-            }
-        }
-
-        jvmTest {
-            dependsOn(commonTest)
-            dependencies {
             }
         }
 
         androidInstrumentedTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(project(":compose:foundation:foundation"))
                 implementation("androidx.compose.ui:ui-test-junit4:1.2.1")
@@ -99,7 +91,7 @@
         }
 
         androidUnitTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(libs.testRules)
                 implementation(libs.testRunner)
@@ -107,10 +99,6 @@
                 implementation(libs.truth)
             }
         }
-
-        desktopTest {
-            dependsOn(jvmTest)
-        }
     }
 }
 
diff --git a/compose/foundation/foundation-layout/src/desktopMain/kotlin/androidx/compose/foundation/layout/WindowInsets.desktop.kt b/compose/foundation/foundation-layout/src/desktopMain/kotlin/androidx/compose/foundation/layout/WindowInsets.desktop.kt
deleted file mode 100644
index 2a17762..0000000
--- a/compose/foundation/foundation-layout/src/desktopMain/kotlin/androidx/compose/foundation/layout/WindowInsets.desktop.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.layout
-
-private val ZeroInsets = WindowInsets(0, 0, 0, 0)
-
-actual val WindowInsets.Companion.captionBar: WindowInsets
-    get() = ZeroInsets
-
-actual val WindowInsets.Companion.displayCutout: WindowInsets
-    get() = ZeroInsets
-
-actual val WindowInsets.Companion.ime: WindowInsets
-    get() = ZeroInsets
-
-actual val WindowInsets.Companion.mandatorySystemGestures: WindowInsets
-    get() = ZeroInsets
-
-actual val WindowInsets.Companion.navigationBars: WindowInsets
-    get() = ZeroInsets
-
-actual val WindowInsets.Companion.statusBars: WindowInsets
-    get() = ZeroInsets
-
-actual val WindowInsets.Companion.systemBars: WindowInsets
-    get() = ZeroInsets
-
-actual val WindowInsets.Companion.systemGestures: WindowInsets
-    get() = ZeroInsets
-
-actual val WindowInsets.Companion.tappableElement: WindowInsets
-    get() = ZeroInsets
-
-actual val WindowInsets.Companion.waterfall: WindowInsets
-    get() = ZeroInsets
-
-actual val WindowInsets.Companion.safeDrawing: WindowInsets
-    get() = ZeroInsets
-
-actual val WindowInsets.Companion.safeGestures: WindowInsets
-    get() = ZeroInsets
-
-actual val WindowInsets.Companion.safeContent: WindowInsets
-    get() = ZeroInsets
diff --git a/compose/foundation/foundation-layout/src/desktopMain/kotlin/androidx/compose/foundation/layout/WindowInsetsPadding.desktop.kt b/compose/foundation/foundation-layout/src/desktopMain/kotlin/androidx/compose/foundation/layout/WindowInsetsPadding.desktop.kt
deleted file mode 100644
index b8e3738..0000000
--- a/compose/foundation/foundation-layout/src/desktopMain/kotlin/androidx/compose/foundation/layout/WindowInsetsPadding.desktop.kt
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.layout
-
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.Stable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.composed
-import androidx.compose.ui.platform.InspectorInfo
-import androidx.compose.ui.platform.debugInspectorInfo
-
-actual fun Modifier.safeDrawingPadding() =
-    windowInsetsPadding(debugInspectorInfo { name = "safeDrawingPadding" }) {
-        WindowInsets.safeDrawing
-    }
-
-actual fun Modifier.safeGesturesPadding() =
-    windowInsetsPadding(debugInspectorInfo { name = "safeGesturesPadding" }) {
-        WindowInsets.safeGestures
-    }
-
-actual fun Modifier.safeContentPadding() =
-    windowInsetsPadding(debugInspectorInfo { name = "safeContentPadding" }) {
-        WindowInsets.safeContent
-    }
-
-actual fun Modifier.systemBarsPadding() =
-    windowInsetsPadding(debugInspectorInfo { name = "systemBarsPadding" }) {
-        WindowInsets.systemBars
-    }
-
-actual fun Modifier.displayCutoutPadding() =
-    windowInsetsPadding(debugInspectorInfo { name = "displayCutoutPadding" }) {
-        WindowInsets.displayCutout
-    }
-
-actual fun Modifier.statusBarsPadding() =
-    windowInsetsPadding(debugInspectorInfo { name = "statusBarsPadding" }) {
-        WindowInsets.statusBars
-    }
-
-actual fun Modifier.imePadding() =
-    windowInsetsPadding(debugInspectorInfo { name = "imePadding" }) { WindowInsets.ime }
-
-actual fun Modifier.navigationBarsPadding() =
-    windowInsetsPadding(debugInspectorInfo { name = "navigationBarsPadding" }) {
-        WindowInsets.navigationBars
-    }
-
-actual fun Modifier.captionBarPadding() =
-    windowInsetsPadding(debugInspectorInfo { name = "captionBarPadding" }) {
-        WindowInsets.captionBar
-    }
-
-actual fun Modifier.waterfallPadding() =
-    windowInsetsPadding(debugInspectorInfo { name = "waterfallPadding" }) { WindowInsets.waterfall }
-
-actual fun Modifier.systemGesturesPadding() =
-    windowInsetsPadding(debugInspectorInfo { name = "systemGesturesPadding" }) {
-        WindowInsets.systemGestures
-    }
-
-actual fun Modifier.mandatorySystemGesturesPadding() =
-    windowInsetsPadding(debugInspectorInfo { name = "mandatorySystemGesturesPadding" }) {
-        WindowInsets.mandatorySystemGestures
-    }
-
-@Suppress("NOTHING_TO_INLINE")
-@Stable
-private inline fun Modifier.windowInsetsPadding(
-    noinline inspectorInfo: InspectorInfo.() -> Unit,
-    crossinline insetsCalculation: @Composable () -> WindowInsets
-): Modifier =
-    composed(inspectorInfo) {
-        val insets = insetsCalculation()
-        InsetsPaddingModifier(insets)
-    }
diff --git a/compose/foundation/foundation-layout/src/jvmStubsMain/kotlin/androidx/compose/foundation/layout/NotImplemented.jvmStubs.kt b/compose/foundation/foundation-layout/src/jvmStubsMain/kotlin/androidx/compose/foundation/layout/NotImplemented.jvmStubs.kt
new file mode 100644
index 0000000..612d448
--- /dev/null
+++ b/compose/foundation/foundation-layout/src/jvmStubsMain/kotlin/androidx/compose/foundation/layout/NotImplemented.jvmStubs.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.foundation.layout
+
+@Suppress("NOTHING_TO_INLINE")
+internal inline fun implementedInJetBrainsFork(): Nothing =
+    throw NotImplementedError(
+        """
+        Implemented only in JetBrains fork.
+        Please use `org.jetbrains.compose.foundation:foundation-layout` package instead.
+        """
+            .trimIndent()
+    )
diff --git a/compose/foundation/foundation-layout/src/jvmStubsMain/kotlin/androidx/compose/foundation/layout/WindowInsets.jvmStubs.kt b/compose/foundation/foundation-layout/src/jvmStubsMain/kotlin/androidx/compose/foundation/layout/WindowInsets.jvmStubs.kt
new file mode 100644
index 0000000..85096b2
--- /dev/null
+++ b/compose/foundation/foundation-layout/src/jvmStubsMain/kotlin/androidx/compose/foundation/layout/WindowInsets.jvmStubs.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.foundation.layout
+
+actual val WindowInsets.Companion.captionBar: WindowInsets
+    get() = implementedInJetBrainsFork()
+
+actual val WindowInsets.Companion.displayCutout: WindowInsets
+    get() = implementedInJetBrainsFork()
+
+actual val WindowInsets.Companion.ime: WindowInsets
+    get() = implementedInJetBrainsFork()
+
+actual val WindowInsets.Companion.mandatorySystemGestures: WindowInsets
+    get() = implementedInJetBrainsFork()
+
+actual val WindowInsets.Companion.navigationBars: WindowInsets
+    get() = implementedInJetBrainsFork()
+
+actual val WindowInsets.Companion.statusBars: WindowInsets
+    get() = implementedInJetBrainsFork()
+
+actual val WindowInsets.Companion.systemBars: WindowInsets
+    get() = implementedInJetBrainsFork()
+
+actual val WindowInsets.Companion.systemGestures: WindowInsets
+    get() = implementedInJetBrainsFork()
+
+actual val WindowInsets.Companion.tappableElement: WindowInsets
+    get() = implementedInJetBrainsFork()
+
+actual val WindowInsets.Companion.waterfall: WindowInsets
+    get() = implementedInJetBrainsFork()
+
+actual val WindowInsets.Companion.safeDrawing: WindowInsets
+    get() = implementedInJetBrainsFork()
+
+actual val WindowInsets.Companion.safeGestures: WindowInsets
+    get() = implementedInJetBrainsFork()
+
+actual val WindowInsets.Companion.safeContent: WindowInsets
+    get() = implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation-layout/src/jvmStubsMain/kotlin/androidx/compose/foundation/layout/WindowInsetsPadding.jvmStubs.kt b/compose/foundation/foundation-layout/src/jvmStubsMain/kotlin/androidx/compose/foundation/layout/WindowInsetsPadding.jvmStubs.kt
new file mode 100644
index 0000000..ec0b474
--- /dev/null
+++ b/compose/foundation/foundation-layout/src/jvmStubsMain/kotlin/androidx/compose/foundation/layout/WindowInsetsPadding.jvmStubs.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.foundation.layout
+
+import androidx.compose.ui.Modifier
+
+actual fun Modifier.safeDrawingPadding(): Modifier = implementedInJetBrainsFork()
+
+actual fun Modifier.safeGesturesPadding(): Modifier = implementedInJetBrainsFork()
+
+actual fun Modifier.safeContentPadding(): Modifier = implementedInJetBrainsFork()
+
+actual fun Modifier.systemBarsPadding(): Modifier = implementedInJetBrainsFork()
+
+actual fun Modifier.displayCutoutPadding(): Modifier = implementedInJetBrainsFork()
+
+actual fun Modifier.statusBarsPadding(): Modifier = implementedInJetBrainsFork()
+
+actual fun Modifier.imePadding(): Modifier = implementedInJetBrainsFork()
+
+actual fun Modifier.navigationBarsPadding(): Modifier = implementedInJetBrainsFork()
+
+actual fun Modifier.captionBarPadding(): Modifier = implementedInJetBrainsFork()
+
+actual fun Modifier.waterfallPadding(): Modifier = implementedInJetBrainsFork()
+
+actual fun Modifier.systemGesturesPadding(): Modifier = implementedInJetBrainsFork()
+
+actual fun Modifier.mandatorySystemGesturesPadding(): Modifier = implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/api/current.txt b/compose/foundation/foundation/api/current.txt
index e3708d9..425b837 100644
--- a/compose/foundation/foundation/api/current.txt
+++ b/compose/foundation/foundation/api/current.txt
@@ -882,7 +882,7 @@
     method @Deprecated public void item(optional Object? key, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.lazy.LazyItemScope,kotlin.Unit> content);
     method public default void items(int count, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,? extends java.lang.Object?> contentType, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.LazyItemScope,? super java.lang.Integer,kotlin.Unit> itemContent);
     method @Deprecated public void items(int count, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.LazyItemScope,? super java.lang.Integer,kotlin.Unit> itemContent);
-    method public void stickyHeader(optional Object? key, optional Object? contentType, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.lazy.LazyItemScope,kotlin.Unit> content);
+    method @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi public void stickyHeader(optional Object? key, optional Object? contentType, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.lazy.LazyItemScope,kotlin.Unit> content);
   }
 
   @androidx.compose.runtime.Stable public final class LazyListState implements androidx.compose.foundation.gestures.ScrollableState {
@@ -1124,7 +1124,7 @@
     property public default kotlin.jvm.functions.Function1<java.lang.Integer,java.lang.Object?> type;
   }
 
-  @androidx.compose.runtime.Stable public interface LazyLayoutItemProvider {
+  @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Stable public interface LazyLayoutItemProvider {
     method @androidx.compose.runtime.Composable public void Item(int index, Object key);
     method public default Object? getContentType(int index);
     method public default int getIndex(Object key);
@@ -1137,7 +1137,7 @@
     method @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static void LazyLayout(kotlin.jvm.functions.Function0<? extends androidx.compose.foundation.lazy.layout.LazyLayoutItemProvider> itemProvider, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.layout.LazyLayoutPrefetchState? prefetchState, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.layout.LazyLayoutMeasureScope,? super androidx.compose.ui.unit.Constraints,? extends androidx.compose.ui.layout.MeasureResult> measurePolicy);
   }
 
-  @androidx.compose.runtime.Stable public sealed interface LazyLayoutMeasureScope extends androidx.compose.ui.layout.MeasureScope {
+  @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Stable public sealed interface LazyLayoutMeasureScope extends androidx.compose.ui.layout.MeasureScope {
     method public java.util.List<androidx.compose.ui.layout.Placeable> measure(int index, long constraints);
     method @androidx.compose.runtime.Stable public default float toDp(float);
     method @androidx.compose.runtime.Stable public default float toDp(int);
diff --git a/compose/foundation/foundation/api/restricted_current.txt b/compose/foundation/foundation/api/restricted_current.txt
index 37aaab2..82f15b1 100644
--- a/compose/foundation/foundation/api/restricted_current.txt
+++ b/compose/foundation/foundation/api/restricted_current.txt
@@ -884,7 +884,7 @@
     method @Deprecated public void item(optional Object? key, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.lazy.LazyItemScope,kotlin.Unit> content);
     method public default void items(int count, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,? extends java.lang.Object?> contentType, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.LazyItemScope,? super java.lang.Integer,kotlin.Unit> itemContent);
     method @Deprecated public void items(int count, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.LazyItemScope,? super java.lang.Integer,kotlin.Unit> itemContent);
-    method public void stickyHeader(optional Object? key, optional Object? contentType, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.lazy.LazyItemScope,kotlin.Unit> content);
+    method @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi public void stickyHeader(optional Object? key, optional Object? contentType, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.lazy.LazyItemScope,kotlin.Unit> content);
   }
 
   @androidx.compose.runtime.Stable public final class LazyListState implements androidx.compose.foundation.gestures.ScrollableState {
@@ -1126,7 +1126,7 @@
     property public default kotlin.jvm.functions.Function1<java.lang.Integer,java.lang.Object?> type;
   }
 
-  @androidx.compose.runtime.Stable public interface LazyLayoutItemProvider {
+  @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Stable public interface LazyLayoutItemProvider {
     method @androidx.compose.runtime.Composable public void Item(int index, Object key);
     method public default Object? getContentType(int index);
     method public default int getIndex(Object key);
@@ -1139,7 +1139,7 @@
     method @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static void LazyLayout(kotlin.jvm.functions.Function0<? extends androidx.compose.foundation.lazy.layout.LazyLayoutItemProvider> itemProvider, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.layout.LazyLayoutPrefetchState? prefetchState, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.layout.LazyLayoutMeasureScope,? super androidx.compose.ui.unit.Constraints,? extends androidx.compose.ui.layout.MeasureResult> measurePolicy);
   }
 
-  @androidx.compose.runtime.Stable public sealed interface LazyLayoutMeasureScope extends androidx.compose.ui.layout.MeasureScope {
+  @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Stable public sealed interface LazyLayoutMeasureScope extends androidx.compose.ui.layout.MeasureScope {
     method public java.util.List<androidx.compose.ui.layout.Placeable> measure(int index, long constraints);
     method @androidx.compose.runtime.Stable public default float toDp(float);
     method @androidx.compose.runtime.Stable public default float toDp(int);
diff --git a/compose/foundation/foundation/build.gradle b/compose/foundation/foundation/build.gradle
index 0d7637f..2afbfde 100644
--- a/compose/foundation/foundation/build.gradle
+++ b/compose/foundation/foundation/build.gradle
@@ -33,14 +33,14 @@
 
 androidXMultiplatform {
     android()
-    desktop()
+    jvmStubs()
 
     defaultPlatform(PlatformIdentifier.ANDROID)
 
     sourceSets {
         commonMain {
             dependencies {
-                implementation(libs.kotlinStdlibCommon)
+                implementation(libs.kotlinStdlib)
                 api("androidx.collection:collection:1.4.0")
                 api(project(":compose:animation:animation"))
                 api(project(":compose:runtime:runtime"))
@@ -74,23 +74,14 @@
             }
         }
 
-        desktopMain {
+        jvmStubsMain {
             dependsOn(jvmMain)
             dependencies {
-                implementation(libs.kotlinStdlib)
-            }
-        }
-
-        jvmTest {
-            dependsOn(commonTest)
-            dependencies {
-                implementation(project(":compose:ui:ui-test"))
-                implementation(project(":compose:ui:ui-test-junit4"))
             }
         }
 
         androidInstrumentedTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(project(":compose:test-utils"))
                 implementation(project(":internal-testutils-fonts"))
@@ -110,11 +101,14 @@
                 implementation(libs.dexmakerMockito)
                 implementation(libs.mockitoCore)
                 implementation(libs.mockitoKotlin)
+
+                implementation(libs.leakcanary)
+                implementation(libs.leakcanaryInstrumentation)
             }
         }
 
         androidUnitTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(libs.testRules)
                 implementation(libs.testRunner)
@@ -127,17 +121,6 @@
                 implementation(project(":constraintlayout:constraintlayout-compose"))
             }
         }
-
-        desktopTest {
-            dependsOn(jvmTest)
-            dependencies {
-                implementation(libs.truth)
-                implementation(libs.junit)
-                implementation(libs.skikoCurrentOs)
-                implementation(libs.mockitoCore)
-                implementation(libs.mockitoKotlin)
-            }
-        }
     }
 }
 
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/LongScreenshotsDemos.kt b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/LongScreenshotsDemos.kt
index b48f8c0..5fc0218 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/LongScreenshotsDemos.kt
+++ b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/LongScreenshotsDemos.kt
@@ -21,6 +21,7 @@
 import android.widget.LinearLayout
 import android.widget.ScrollView
 import android.widget.TextView
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.background
 import androidx.compose.foundation.border
 import androidx.compose.foundation.layout.Arrangement
@@ -374,6 +375,7 @@
     }
 }
 
+@OptIn(ExperimentalFoundationApi::class)
 @Composable
 private fun LazyListWithStickiesDemo() {
     LazyColumn(Modifier.fillMaxSize()) {
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/ComposeLineHeight.kt b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/ComposeLineHeight.kt
index b9f6b2c..0306cd0 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/ComposeLineHeight.kt
+++ b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/ComposeLineHeight.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.foundation.demos.text
 
+import android.annotation.SuppressLint
 import androidx.compose.foundation.background
 import androidx.compose.foundation.horizontalScroll
 import androidx.compose.foundation.layout.Column
@@ -79,6 +80,7 @@
         val lineHeightStyleEnabled = remember { mutableStateOf(false) }
         var lineHeightAlignment = remember { mutableStateOf(LineHeightStyle.Default.alignment) }
         var lineHeightTrim = remember { mutableStateOf(LineHeightStyle.Default.trim) }
+        var lineHeightMode = remember { mutableStateOf(LineHeightStyle.Default.mode) }
         val includeFontPadding = remember { mutableStateOf(false) }
         val applyMaxLines = remember { mutableStateOf(false) }
         val ellipsize = remember { mutableStateOf(false) }
@@ -93,7 +95,8 @@
             LineHeightStyleConfiguration(
                 lineHeightStyleEnabled,
                 lineHeightTrim,
-                lineHeightAlignment
+                lineHeightAlignment,
+                lineHeightMode,
             )
             Spacer(Modifier.padding(16.dp))
             TextWithLineHeight(
@@ -103,7 +106,8 @@
                 if (lineHeightStyleEnabled.value) {
                     LineHeightStyle(
                         alignment = lineHeightAlignment.value,
-                        trim = lineHeightTrim.value
+                        trim = lineHeightTrim.value,
+                        mode = lineHeightMode.value,
                     )
                 } else null,
                 includeFontPadding.value,
@@ -176,7 +180,8 @@
 private fun LineHeightStyleConfiguration(
     lineHeightStyleEnabled: MutableState<Boolean>,
     lineHeightTrim: MutableState<Trim>,
-    lineHeightAlignment: MutableState<LineHeightStyle.Alignment>
+    lineHeightAlignment: MutableState<LineHeightStyle.Alignment>,
+    lineHeightMode: MutableState<LineHeightStyle.Mode>,
 ) {
     Column(Modifier.horizontalScroll(rememberScrollState())) {
         Row(verticalAlignment = Alignment.CenterVertically) {
@@ -189,6 +194,7 @@
         Column(Modifier.padding(horizontal = 16.dp)) {
             LineHeightTrimOptions(lineHeightTrim, lineHeightStyleEnabled.value)
             LineHeightAlignmentOptions(lineHeightAlignment, lineHeightStyleEnabled.value)
+            LineHeightModeOptions(lineHeightMode, lineHeightStyleEnabled.value)
         }
     }
 }
@@ -259,6 +265,39 @@
 }
 
 @Composable
+private fun LineHeightModeOptions(
+    lineHeightMode: MutableState<LineHeightStyle.Mode>,
+    enabled: Boolean
+) {
+    // Unable to use IntArray because of private value class ctor/accessors.
+    @SuppressLint("PrimitiveInCollection")
+    val options = listOf(LineHeightStyle.Mode.Fixed, LineHeightStyle.Mode.Minimum)
+
+    Row(modifier = Modifier.selectableGroup(), verticalAlignment = Alignment.CenterVertically) {
+        Text(text = "mode:", style = HintStyle)
+        options.forEach { option ->
+            Row(
+                Modifier.height(56.dp)
+                    .selectable(
+                        selected = (option == lineHeightMode.value),
+                        onClick = { lineHeightMode.value = option },
+                        role = Role.RadioButton,
+                        enabled = enabled
+                    ),
+                verticalAlignment = Alignment.CenterVertically
+            ) {
+                RadioButton(
+                    selected = (option == lineHeightMode.value),
+                    onClick = null,
+                    enabled = enabled
+                )
+                Text(text = option.toString().split(".").last(), style = HintStyle)
+            }
+        }
+    }
+}
+
+@Composable
 private fun StringConfiguration(
     useSizeSpan: MutableState<Boolean>,
     singleLine: MutableState<Boolean>,
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/Hyperlinks.kt b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/Hyperlinks.kt
index a3c1db7..f96f0f3 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/Hyperlinks.kt
+++ b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/Hyperlinks.kt
@@ -103,6 +103,31 @@
                 }
             )
         }
+        Sample("Link custom styling") {
+            val string = buildAnnotatedString {
+                withStyle(SpanStyle(Color.Green)) {
+                    append("Text. ")
+                    withLink(
+                        LinkAnnotation.Url(
+                            "tr",
+                            styles =
+                                TextLinkStyles(
+                                    SpanStyle(Color.Blue, textDecoration = TextDecoration.Underline)
+                                )
+                        )
+                    ) {
+                        append("VERY")
+                        withStyle(SpanStyle(Color.Cyan)) {
+                            append("LO")
+                            withStyle(SpanStyle(Color.Magenta)) { append("NG") }
+                        }
+                        append("LINK.")
+                    }
+                    append(" Text.")
+                }
+            }
+            BasicText(string)
+        }
         Sample("State-based styling from Html-tagged string") {
             val htmlString =
                 """
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/VariableFontsDemo.kt b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/VariableFontsDemo.kt
index c8935ec..10cc07d 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/VariableFontsDemo.kt
+++ b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/VariableFontsDemo.kt
@@ -23,6 +23,7 @@
 import android.text.TextPaint
 import androidx.annotation.RequiresApi
 import androidx.compose.foundation.Canvas
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.background
 import androidx.compose.foundation.demos.text.FontVariationSettingsCompot.compatSetFontVariationSettings
 import androidx.compose.foundation.layout.Column
@@ -57,6 +58,7 @@
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.withContext
 
+@OptIn(ExperimentalFoundationApi::class)
 @Preview
 @Composable
 fun VariableFontsDemo() {
diff --git a/compose/foundation/foundation/integration-tests/lazy-tests/src/androidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListBeyondBoundsTest.kt b/compose/foundation/foundation/integration-tests/lazy-tests/src/androidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListBeyondBoundsTest.kt
index 2518294..0090018 100644
--- a/compose/foundation/foundation/integration-tests/lazy-tests/src/androidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListBeyondBoundsTest.kt
+++ b/compose/foundation/foundation/integration-tests/lazy-tests/src/androidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListBeyondBoundsTest.kt
@@ -16,6 +16,10 @@
 
 package androidx.compose.foundation.lazy.list
 
+import android.view.View
+import android.view.ViewGroup.FOCUS_DOWN
+import android.view.ViewGroup.LayoutParams
+import android.widget.FrameLayout
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.lazy.LazyColumn
@@ -27,6 +31,7 @@
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.key
 import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.runtime.setValue
 import androidx.compose.testutils.ParameterizedComposeTestRule
 import androidx.compose.testutils.createParameterizedComposeTestRule
@@ -47,12 +52,16 @@
 import androidx.compose.ui.node.ModifierNodeElement
 import androidx.compose.ui.platform.InspectorInfo
 import androidx.compose.ui.platform.LocalLayoutDirection
+import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.LayoutDirection.Ltr
 import androidx.compose.ui.unit.LayoutDirection.Rtl
+import androidx.compose.ui.viewinterop.AndroidView
 import androidx.test.filters.MediumTest
 import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
 import kotlinx.coroutines.runBlocking
 import org.junit.Rule
 import org.junit.Test
@@ -82,6 +91,7 @@
     private val placedItems = sortedMapOf<Int, Rect>()
     private var beyondBoundsLayout: BeyondBoundsLayout? = null
     private lateinit var lazyListState: LazyListState
+    private lateinit var scope: CoroutineScope
 
     companion object {
         val ParamsToTest = buildList {
@@ -193,6 +203,43 @@
         }
 
     @Test
+    fun scrollingLazyList_doesNotCrash() =
+        with(rule) {
+            // Arrange.
+            var exception: Result<View>? = null
+            setLazyContent(size = 30.toDp(), firstVisibleItem = 0) {
+                items(5) { index -> Box(Modifier.size(10.toDp()).trackPlaced(index)) }
+                item {
+                    AndroidView(::View, modifier = Modifier.size(10.toDp())) {
+                        it.layoutParams =
+                            FrameLayout.LayoutParams(
+                                LayoutParams.MATCH_PARENT,
+                                LayoutParams.MATCH_PARENT
+                            )
+                        it.isFocusableInTouchMode = true
+                        exception = kotlin.runCatching { it.focusSearch(FOCUS_DOWN) }
+                    }
+                }
+                items(5) { index -> Box(Modifier.size(10.toDp()).trackPlaced(index)) }
+            }
+
+            forEachParameter(ParamsToTest) { _ ->
+                rule.mainClock.autoAdvance = false
+
+                // Act.
+                // scroll to trigger measurement
+                scope.launch { lazyListState.animateScrollToItem(4) }
+
+                rule.mainClock.advanceTimeUntil { lazyListState.firstVisibleItemIndex > 2 }
+
+                // Assert.
+                assertThat(exception?.isSuccess).isTrue() // should not crash
+                rule.mainClock.autoAdvance = true
+                resetTestCase()
+            }
+        }
+
+    @Test
     fun oneExtraItemBeyondVisibleBounds() =
         with(rule) {
             // Arrange.
@@ -459,13 +506,14 @@
             key(it) {
                 CompositionLocalProvider(LocalLayoutDirection provides it.layoutDirection) {
                     lazyListState = rememberLazyListState(firstVisibleItem)
+                    scope = rememberCoroutineScope()
                     when (it.beyondBoundsLayoutDirection) {
                         Left,
                         Right,
                         Before,
                         After ->
                             LazyRow(
-                                modifier = Modifier.size(size),
+                                modifier = Modifier.size(size).testTag("list"),
                                 state = lazyListState,
                                 reverseLayout = it.reverseLayout,
                                 content = content
@@ -473,7 +521,7 @@
                         Above,
                         Below ->
                             LazyColumn(
-                                modifier = Modifier.size(size),
+                                modifier = Modifier.size(size).testTag("list"),
                                 state = lazyListState,
                                 reverseLayout = it.reverseLayout,
                                 content = content
diff --git a/compose/foundation/foundation/integration-tests/lazy-tests/src/androidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListHeadersTest.kt b/compose/foundation/foundation/integration-tests/lazy-tests/src/androidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListHeadersTest.kt
index 08d3411..8ee217e 100644
--- a/compose/foundation/foundation/integration-tests/lazy-tests/src/androidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListHeadersTest.kt
+++ b/compose/foundation/foundation/integration-tests/lazy-tests/src/androidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListHeadersTest.kt
@@ -18,6 +18,7 @@
 
 package androidx.compose.foundation.lazy.list
 
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.gestures.FlingBehavior
 import androidx.compose.foundation.gestures.ScrollableDefaults
 import androidx.compose.foundation.gestures.scrollBy
@@ -53,6 +54,7 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 
+@OptIn(ExperimentalFoundationApi::class)
 @LargeTest
 @RunWith(AndroidJUnit4::class)
 class LazyListHeadersTest {
diff --git a/compose/foundation/foundation/integration-tests/lazy-tests/src/androidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListItemPlacementAnimationTest.kt b/compose/foundation/foundation/integration-tests/lazy-tests/src/androidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListItemPlacementAnimationTest.kt
index 637b798..e3e55ef 100644
--- a/compose/foundation/foundation/integration-tests/lazy-tests/src/androidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListItemPlacementAnimationTest.kt
+++ b/compose/foundation/foundation/integration-tests/lazy-tests/src/androidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListItemPlacementAnimationTest.kt
@@ -24,6 +24,7 @@
 import androidx.compose.animation.core.VisibilityThreshold
 import androidx.compose.animation.core.spring
 import androidx.compose.animation.core.tween
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.gestures.scrollBy
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
@@ -451,6 +452,7 @@
         }
     }
 
+    @OptIn(ExperimentalFoundationApi::class)
     @Test
     fun moveItemToTheTopOutsideOfBounds_withStickyHeader() {
         var list by mutableStateOf(listOf(0, 1, 2, 3, 4))
diff --git a/compose/foundation/foundation/integration-tests/lazy-tests/src/androidTest/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridArrangementsTest.kt b/compose/foundation/foundation/integration-tests/lazy-tests/src/androidTest/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridArrangementsTest.kt
index d99f7d4..5fc2cfd 100644
--- a/compose/foundation/foundation/integration-tests/lazy-tests/src/androidTest/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridArrangementsTest.kt
+++ b/compose/foundation/foundation/integration-tests/lazy-tests/src/androidTest/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridArrangementsTest.kt
@@ -46,6 +46,8 @@
  * limitations under the License.
  */
 
+@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
+
 package androidx.compose.foundation.lazy.staggeredgrid
 
 import androidx.compose.foundation.gestures.Orientation
@@ -97,6 +99,7 @@
     @Test
     fun arrangement_addsSpacingInBothDirections() {
         state = LazyStaggeredGridState()
+        state.prefetchingEnabled = false
         rule.setContent {
             LazyStaggeredGrid(
                 lanes = 2,
@@ -145,6 +148,7 @@
     @Test
     fun arrangement_lastItem_noSpacingMainAxis() {
         state = LazyStaggeredGridState()
+        state.prefetchingEnabled = false
         rule.setContent {
             LazyStaggeredGrid(
                 lanes = 2,
@@ -178,6 +182,7 @@
     @Test
     fun negativeSpacing_itemsVisible() {
         state = LazyStaggeredGridState()
+        state.prefetchingEnabled = false
         rule.setContent {
             LazyStaggeredGrid(
                 lanes = 2,
@@ -224,6 +229,7 @@
     @Test
     fun negativeSpacing_withContentPadding_itemsVisible() {
         state = LazyStaggeredGridState()
+        state.prefetchingEnabled = false
         rule.setContent {
             LazyStaggeredGrid(
                 lanes = 2,
@@ -271,6 +277,7 @@
     @Test
     fun negativeSpacingLargerThanItem_itemsVisible() {
         val state = LazyStaggeredGridState(initialFirstVisibleItemIndex = 2)
+        state.prefetchingEnabled = false
         val largerThanItemSize = itemSizeDp * 1.5f
         rule.setContent {
             LazyStaggeredGrid(
@@ -294,6 +301,7 @@
     @Test
     fun nonStartCrossAxisArrangement() {
         val state = LazyStaggeredGridState()
+        state.prefetchingEnabled = false
         rule.setContent {
             LazyStaggeredGrid(
                 cells = StaggeredGridCells.FixedSize(itemSizeDp * 2),
@@ -318,6 +326,7 @@
     @Test
     fun spacedByWithAlignment() {
         val state = LazyStaggeredGridState()
+        state.prefetchingEnabled = false
         rule.setContent {
             LazyStaggeredGrid(
                 cells = StaggeredGridCells.FixedSize(itemSizeDp * 2),
diff --git a/compose/foundation/foundation/samples/src/main/java/androidx/compose/foundation/samples/LazyDslSamples.kt b/compose/foundation/foundation/samples/src/main/java/androidx/compose/foundation/samples/LazyDslSamples.kt
index b52f91b..3db1162 100644
--- a/compose/foundation/foundation/samples/src/main/java/androidx/compose/foundation/samples/LazyDslSamples.kt
+++ b/compose/foundation/foundation/samples/src/main/java/androidx/compose/foundation/samples/LazyDslSamples.kt
@@ -17,6 +17,7 @@
 package androidx.compose.foundation.samples
 
 import androidx.annotation.Sampled
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.PaddingValues
@@ -72,6 +73,7 @@
     }
 }
 
+@OptIn(ExperimentalFoundationApi::class)
 @Sampled
 @Composable
 fun StickyHeaderSample() {
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/ClickableTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/ClickableTest.kt
index a82bbc0..18065f8 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/ClickableTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/ClickableTest.kt
@@ -1629,6 +1629,343 @@
         }
     }
 
+    /* Uses pointer input block for the non-dynamic pointer input and TWO pointer input
+     * blocks (awaitPointerEventScope + awaitPointerEvent) for the dynamic pointer
+     * inputs (both on same Box).
+     * Both dynamic Pointers are disabled to start and then enabled.
+     * Event sequences:
+     * 1. Touch "click" (down/move/up)
+     * 2. Assert
+     * 3. Touch down
+     * 4. Assert
+     * 5. Touch move
+     * 6. Assert
+     * 7. Touch up
+     * 8. Assert
+     */
+    @Test
+    fun twoDynamicInputModifiers_addsAbovePointerInputWithUnitKeyTouchEventsWithMove() {
+        var originalPointerInputLambdaExecutionCount by mutableStateOf(0)
+        var originalPointerInputPressCounter by mutableStateOf(0)
+        var originalPointerInputMoveCounter by mutableStateOf(0)
+        var originalPointerInputReleaseCounter by mutableStateOf(0)
+
+        var activeDynamicPointerInput by mutableStateOf(false)
+        var dynamicPointerInputPressCounter by mutableStateOf(0)
+        var dynamicPointerInputMoveCounter by mutableStateOf(0)
+        var dynamicPointerInputReleaseCounter by mutableStateOf(0)
+
+        var activeDynamicPointerInput2 by mutableStateOf(false)
+        var dynamicPointerInput2PressCounter by mutableStateOf(0)
+        var dynamicPointerInput2ReleaseCounter by mutableStateOf(0)
+
+        rule.setContent {
+            Box(
+                Modifier.size(200.dp)
+                    .testTag("myClickable")
+                    .dynamicPointerInputModifier(
+                        enabled = activeDynamicPointerInput,
+                        onPress = { dynamicPointerInputPressCounter++ },
+                        onMove = { dynamicPointerInputMoveCounter++ },
+                        onRelease = {
+                            dynamicPointerInputReleaseCounter++
+                            activeDynamicPointerInput2 = true
+                        }
+                    )
+                    .dynamicPointerInputModifier(
+                        enabled = activeDynamicPointerInput2,
+                        onPress = { dynamicPointerInput2PressCounter++ },
+                        onRelease = { dynamicPointerInput2ReleaseCounter++ }
+                    )
+                    .pointerInput(Unit) {
+                        originalPointerInputLambdaExecutionCount++
+                        awaitPointerEventScope {
+                            while (true) {
+                                val event = awaitPointerEvent()
+                                when (event.type) {
+                                    PointerEventType.Press -> {
+                                        originalPointerInputPressCounter++
+                                    }
+                                    PointerEventType.Move -> {
+                                        originalPointerInputMoveCounter++
+                                    }
+                                    PointerEventType.Release -> {
+                                        originalPointerInputReleaseCounter++
+                                        activeDynamicPointerInput = true
+                                    }
+                                }
+                            }
+                        }
+                    }
+            )
+        }
+
+        // Even though we are enabling the dynamic pointer input, it will NOT receive events until
+        // the next event stream (after the click is over) which is why you see zeros below.
+        // Only two events are triggered for click (down/up)
+        rule.onNodeWithTag("myClickable").performClick()
+
+        rule.runOnIdle {
+            assertEquals(1, originalPointerInputLambdaExecutionCount)
+            // With these events, we enable the dynamic pointer input
+            assertEquals(1, originalPointerInputPressCounter)
+            assertEquals(0, originalPointerInputMoveCounter)
+            assertEquals(1, originalPointerInputReleaseCounter)
+
+            assertEquals(0, dynamicPointerInputPressCounter)
+            assertEquals(0, dynamicPointerInputMoveCounter)
+            assertEquals(0, dynamicPointerInputReleaseCounter)
+
+            assertEquals(0, dynamicPointerInput2PressCounter)
+            assertEquals(0, dynamicPointerInput2ReleaseCounter)
+        }
+
+        rule.onNodeWithTag("myClickable").performTouchInput { down(Offset(0f, 0f)) }
+
+        rule.runOnIdle {
+            // Each time a new dynamic pointer input is added DIRECTLY above an existing one, the
+            // previously existing pointer input lambda will be restarted.
+            assertEquals(2, originalPointerInputLambdaExecutionCount)
+            assertEquals(2, originalPointerInputPressCounter)
+            assertEquals(0, originalPointerInputMoveCounter)
+            assertEquals(1, originalPointerInputReleaseCounter)
+
+            assertEquals(1, dynamicPointerInputPressCounter)
+            assertEquals(0, dynamicPointerInputMoveCounter)
+            assertEquals(0, dynamicPointerInputReleaseCounter)
+
+            assertEquals(0, dynamicPointerInput2PressCounter)
+            assertEquals(0, dynamicPointerInput2ReleaseCounter)
+        }
+
+        rule.onNodeWithTag("myClickable").performTouchInput { moveTo(Offset(1f, 1f)) }
+
+        rule.runOnIdle {
+            assertEquals(2, originalPointerInputLambdaExecutionCount)
+            assertEquals(2, originalPointerInputPressCounter)
+            assertEquals(1, originalPointerInputMoveCounter)
+            assertEquals(1, originalPointerInputReleaseCounter)
+
+            assertEquals(1, dynamicPointerInputPressCounter)
+            assertEquals(1, dynamicPointerInputMoveCounter)
+            assertEquals(0, dynamicPointerInputReleaseCounter)
+
+            assertEquals(0, dynamicPointerInput2PressCounter)
+            assertEquals(0, dynamicPointerInput2ReleaseCounter)
+        }
+
+        rule.onNodeWithTag("myClickable").performTouchInput { up() }
+
+        rule.runOnIdle {
+            assertEquals(2, originalPointerInputLambdaExecutionCount)
+            assertEquals(2, originalPointerInputPressCounter)
+            assertEquals(1, originalPointerInputMoveCounter)
+            assertEquals(2, originalPointerInputReleaseCounter)
+
+            assertEquals(1, dynamicPointerInputPressCounter)
+            assertEquals(1, dynamicPointerInputMoveCounter)
+            // With this release counter, we enable the dynamic clickable{}
+            assertEquals(1, dynamicPointerInputReleaseCounter)
+
+            assertEquals(0, dynamicPointerInput2PressCounter)
+            assertEquals(0, dynamicPointerInput2ReleaseCounter)
+        }
+
+        // Only two events are triggered for click (down/up)
+        rule.onNodeWithTag("myClickable").performClick()
+
+        rule.runOnIdle {
+            // Each time a new dynamic pointer input is added DIRECTLY above an existing one, the
+            // previously existing pointer input lambda will be restarted.
+            assertEquals(3, originalPointerInputLambdaExecutionCount)
+            assertEquals(3, originalPointerInputPressCounter)
+            assertEquals(1, originalPointerInputMoveCounter)
+            assertEquals(3, originalPointerInputReleaseCounter)
+
+            assertEquals(2, dynamicPointerInputPressCounter)
+            assertEquals(1, dynamicPointerInputMoveCounter)
+            assertEquals(2, dynamicPointerInputReleaseCounter)
+
+            assertEquals(1, dynamicPointerInput2PressCounter)
+            assertEquals(1, dynamicPointerInput2ReleaseCounter)
+        }
+    }
+
+    /* Uses two pointer input blocks and a dynamic background color property to recompose UI.
+     * It should NOT restart the pointer input lambdas.
+     * Event sequences:
+     * 1. "click" (down/up)
+     * 2. Assert
+     * 3. Recompose
+     * 4. Assert
+     * 5. Touch down
+     * 6. Assert
+     * 7. Touch move
+     * 8. Assert
+     * 9. Touch up
+     * 10. Assert
+     * 11. Recompose
+     * 12. Assert
+     */
+    @Test
+    fun twoPointerInputModifiers_recomposeShouldNotRestartPointerInputLambda() {
+        var backgroundModifierColor by mutableStateOf(Color.Red)
+
+        var firstPointerInputLambdaExecutionCount by mutableStateOf(0)
+        var firstPointerInputPressCounter by mutableStateOf(0)
+        var firstPointerInputMoveCounter by mutableStateOf(0)
+        var firstPointerInputReleaseCounter by mutableStateOf(0)
+
+        var secondPointerInputLambdaExecutionCount by mutableStateOf(0)
+        var secondPointerInputPressCounter by mutableStateOf(0)
+        var secondPointerInputMoveCounter by mutableStateOf(0)
+        var secondPointerInputReleaseCounter by mutableStateOf(0)
+
+        rule.setContent {
+            Box(
+                Modifier.size(200.dp)
+                    .testTag("myClickable")
+                    .pointerInput(Unit) {
+                        firstPointerInputLambdaExecutionCount++
+                        awaitPointerEventScope {
+                            while (true) {
+                                val event = awaitPointerEvent()
+                                when (event.type) {
+                                    PointerEventType.Press -> {
+                                        firstPointerInputPressCounter++
+                                    }
+                                    PointerEventType.Move -> {
+                                        firstPointerInputMoveCounter++
+                                    }
+                                    PointerEventType.Release -> {
+                                        firstPointerInputReleaseCounter++
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    .pointerInput(Unit) {
+                        secondPointerInputLambdaExecutionCount++
+                        awaitPointerEventScope {
+                            while (true) {
+                                val event = awaitPointerEvent()
+                                when (event.type) {
+                                    PointerEventType.Press -> {
+                                        secondPointerInputPressCounter++
+                                    }
+                                    PointerEventType.Move -> {
+                                        secondPointerInputMoveCounter++
+                                    }
+                                    PointerEventType.Release -> {
+                                        secondPointerInputReleaseCounter++
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    .background(backgroundModifierColor)
+            )
+        }
+
+        rule.onNodeWithTag("myClickable").performClick()
+
+        rule.runOnIdle {
+            assertEquals(Color.Red, backgroundModifierColor)
+
+            assertEquals(1, firstPointerInputLambdaExecutionCount)
+            assertEquals(1, firstPointerInputPressCounter)
+            assertEquals(0, firstPointerInputMoveCounter)
+            assertEquals(1, firstPointerInputReleaseCounter)
+
+            assertEquals(1, secondPointerInputLambdaExecutionCount)
+            assertEquals(1, secondPointerInputPressCounter)
+            assertEquals(0, secondPointerInputMoveCounter)
+            assertEquals(1, secondPointerInputReleaseCounter)
+        }
+
+        // Recompose
+        backgroundModifierColor = Color.Green
+
+        rule.runOnIdle {
+            assertEquals(Color.Green, backgroundModifierColor)
+
+            assertEquals(1, firstPointerInputLambdaExecutionCount)
+            assertEquals(1, firstPointerInputPressCounter)
+            assertEquals(0, firstPointerInputMoveCounter)
+            assertEquals(1, firstPointerInputReleaseCounter)
+
+            assertEquals(1, secondPointerInputLambdaExecutionCount)
+            assertEquals(1, secondPointerInputPressCounter)
+            assertEquals(0, secondPointerInputMoveCounter)
+            assertEquals(1, secondPointerInputReleaseCounter)
+        }
+
+        rule.onNodeWithTag("myClickable").performTouchInput { down(Offset(0f, 0f)) }
+
+        rule.runOnIdle {
+            assertEquals(Color.Green, backgroundModifierColor)
+
+            assertEquals(1, firstPointerInputLambdaExecutionCount)
+            assertEquals(2, firstPointerInputPressCounter)
+            assertEquals(0, firstPointerInputMoveCounter)
+            assertEquals(1, firstPointerInputReleaseCounter)
+
+            assertEquals(1, secondPointerInputLambdaExecutionCount)
+            assertEquals(2, secondPointerInputPressCounter)
+            assertEquals(0, secondPointerInputMoveCounter)
+            assertEquals(1, secondPointerInputReleaseCounter)
+        }
+
+        rule.onNodeWithTag("myClickable").performTouchInput { moveTo(Offset(1f, 1f)) }
+
+        rule.runOnIdle {
+            assertEquals(Color.Green, backgroundModifierColor)
+
+            assertEquals(1, firstPointerInputLambdaExecutionCount)
+            assertEquals(2, firstPointerInputPressCounter)
+            assertEquals(1, firstPointerInputMoveCounter)
+            assertEquals(1, firstPointerInputReleaseCounter)
+
+            assertEquals(1, secondPointerInputLambdaExecutionCount)
+            assertEquals(2, secondPointerInputPressCounter)
+            assertEquals(1, secondPointerInputMoveCounter)
+            assertEquals(1, secondPointerInputReleaseCounter)
+        }
+
+        rule.onNodeWithTag("myClickable").performTouchInput { up() }
+
+        rule.runOnIdle {
+            assertEquals(Color.Green, backgroundModifierColor)
+
+            assertEquals(1, firstPointerInputLambdaExecutionCount)
+            assertEquals(2, firstPointerInputPressCounter)
+            assertEquals(1, firstPointerInputMoveCounter)
+            assertEquals(2, firstPointerInputReleaseCounter)
+
+            assertEquals(1, secondPointerInputLambdaExecutionCount)
+            assertEquals(2, secondPointerInputPressCounter)
+            assertEquals(1, secondPointerInputMoveCounter)
+            assertEquals(2, secondPointerInputReleaseCounter)
+        }
+
+        // Recompose
+        backgroundModifierColor = Color.Red
+
+        rule.runOnIdle {
+            assertEquals(Color.Red, backgroundModifierColor)
+
+            assertEquals(1, firstPointerInputLambdaExecutionCount)
+            assertEquals(2, firstPointerInputPressCounter)
+            assertEquals(1, firstPointerInputMoveCounter)
+            assertEquals(2, firstPointerInputReleaseCounter)
+
+            assertEquals(1, secondPointerInputLambdaExecutionCount)
+            assertEquals(2, secondPointerInputPressCounter)
+            assertEquals(1, secondPointerInputMoveCounter)
+            assertEquals(2, secondPointerInputReleaseCounter)
+        }
+    }
+
     /* Uses pointer input block for the non-dynamic pointer input and BOTH a clickable{} and
      * pointer input block (awaitPointerEventScope + awaitPointerEvent) for the dynamic pointer
      * inputs (both on same Box).
@@ -1654,7 +1991,9 @@
         var dynamicPointerInputReleaseCounter by mutableStateOf(0)
 
         var originalPointerInputLambdaExecutionCount by mutableStateOf(0)
-        var originalPointerInputEventCounter by mutableStateOf(0)
+        var originalPointerInputPressCounter by mutableStateOf(0)
+        var originalPointerInputMoveCounter by mutableStateOf(0)
+        var originalPointerInputReleaseCounter by mutableStateOf(0)
 
         rule.setContent {
             Box(
@@ -1670,19 +2009,23 @@
                         }
                     )
                     .dynamicClickableModifier(activeDynamicClickable) { dynamicClickableCounter++ }
-                    // Note the .background() above the static pointer input block
-                    // TODO (jjw): Remove once bug fixed for when a dynamic pointer input follows
-                    // directly after another pointer input (both using Unit key).
-                    // Workaround: add a modifier between them OR use unique keys (that is, not
-                    // Unit)
-                    .background(Color.Green)
                     .pointerInput(Unit) {
                         originalPointerInputLambdaExecutionCount++
                         awaitPointerEventScope {
                             while (true) {
-                                awaitPointerEvent()
-                                originalPointerInputEventCounter++
-                                activeDynamicPointerInput = true
+                                val event = awaitPointerEvent()
+                                when (event.type) {
+                                    PointerEventType.Press -> {
+                                        originalPointerInputPressCounter++
+                                    }
+                                    PointerEventType.Move -> {
+                                        originalPointerInputMoveCounter++
+                                    }
+                                    PointerEventType.Release -> {
+                                        originalPointerInputReleaseCounter++
+                                        activeDynamicPointerInput = true
+                                    }
+                                }
                             }
                         }
                     }
@@ -1697,7 +2040,9 @@
         rule.runOnIdle {
             assertEquals(1, originalPointerInputLambdaExecutionCount)
             // With these events, we enable the dynamic pointer input
-            assertEquals(2, originalPointerInputEventCounter)
+            assertEquals(1, originalPointerInputPressCounter)
+            assertEquals(0, originalPointerInputMoveCounter)
+            assertEquals(1, originalPointerInputReleaseCounter)
 
             assertEquals(0, dynamicPointerInputPressCounter)
             assertEquals(0, dynamicPointerInputMoveCounter)
@@ -1709,8 +2054,12 @@
         rule.onNodeWithTag("myClickable").performTouchInput { down(Offset(0f, 0f)) }
 
         rule.runOnIdle {
-            assertEquals(1, originalPointerInputLambdaExecutionCount)
-            assertEquals(3, originalPointerInputEventCounter)
+            // Each time a new dynamic pointer input is added DIRECTLY above an existing one, the
+            // previously existing pointer input lambda will be restarted.
+            assertEquals(2, originalPointerInputLambdaExecutionCount)
+            assertEquals(2, originalPointerInputPressCounter)
+            assertEquals(0, originalPointerInputMoveCounter)
+            assertEquals(1, originalPointerInputReleaseCounter)
 
             assertEquals(1, dynamicPointerInputPressCounter)
             assertEquals(0, dynamicPointerInputMoveCounter)
@@ -1722,8 +2071,10 @@
         rule.onNodeWithTag("myClickable").performTouchInput { moveTo(Offset(1f, 1f)) }
 
         rule.runOnIdle {
-            assertEquals(1, originalPointerInputLambdaExecutionCount)
-            assertEquals(4, originalPointerInputEventCounter)
+            assertEquals(2, originalPointerInputLambdaExecutionCount)
+            assertEquals(2, originalPointerInputPressCounter)
+            assertEquals(1, originalPointerInputMoveCounter)
+            assertEquals(1, originalPointerInputReleaseCounter)
 
             assertEquals(1, dynamicPointerInputPressCounter)
             assertEquals(1, dynamicPointerInputMoveCounter)
@@ -1735,8 +2086,10 @@
         rule.onNodeWithTag("myClickable").performTouchInput { up() }
 
         rule.runOnIdle {
-            assertEquals(1, originalPointerInputLambdaExecutionCount)
-            assertEquals(5, originalPointerInputEventCounter)
+            assertEquals(2, originalPointerInputLambdaExecutionCount)
+            assertEquals(2, originalPointerInputPressCounter)
+            assertEquals(1, originalPointerInputMoveCounter)
+            assertEquals(2, originalPointerInputReleaseCounter)
 
             assertEquals(1, dynamicPointerInputPressCounter)
             assertEquals(1, dynamicPointerInputMoveCounter)
@@ -1750,8 +2103,12 @@
         rule.onNodeWithTag("myClickable").performClick()
 
         rule.runOnIdle {
-            assertEquals(1, originalPointerInputLambdaExecutionCount)
-            assertEquals(7, originalPointerInputEventCounter)
+            // In this case, the lambda is not re-executed because the modifier added before it was
+            // not directly a pointer input.
+            assertEquals(2, originalPointerInputLambdaExecutionCount)
+            assertEquals(3, originalPointerInputPressCounter)
+            assertEquals(1, originalPointerInputMoveCounter)
+            assertEquals(3, originalPointerInputReleaseCounter)
 
             assertEquals(2, dynamicPointerInputPressCounter)
             assertEquals(1, dynamicPointerInputMoveCounter)
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/GoldenCommon.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/GoldenCommon.kt
index 9d96777..3549c4b 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/GoldenCommon.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/GoldenCommon.kt
@@ -16,4 +16,4 @@
 
 package androidx.compose.foundation
 
-internal const val GOLDEN_UI = "compose/foundation/foundation"
+internal const val GOLDEN_FOUNDATION = "compose/foundation/foundation"
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/OverscrollScreenshotTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/OverscrollScreenshotTest.kt
deleted file mode 100644
index df2745e..0000000
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/OverscrollScreenshotTest.kt
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation
-
-import android.os.Build
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.PaddingValues
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.wrapContentSize
-import androidx.compose.foundation.lazy.LazyColumn
-import androidx.compose.foundation.lazy.LazyRow
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.testutils.assertAgainstGolden
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.platform.testTag
-import androidx.compose.ui.test.captureToImage
-import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.compose.ui.test.onNodeWithTag
-import androidx.compose.ui.test.performTouchInput
-import androidx.compose.ui.unit.dp
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.LargeTest
-import androidx.test.filters.SdkSuppress
-import androidx.test.screenshot.AndroidXScreenshotTestRule
-import androidx.testutils.AnimationDurationScaleRule
-import org.junit.Ignore
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@LargeTest
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
-class OverscrollScreenshotTest {
-    @get:Rule val rule = createComposeRule()
-
-    @get:Rule val screenshotRule = AndroidXScreenshotTestRule(GOLDEN_UI)
-
-    @get:Rule
-    val animationScaleRule: AnimationDurationScaleRule =
-        AnimationDurationScaleRule.createForAllTests(1f)
-
-    val overscrollTag = "overscrollTag"
-
-    @Test
-    @Ignore("b/197325932 no animations in screenshot tests")
-    fun overscroll_dragTop() {
-        animationScaleRule.setAnimationDurationScale(1f)
-        rule.setContent { VerticalScrollable() }
-
-        rule.onNodeWithTag(overscrollTag).performTouchInput {
-            down(Offset(centerX + width / 2 - 10, centerY))
-            moveBy(Offset(0f, 500f))
-            repeat(5) { moveBy(Offset(0f, 200f)) }
-        }
-
-        rule
-            .onNodeWithTag(overscrollTag)
-            .captureToImage()
-            .assertAgainstGolden(screenshotRule, "overscroll_top_origin")
-    }
-
-    @Test
-    @Ignore("b/197325932 no animations in screenshot tests")
-    fun overscroll_dragBottom() {
-        animationScaleRule.setAnimationDurationScale(1f)
-        rule.setContent { VerticalScrollable() }
-
-        rule.onNodeWithTag(overscrollTag).performTouchInput {
-            down(Offset(centerX + width / 2 - 10, centerY))
-            moveBy(Offset(0f, -500f))
-            repeat(5) { moveBy(Offset(0f, -200f)) }
-        }
-
-        rule
-            .onNodeWithTag(overscrollTag)
-            .captureToImage()
-            .assertAgainstGolden(screenshotRule, "overscroll_bottom_origin")
-    }
-
-    @Test
-    @Ignore("b/197325932 no animations in screenshot tests")
-    fun overscroll_dragLeft() {
-        animationScaleRule.setAnimationDurationScale(1f)
-        rule.setContent { HorizontalScrollable() }
-
-        rule.onNodeWithTag(overscrollTag).performTouchInput {
-            down(Offset(centerX, centerY + height / 2 - 10))
-            moveBy(Offset(500f, 0f))
-            repeat(5) { moveBy(Offset(200f, 0f)) }
-        }
-
-        rule
-            .onNodeWithTag(overscrollTag)
-            .captureToImage()
-            .assertAgainstGolden(screenshotRule, "overscroll_left_origin")
-    }
-
-    @Test
-    @Ignore("b/197325932 no animations in screenshot tests")
-    fun overscroll_dragRight() {
-        animationScaleRule.setAnimationDurationScale(1f)
-        rule.setContent { HorizontalScrollable() }
-
-        rule.onNodeWithTag(overscrollTag).performTouchInput {
-            down(Offset(centerX, centerY + height / 2 - 10))
-            moveBy(Offset(-500f, 0f))
-            repeat(5) { moveBy(Offset(-200f, 0f)) }
-        }
-
-        rule
-            .onNodeWithTag(overscrollTag)
-            .captureToImage()
-            .assertAgainstGolden(screenshotRule, "overscroll_right_origin")
-    }
-
-    @Composable
-    fun VerticalScrollable() {
-        CompositionLocalProvider(
-            LocalOverscrollConfiguration provides
-                OverscrollConfiguration(glowColor = Color.Red, drawPadding = PaddingValues(10.dp))
-        ) {
-            Box(Modifier.wrapContentSize(Alignment.TopStart)) {
-                LazyColumn(
-                    Modifier.border(5.dp, Color.Black)
-                        .size(width = 400.dp, height = 200.dp)
-                        .testTag(overscrollTag)
-                ) {
-                    items(7) { Box(Modifier.size(400.dp, 50.dp)) }
-                }
-            }
-        }
-    }
-
-    @Composable
-    fun HorizontalScrollable() {
-        CompositionLocalProvider(
-            LocalOverscrollConfiguration provides
-                OverscrollConfiguration(glowColor = Color.Red, drawPadding = PaddingValues(10.dp))
-        ) {
-            Box(Modifier.wrapContentSize(Alignment.TopStart)) {
-                LazyRow(
-                    Modifier.border(5.dp, Color.Black)
-                        .size(width = 200.dp, height = 400.dp)
-                        .testTag(overscrollTag)
-                ) {
-                    items(7) { Box(Modifier.size(50.dp, 400.dp)) }
-                }
-            }
-        }
-    }
-}
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/OverscrollTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/OverscrollTest.kt
index 8866e449..0ad3646 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/OverscrollTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/OverscrollTest.kt
@@ -44,6 +44,7 @@
 import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
 import androidx.compose.ui.input.nestedscroll.NestedScrollSource
 import androidx.compose.ui.input.nestedscroll.nestedScroll
+import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.platform.LocalView
 import androidx.compose.ui.platform.LocalViewConfiguration
 import androidx.compose.ui.platform.ViewConfiguration
@@ -78,8 +79,7 @@
     @get:Rule val rule = createComposeRule()
 
     @get:Rule
-    val animationScaleRule: AnimationDurationScaleRule =
-        AnimationDurationScaleRule.createForAllTests(1f)
+    val animationScaleRule: AnimationDurationScaleRule = AnimationDurationScaleRule.create()
 
     @Before
     fun before() {
@@ -123,7 +123,7 @@
         rule.onNodeWithTag(boxTag).assertExists()
 
         rule.onNodeWithTag(boxTag).performTouchInput {
-            swipeWithVelocity(center, Offset(centerX + 10800, centerY), endVelocity = 30000f)
+            swipeWithVelocity(center, centerRight, endVelocity = 3000f)
         }
 
         rule.runOnIdle {
@@ -156,7 +156,7 @@
         rule.runOnIdle {
             val slop = viewConfig.touchSlop
             // since we consume 1/10 of the delta in the pre scroll during overscroll, expect 9/10
-            assertThat(abs(acummulatedScroll - 1000f * 9 / 10)).isWithin(0.1f)
+            assertThat(abs(acummulatedScroll)).isWithin(0.1f).of((1000f - slop) * 9 / 10)
 
             assertThat(controller.lastPreScrollDelta).isEqualTo(Offset(1000f - slop, 0f))
             assertThat(controller.lastNestedScrollSource).isEqualTo(NestedScrollSource.UserInput)
@@ -199,7 +199,7 @@
         rule.runOnIdle {
             val slop = viewConfig.touchSlop
             // since we consume 1/10 of the delta in the pre scroll during overscroll, expect 9/10
-            assertThat(abs(acummulatedScroll - 1000f * 9 / 10)).isWithin(0.1f)
+            assertThat(abs(acummulatedScroll)).isWithin(0.1f).of((1000f - slop) * 9 / 10)
 
             assertThat(controller.lastPreScrollDelta).isEqualTo(Offset(1000f - slop, 0f))
             assertThat(controller.lastNestedScrollSource).isEqualTo(NestedScrollSource.UserInput)
@@ -248,12 +248,12 @@
         rule.onNodeWithTag(boxTag).assertExists()
 
         rule.onNodeWithTag(boxTag).performTouchInput {
-            swipeWithVelocity(center, Offset(centerX + 10800, centerY), endVelocity = 30000f)
+            swipeWithVelocity(center, centerRight, endVelocity = 3000f)
         }
 
         rule.runOnIdle {
-            assertThat(abs(controller.preFlingVelocity.x - 30000f)).isWithin(0.1f)
-            assertThat(abs(lastFlingReceived - 30000f * 9 / 10)).isWithin(0.1f)
+            assertThat(abs(controller.preFlingVelocity.x)).isWithin(0.1f).of(3000f)
+            assertThat(abs(lastFlingReceived)).isWithin(0.1f).of(3000f * 9 / 10)
         }
     }
 
@@ -311,6 +311,7 @@
             overscrollEffect =
                 AndroidEdgeEffectOverscrollEffect(
                     LocalView.current.context,
+                    LocalDensity.current,
                     OverscrollConfiguration(Color.Gray)
                 )
         }
@@ -873,7 +874,7 @@
         rule.onNodeWithTag(boxTag).assertExists()
 
         rule.onNodeWithTag(boxTag).performTouchInput {
-            swipeWithVelocity(center, Offset(centerX + 10800, centerY), endVelocity = 30000f)
+            swipeWithVelocity(center, centerRight, endVelocity = 3000f)
         }
 
         rule.runOnIdle {
@@ -909,7 +910,7 @@
         rule.onNodeWithTag(boxTag).assertExists()
 
         rule.onNodeWithTag(boxTag).performTouchInput {
-            swipeWithVelocity(center, Offset(centerX, centerY + 10800), endVelocity = 30000f)
+            swipeWithVelocity(center, bottomCenter, endVelocity = 3000f)
         }
 
         rule.runOnIdle {
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/StretchOverscrollIntegrationTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/StretchOverscrollIntegrationTest.kt
new file mode 100644
index 0000000..f11a8b9
--- /dev/null
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/StretchOverscrollIntegrationTest.kt
@@ -0,0 +1,1049 @@
+/*
+ * 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.foundation
+
+import android.os.Build
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.foundation.gestures.ScrollScope
+import androidx.compose.foundation.gestures.ScrollableDefaults
+import androidx.compose.foundation.gestures.ScrollableState
+import androidx.compose.foundation.gestures.scrollable
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.size
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
+import androidx.compose.testutils.WithTouchSlop
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
+import androidx.compose.ui.input.nestedscroll.NestedScrollSource
+import androidx.compose.ui.input.nestedscroll.nestedScroll
+import androidx.compose.ui.platform.LocalLayoutDirection
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.performTouchInput
+import androidx.compose.ui.test.swipeWithVelocity
+import androidx.compose.ui.unit.Velocity
+import androidx.compose.ui.unit.dp
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import androidx.test.filters.SdkSuppress
+import androidx.testutils.AnimationDurationScaleRule
+import com.google.common.truth.Truth.assertThat
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/** Integration test for stretch overscroll with [scrollable] and [nestedScroll]. */
+@MediumTest
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
+@RunWith(AndroidJUnit4::class)
+class StretchOverscrollIntegrationTest {
+    @get:Rule val rule = createComposeRule()
+
+    @get:Rule
+    val animationScaleRule: AnimationDurationScaleRule =
+        AnimationDurationScaleRule.createForAllTests(1f)
+
+    /**
+     * Test case to make sure that stretch overscroll correctly consumes delta before the scroll
+     * cycle when relaxing, and after the scroll cycle when stretching, when pulled. Pull left =
+     * showing overscroll from the right edge because of reverse scrolling
+     */
+    @Test
+    fun stretchOverscroll_consumesDelta_pullLeft() {
+        val state = setStretchOverscrollContent(Orientation.Horizontal)
+        // Move to the end, since pulling left requires us to be at the right edge
+        state.dispatchRawDelta(1000f)
+        rule.runOnIdle { assertThat(state.scrollPosition).isEqualTo(1000f) }
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            down(center)
+            // Stretch by 200
+            moveBy(Offset(-200f, 0f))
+            state.overscroll.invalidationEnabled = false
+        }
+
+        rule.runOnIdle {
+            // When stretching, overscroll will consume after the scroll cycle
+            assertThat(state.onPreScrollAvailable.x).isEqualTo(-200f)
+            assertThat(state.scrollPosition).isEqualTo(1000f)
+            assertThat(state.onPostScrollAvailable.x).isEqualTo(-200f)
+        }
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            // Stretch by another 200
+            moveBy(Offset(-200f, 0f))
+        }
+
+        rule.runOnIdle {
+            assertThat(state.onPreScrollAvailable.x).isEqualTo(-400f)
+            assertThat(state.scrollPosition).isEqualTo(1000f)
+            assertThat(state.onPostScrollAvailable.x).isEqualTo(-400f)
+        }
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            // Pull 200 in the opposite direction - because we had 200 pixels of stretch before,
+            // this should only relax the existing overscroll, and not dispatch anything to the
+            // state
+            moveBy(Offset(200f, 0f))
+        }
+
+        rule.runOnIdle {
+            // Overscroll consumes when relaxing before the scroll cycle, so these will not see the
+            // new delta - all 200 should have been consumed relaxing the existing stretch
+            assertThat(state.onPreScrollAvailable.x).isEqualTo(-400f)
+            assertThat(state.scrollPosition).isEqualTo(1000f)
+            assertThat(state.onPostScrollAvailable.x).isEqualTo(-400f)
+        }
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            // Relax all the way, and continue into a scroll in the other direction with 200 excess
+            moveBy(Offset(400f, 0f))
+        }
+
+        rule.runOnIdle {
+            // Since overscroll fully relaxed, there should be 200 excess
+            assertThat(state.onPreScrollAvailable.x).isEqualTo(-200f)
+            // The scroll will consume the new delta
+            assertThat(state.scrollPosition).isEqualTo(800f)
+            // So post scroll will be unchanged at this point
+            assertThat(state.onPostScrollAvailable.x).isEqualTo(-400f)
+        }
+    }
+
+    /**
+     * Test case to make sure that stretch overscroll correctly consumes delta after the scroll
+     * cycle when stretching with a fling. Fling left = showing overscroll from the right edge
+     * because of reverse scrolling
+     */
+    @Test
+    fun stretchOverscroll_consumesDelta_flingLeft_stretch() {
+        val state = setStretchOverscrollContent(Orientation.Horizontal)
+        // Move to the end, since flinging left requires us to be at the right edge
+        state.dispatchRawDelta(1000f)
+        rule.runOnIdle { assertThat(state.scrollPosition).isEqualTo(1000f) }
+
+        val velocity = 1000f
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            swipeWithVelocity(
+                start = center,
+                end = center - Offset(100f, 0f),
+                endVelocity = velocity
+            )
+            state.overscroll.invalidationEnabled = false
+        }
+
+        rule.runOnIdle {
+            // When stretching, overscroll will consume after the scroll cycle
+            assertThat(state.onPreFlingAvailable.x).isWithin(1f).of(-1000f)
+            assertThat(state.scrollPosition).isEqualTo(1000f)
+            // Some velocity will be consumed as part of scrollable performing a fling animation,
+            // even if we are at the end bound, so this value will be a bit lower as some velocity
+            // is lost during the decay animation, before we return.
+            assertThat(state.onPostFlingAvailable.x).isWithin(100f).of(-1000f)
+        }
+    }
+
+    /**
+     * Test case to make sure that stretch overscroll correctly consumes delta before the scroll
+     * cycle when relaxing with a low velocity fling. Fling left = showing overscroll from the right
+     * edge because of reverse scrolling
+     */
+    @Test
+    fun stretchOverscroll_consumesDelta_flingLeft_relax_lowVelocity() {
+        val state = setStretchOverscrollContent(Orientation.Horizontal)
+        // Move to the end, since flinging left requires us to be at the right edge
+        state.dispatchRawDelta(1000f)
+        rule.runOnIdle { assertThat(state.scrollPosition).isEqualTo(1000f) }
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            down(center)
+            // Stretch by 200
+            moveBy(Offset(-200f, 0f))
+            state.overscroll.invalidationEnabled = false
+        }
+
+        rule.runOnIdle {
+            assertThat(state.onPreScrollAvailable.x).isEqualTo(-200f)
+            // No fling yet
+            assertThat(state.onPreFlingAvailable.x).isEqualTo(0f)
+            assertThat(state.scrollPosition).isEqualTo(1000f)
+            assertThat(state.onPostFlingAvailable.x).isEqualTo(0f)
+        }
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            // TODO: use test API when VelocityPathFinder is made public / there is another API to
+            //  start a fling after some previous move events
+            // Relax by a total of 100: there will be 100 stretch left, and a low velocity
+            // (since we have a lot of small moves, over a long period of time) left over to relax
+            // the stretch with. Note that events with a duration longer than 40ms between them are
+            // ignored by velocity tracker, so we can't add a large delay between events.
+            repeat(100) { moveBy(Offset(1f, 0f)) }
+            up()
+        }
+
+        rule.runOnIdle {
+            // The velocity here will be lower than required to fully relax the stretch, so all
+            // velocity should be consumed, and the overscroll should relax to 0.
+            assertThat(state.onPreScrollAvailable.x).isEqualTo(-200f)
+            assertThat(state.onPreFlingAvailable.x).isEqualTo(0f)
+            assertThat(state.scrollPosition).isEqualTo(1000f)
+            assertThat(state.onPostFlingAvailable.x).isEqualTo(0f)
+        }
+    }
+
+    /**
+     * Test case to make sure that stretch overscroll does not consume delta before the scroll cycle
+     * when relaxing with a high velocity fling (instead the stretch will be relaxed as part of the
+     * scroll cycle). Fling left = showing overscroll from the right edge because of reverse
+     * scrolling
+     */
+    @Test
+    fun stretchOverscroll_consumesDelta_flingLeft_relax_highVelocity() {
+        val state = setStretchOverscrollContent(Orientation.Horizontal)
+        // Move to the end, since flinging left requires us to be at the right edge
+        state.dispatchRawDelta(1000f)
+        rule.runOnIdle { assertThat(state.scrollPosition).isEqualTo(1000f) }
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            down(center)
+            // Stretch by 200
+            moveBy(Offset(-200f, 0f))
+            state.overscroll.invalidationEnabled = false
+        }
+
+        rule.runOnIdle {
+            assertThat(state.onPreScrollAvailable.x).isEqualTo(-200f)
+            // No fling yet
+            assertThat(state.onPreFlingAvailable.x).isEqualTo(0f)
+            assertThat(state.scrollPosition).isEqualTo(1000f)
+            assertThat(state.onPostFlingAvailable.x).isEqualTo(0f)
+        }
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            // TODO: use test API when VelocityPathFinder is made public / there is another API to
+            //  start a fling after some previous move events
+            // Relax by a total of 100: there will be 100 stretch left, and a high velocity
+            // (since we have two large moves, over a short period of time) left over to relax
+            // the stretch with.
+            moveBy(Offset(50f, 0f))
+            moveBy(Offset(50f, 0f))
+            up()
+        }
+
+        rule.runOnIdle {
+            // The velocity here will be higher than required to fully relax the stretch, so instead
+            // of consuming velocity, we will instead relax the stretch as part of the fling. As a
+            // result there should be some pre fling available, before we perform the fling
+            assertThat(state.onPreFlingAvailable.x).isGreaterThan(0f)
+            // There will be some leftover delta after relaxing the overscroll for pre scroll
+            assertThat(state.onPreScrollAvailable.x).isGreaterThan(-200f)
+            // The scroll will consume the leftover velocity after relaxing
+            assertThat(state.scrollPosition).isLessThan(1000f)
+        }
+    }
+
+    /**
+     * Test case to make sure that stretch overscroll correctly consumes delta before the scroll
+     * cycle when relaxing, and after the scroll cycle when stretching, when pulled. Pull top (up) =
+     * showing overscroll from the bottom edge because of reverse scrolling
+     */
+    @Test
+    fun stretchOverscroll_consumesDelta_pullTop() {
+        val state = setStretchOverscrollContent(Orientation.Vertical)
+        // Move to the end, since pulling up requires us to be at the bottom edge
+        state.dispatchRawDelta(1000f)
+        rule.runOnIdle { assertThat(state.scrollPosition).isEqualTo(1000f) }
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            down(center)
+            // Stretch by 200
+            moveBy(Offset(0f, -200f))
+            state.overscroll.invalidationEnabled = false
+        }
+
+        rule.runOnIdle {
+            // When stretching, overscroll will consume after the scroll cycle
+            assertThat(state.onPreScrollAvailable.y).isEqualTo(-200f)
+            assertThat(state.scrollPosition).isEqualTo(1000f)
+            assertThat(state.onPostScrollAvailable.y).isEqualTo(-200f)
+        }
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            // Stretch by another 200
+            moveBy(Offset(0f, -200f))
+        }
+
+        rule.runOnIdle {
+            assertThat(state.onPreScrollAvailable.y).isEqualTo(-400f)
+            assertThat(state.scrollPosition).isEqualTo(1000f)
+            assertThat(state.onPostScrollAvailable.y).isEqualTo(-400f)
+        }
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            // Pull 200 in the opposite direction - because we had 200 pixels of stretch before,
+            // this should only relax the existing overscroll, and not dispatch anything to the
+            // state
+            moveBy(Offset(0f, 200f))
+        }
+
+        rule.runOnIdle {
+            // Overscroll consumes when relaxing before the scroll cycle, so these will not see the
+            // new delta - all 200 should have been consumed relaxing the existing stretch
+            assertThat(state.onPreScrollAvailable.y).isEqualTo(-400f)
+            assertThat(state.scrollPosition).isEqualTo(1000f)
+            assertThat(state.onPostScrollAvailable.y).isEqualTo(-400f)
+        }
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            // Relax all the way, and continue into a scroll in the other direction with 200 excess
+            moveBy(Offset(0f, 400f))
+        }
+
+        rule.runOnIdle {
+            // Since overscroll fully relaxed, there should be 200 excess
+            assertThat(state.onPreScrollAvailable.y).isEqualTo(-200f)
+            // The scroll will consume the new delta
+            assertThat(state.scrollPosition).isEqualTo(800f)
+            // So post scroll will be unchanged at this point
+            assertThat(state.onPostScrollAvailable.y).isEqualTo(-400f)
+        }
+    }
+
+    /**
+     * Test case to make sure that stretch overscroll correctly consumes delta after the scroll
+     * cycle when stretching with a fling. Fling top (up) = showing overscroll from the bottom edge
+     * because of reverse scrolling
+     */
+    @Test
+    fun stretchOverscroll_consumesDelta_flingTop_stretch() {
+        val state = setStretchOverscrollContent(Orientation.Vertical)
+        // Move to the end, since flinging up requires us to be at the bottom edge
+        state.dispatchRawDelta(1000f)
+        rule.runOnIdle { assertThat(state.scrollPosition).isEqualTo(1000f) }
+
+        val velocity = 1000f
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            swipeWithVelocity(
+                start = center,
+                end = center - Offset(0f, 100f),
+                endVelocity = velocity
+            )
+            state.overscroll.invalidationEnabled = false
+        }
+
+        rule.runOnIdle {
+            // When stretching, overscroll will consume after the scroll cycle
+            assertThat(state.onPreFlingAvailable.y).isWithin(1f).of(-1000f)
+            assertThat(state.scrollPosition).isEqualTo(1000f)
+            // Some velocity will be consumed as part of scrollable performing a fling animation,
+            // even if we are at the end bound, so this value will be a bit lower as some velocity
+            // is lost during the decay animation, before we return.
+            assertThat(state.onPostFlingAvailable.y).isWithin(100f).of(-1000f)
+        }
+    }
+
+    /**
+     * Test case to make sure that stretch overscroll correctly consumes delta before the scroll
+     * cycle when relaxing with a low velocity fling. Fling top (up) = showing overscroll from the
+     * bottom edge because of reverse scrolling
+     */
+    @Test
+    fun stretchOverscroll_consumesDelta_flingTop_relax_lowVelocity() {
+        val state = setStretchOverscrollContent(Orientation.Vertical)
+        // Move to the end, since flinging up requires us to be at the bottom edge
+        state.dispatchRawDelta(1000f)
+        rule.runOnIdle { assertThat(state.scrollPosition).isEqualTo(1000f) }
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            down(center)
+            // Stretch by 200
+            moveBy(Offset(0f, -200f))
+            state.overscroll.invalidationEnabled = false
+        }
+
+        rule.runOnIdle {
+            assertThat(state.onPreScrollAvailable.y).isEqualTo(-200f)
+            // No fling yet
+            assertThat(state.onPreFlingAvailable.y).isEqualTo(0f)
+            assertThat(state.scrollPosition).isEqualTo(1000f)
+            assertThat(state.onPostFlingAvailable.y).isEqualTo(0f)
+        }
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            // TODO: use test API when VelocityPathFinder is made public / there is another API to
+            //  start a fling after some previous move events
+            // Relax by a total of 100: there will be 100 stretch left, and a low velocity
+            // (since we have a lot of small moves, over a long period of time) left over to relax
+            // the stretch with. Note that events with a duration longer than 40ms between them are
+            // ignored by velocity tracker, so we can't add a large delay between events.
+            repeat(100) { moveBy(Offset(0f, 1f)) }
+            up()
+        }
+
+        rule.runOnIdle {
+            // The velocity here will be lower than required to fully relax the stretch, so all
+            // velocity should be consumed, and the overscroll should relax to 0.
+            assertThat(state.onPreScrollAvailable.y).isEqualTo(-200f)
+            assertThat(state.onPreFlingAvailable.y).isEqualTo(0f)
+            assertThat(state.scrollPosition).isEqualTo(1000f)
+            assertThat(state.onPostFlingAvailable.y).isEqualTo(0f)
+        }
+    }
+
+    /**
+     * Test case to make sure that stretch overscroll does not consume delta before the scroll cycle
+     * when relaxing with a high velocity fling (instead the stretch will be relaxed as part of the
+     * scroll cycle). Fling top (up) = showing overscroll from the bottom edge because of reverse
+     * scrolling
+     */
+    @Test
+    fun stretchOverscroll_consumesDelta_flingTop_relax_highVelocity() {
+        val state = setStretchOverscrollContent(Orientation.Vertical)
+        // Move to the end, since flinging up requires us to be at the bottom edge
+        state.dispatchRawDelta(1000f)
+        rule.runOnIdle { assertThat(state.scrollPosition).isEqualTo(1000f) }
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            down(center)
+            // Stretch by 200
+            moveBy(Offset(0f, -200f))
+            state.overscroll.invalidationEnabled = false
+        }
+
+        rule.runOnIdle {
+            assertThat(state.onPreScrollAvailable.y).isEqualTo(-200f)
+            // No fling yet
+            assertThat(state.onPreFlingAvailable.y).isEqualTo(0f)
+            assertThat(state.scrollPosition).isEqualTo(1000f)
+            assertThat(state.onPostFlingAvailable.y).isEqualTo(0f)
+        }
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            // TODO: use test API when VelocityPathFinder is made public / there is another API to
+            //  start a fling after some previous move events
+            // Relax by a total of 100: there will be 100 stretch left, and a high velocity
+            // (since we have two large moves, over a short period of time) left over to relax
+            // the stretch with.
+            moveBy(Offset(0f, 50f))
+            moveBy(Offset(0f, 50f))
+            up()
+        }
+
+        rule.runOnIdle {
+            // The velocity here will be higher than required to fully relax the stretch, so instead
+            // of consuming velocity, we will instead relax the stretch as part of the fling. As a
+            // result there should be some pre fling available, before we perform the fling
+            assertThat(state.onPreFlingAvailable.y).isGreaterThan(0f)
+            // There will be some leftover delta after relaxing the overscroll for pre scroll
+            assertThat(state.onPreScrollAvailable.y).isGreaterThan(-200f)
+            // The scroll will consume the leftover velocity after relaxing
+            assertThat(state.scrollPosition).isLessThan(1000f)
+        }
+    }
+
+    /**
+     * Test case to make sure that stretch overscroll correctly consumes delta before the scroll
+     * cycle when relaxing, and after the scroll cycle when stretching, when pulled. Pull right =
+     * showing overscroll from the left edge because of reverse scrolling
+     */
+    @Test
+    fun stretchOverscroll_consumesDelta_pullRight() {
+        val state = setStretchOverscrollContent(Orientation.Horizontal)
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            down(center)
+            // Stretch by 200
+            moveBy(Offset(200f, 0f))
+            state.overscroll.invalidationEnabled = false
+        }
+
+        rule.runOnIdle {
+            // When stretching, overscroll will consume after the scroll cycle
+            assertThat(state.onPreScrollAvailable.x).isEqualTo(200f)
+            assertThat(state.scrollPosition).isEqualTo(0f)
+            assertThat(state.onPostScrollAvailable.x).isEqualTo(200f)
+        }
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            // Stretch by another 200
+            moveBy(Offset(200f, 0f))
+        }
+
+        rule.runOnIdle {
+            assertThat(state.onPreScrollAvailable.x).isEqualTo(400f)
+            assertThat(state.scrollPosition).isEqualTo(0f)
+            assertThat(state.onPostScrollAvailable.x).isEqualTo(400f)
+        }
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            // Pull 200 in the opposite direction - because we had 200 pixels of stretch before,
+            // this should only relax the existing overscroll, and not dispatch anything to the
+            // state
+            moveBy(Offset(-200f, 0f))
+        }
+
+        rule.runOnIdle {
+            // Overscroll consumes when relaxing before the scroll cycle, so these will not see the
+            // new delta - all 200 should have been consumed relaxing the existing stretch
+            assertThat(state.onPreScrollAvailable.x).isEqualTo(400f)
+            assertThat(state.scrollPosition).isEqualTo(0f)
+            assertThat(state.onPostScrollAvailable.x).isEqualTo(400f)
+        }
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            // Relax all the way, and continue into a scroll in the other direction with 200 excess
+            moveBy(Offset(-400f, 0f))
+        }
+
+        rule.runOnIdle {
+            // Since overscroll fully relaxed, there should be 200 excess
+            assertThat(state.onPreScrollAvailable.x).isEqualTo(200f)
+            // The scroll will consume the new delta
+            assertThat(state.scrollPosition).isEqualTo(200f)
+            // So post scroll will be unchanged at this point
+            assertThat(state.onPostScrollAvailable.x).isEqualTo(400f)
+        }
+    }
+
+    /**
+     * Test case to make sure that stretch overscroll correctly consumes delta after the scroll
+     * cycle when stretching with a fling. Fling right = showing overscroll from the left edge
+     * because of reverse scrolling
+     */
+    @Test
+    fun stretchOverscroll_consumesDelta_flingRight_stretch() {
+        val state = setStretchOverscrollContent(Orientation.Horizontal)
+
+        val velocity = 1000f
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            swipeWithVelocity(
+                start = center,
+                end = center + Offset(100f, 0f),
+                endVelocity = velocity
+            )
+            state.overscroll.invalidationEnabled = false
+        }
+
+        rule.runOnIdle {
+            // When stretching, overscroll will consume after the scroll cycle
+            assertThat(state.onPreFlingAvailable.x).isWithin(1f).of(1000f)
+            assertThat(state.scrollPosition).isEqualTo(0f)
+            // Some velocity will be consumed as part of scrollable performing a fling animation,
+            // even if we are at the end bound, so this value will be a bit lower as some velocity
+            // is lost during the decay animation, before we return.
+            assertThat(state.onPostFlingAvailable.x).isWithin(100f).of(1000f)
+        }
+    }
+
+    /**
+     * Test case to make sure that stretch overscroll correctly consumes delta before the scroll
+     * cycle when relaxing with a low velocity fling. Fling right = showing overscroll from the left
+     * edge because of reverse scrolling
+     */
+    @Test
+    fun stretchOverscroll_consumesDelta_flingRight_relax_lowVelocity() {
+        val state = setStretchOverscrollContent(Orientation.Horizontal)
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            down(center)
+            // Stretch by 200
+            moveBy(Offset(200f, 0f))
+            state.overscroll.invalidationEnabled = false
+        }
+
+        rule.runOnIdle {
+            assertThat(state.onPreScrollAvailable.x).isEqualTo(200f)
+            // No fling yet
+            assertThat(state.onPreFlingAvailable.x).isEqualTo(0f)
+            assertThat(state.scrollPosition).isEqualTo(0f)
+            assertThat(state.onPostFlingAvailable.x).isEqualTo(0f)
+        }
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            // TODO: use test API when VelocityPathFinder is made public / there is another API to
+            //  start a fling after some previous move events
+            // Relax by a total of 100: there will be 100 stretch left, and a low velocity
+            // (since we have a lot of small moves, over a long period of time) left over to relax
+            // the stretch with. Note that events with a duration longer than 40ms between them are
+            // ignored by velocity tracker, so we can't add a large delay between events.
+            repeat(100) { moveBy(Offset(-1f, 0f)) }
+            up()
+        }
+
+        rule.runOnIdle {
+            // The velocity here will be lower than required to fully relax the stretch, so all
+            // velocity should be consumed, and the overscroll should relax to 0.
+            assertThat(state.onPreScrollAvailable.x).isEqualTo(200f)
+            assertThat(state.onPreFlingAvailable.x).isEqualTo(0f)
+            assertThat(state.scrollPosition).isEqualTo(0f)
+            assertThat(state.onPostFlingAvailable.x).isEqualTo(0f)
+        }
+    }
+
+    /**
+     * Test case to make sure that stretch overscroll does not consume delta before the scroll cycle
+     * when relaxing with a high velocity fling (instead the stretch will be relaxed as part of the
+     * scroll cycle). Fling right = showing overscroll from the left edge because of reverse
+     * scrolling
+     */
+    @Test
+    fun stretchOverscroll_consumesDelta_flingRight_relax_highVelocity() {
+        val state = setStretchOverscrollContent(Orientation.Horizontal)
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            down(center)
+            // Stretch by 200
+            moveBy(Offset(200f, 0f))
+            state.overscroll.invalidationEnabled = false
+        }
+
+        rule.runOnIdle {
+            assertThat(state.onPreScrollAvailable.x).isEqualTo(200f)
+            // No fling yet
+            assertThat(state.onPreFlingAvailable.x).isEqualTo(0f)
+            assertThat(state.scrollPosition).isEqualTo(0f)
+            assertThat(state.onPostFlingAvailable.x).isEqualTo(0f)
+        }
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            // TODO: use test API when VelocityPathFinder is made public / there is another API to
+            //  start a fling after some previous move events
+            // Relax by a total of 100: there will be 100 stretch left, and a high velocity
+            // (since we have two large moves, over a short period of time) left over to relax
+            // the stretch with.
+            moveBy(Offset(-50f, 0f))
+            moveBy(Offset(-50f, 0f))
+            up()
+        }
+
+        rule.runOnIdle {
+            // The velocity here will be higher than required to fully relax the stretch, so instead
+            // of consuming velocity, we will instead relax the stretch as part of the fling. As a
+            // result there should be some pre fling available, before we perform the fling
+            assertThat(state.onPreFlingAvailable.x).isLessThan(0f)
+            // There will be some leftover delta after relaxing the overscroll for pre scroll
+            assertThat(state.onPreScrollAvailable.x).isLessThan(200f)
+            // The scroll will consume the leftover velocity after relaxing
+            assertThat(state.scrollPosition).isGreaterThan(0f)
+        }
+    }
+
+    /**
+     * Test case to make sure that stretch overscroll correctly consumes delta before the scroll
+     * cycle when relaxing, and after the scroll cycle when stretching, when pulled. Pull bottom
+     * (down) = showing overscroll from the top edge because of reverse scrolling
+     */
+    @Test
+    fun stretchOverscroll_consumesDelta_pullBottom() {
+        val state = setStretchOverscrollContent(Orientation.Vertical)
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            down(center)
+            // Stretch by 200
+            moveBy(Offset(0f, 200f))
+            state.overscroll.invalidationEnabled = false
+        }
+
+        rule.runOnIdle {
+            // When stretching, overscroll will consume after the scroll cycle
+            assertThat(state.onPreScrollAvailable.y).isEqualTo(200f)
+            assertThat(state.scrollPosition).isEqualTo(0f)
+            assertThat(state.onPostScrollAvailable.y).isEqualTo(200f)
+        }
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            // Stretch by another 200
+            moveBy(Offset(0f, 200f))
+        }
+
+        rule.runOnIdle {
+            assertThat(state.onPreScrollAvailable.y).isEqualTo(400f)
+            assertThat(state.scrollPosition).isEqualTo(0f)
+            assertThat(state.onPostScrollAvailable.y).isEqualTo(400f)
+        }
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            // Pull 200 in the opposite direction - because we had 200 pixels of stretch before,
+            // this should only relax the existing overscroll, and not dispatch anything to the
+            // state
+            moveBy(Offset(0f, -200f))
+        }
+
+        rule.runOnIdle {
+            // Overscroll consumes when relaxing before the scroll cycle, so these will not see the
+            // new delta - all 200 should have been consumed relaxing the existing stretch
+            assertThat(state.onPreScrollAvailable.y).isEqualTo(400f)
+            assertThat(state.scrollPosition).isEqualTo(0f)
+            assertThat(state.onPostScrollAvailable.y).isEqualTo(400f)
+        }
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            // Relax all the way, and continue into a scroll in the other direction with 200 excess
+            moveBy(Offset(0f, -400f))
+        }
+
+        rule.runOnIdle {
+            // Since overscroll fully relaxed, there should be 200 excess
+            assertThat(state.onPreScrollAvailable.y).isEqualTo(200f)
+            // The scroll will consume the new delta
+            assertThat(state.scrollPosition).isEqualTo(200f)
+            // So post scroll will be unchanged at this point
+            assertThat(state.onPostScrollAvailable.y).isEqualTo(400f)
+        }
+    }
+
+    /**
+     * Test case to make sure that stretch overscroll correctly consumes delta after the scroll
+     * cycle when stretching with a fling. Fling bottom (down) = showing overscroll from the top
+     * edge because of reverse scrolling
+     */
+    @Test
+    fun stretchOverscroll_consumesDelta_flingBottom_stretch() {
+        val state = setStretchOverscrollContent(Orientation.Vertical)
+
+        val velocity = 1000f
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            swipeWithVelocity(
+                start = center,
+                end = center + Offset(0f, 100f),
+                endVelocity = velocity
+            )
+            state.overscroll.invalidationEnabled = false
+        }
+
+        rule.runOnIdle {
+            // When stretching, overscroll will consume after the scroll cycle
+            assertThat(state.onPreFlingAvailable.y).isWithin(1f).of(1000f)
+            assertThat(state.scrollPosition).isEqualTo(0f)
+            // Some velocity will be consumed as part of scrollable performing a fling animation,
+            // even if we are at the end bound, so this value will be a bit lower as some velocity
+            // is lost during the decay animation, before we return.
+            assertThat(state.onPostFlingAvailable.y).isWithin(100f).of(1000f)
+        }
+    }
+
+    /**
+     * Test case to make sure that stretch overscroll correctly consumes delta before the scroll
+     * cycle when relaxing with a low velocity fling. Fling bottom (down) = showing overscroll from
+     * the top edge because of reverse scrolling
+     */
+    @Test
+    fun stretchOverscroll_consumesDelta_flingBottom_relax_lowVelocity() {
+        val state = setStretchOverscrollContent(Orientation.Vertical)
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            down(center)
+            // Stretch by 200
+            moveBy(Offset(0f, 200f))
+            state.overscroll.invalidationEnabled = false
+        }
+
+        rule.runOnIdle {
+            assertThat(state.onPreScrollAvailable.y).isEqualTo(200f)
+            // No fling yet
+            assertThat(state.onPreFlingAvailable.y).isEqualTo(0f)
+            assertThat(state.scrollPosition).isEqualTo(0f)
+            assertThat(state.onPostFlingAvailable.y).isEqualTo(0f)
+        }
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            // TODO: use test API when VelocityPathFinder is made public / there is another API to
+            //  start a fling after some previous move events
+            // Relax by a total of 100: there will be 100 stretch left, and a low velocity
+            // (since we have a lot of small moves, over a long period of time) left over to relax
+            // the stretch with. Note that events with a duration longer than 40ms between them are
+            // ignored by velocity tracker, so we can't add a large delay between events.
+            repeat(100) { moveBy(Offset(0f, -1f)) }
+            up()
+        }
+
+        rule.runOnIdle {
+            // The velocity here will be lower than required to fully relax the stretch, so all
+            // velocity should be consumed, and the overscroll should relax to 0.
+            assertThat(state.onPreScrollAvailable.y).isEqualTo(200f)
+            assertThat(state.onPreFlingAvailable.y).isEqualTo(0f)
+            assertThat(state.scrollPosition).isEqualTo(0f)
+            assertThat(state.onPostFlingAvailable.y).isEqualTo(0f)
+        }
+    }
+
+    /**
+     * Test case to make sure that stretch overscroll does not consume delta before the scroll cycle
+     * when relaxing with a high velocity fling (instead the stretch will be relaxed as part of the
+     * scroll cycle). Fling bottom (down) = showing overscroll from the top edge because of reverse
+     * scrolling
+     */
+    @Test
+    fun stretchOverscroll_doesNotConsumeDelta_flingBottom_relax_highVelocity() {
+        val state = setStretchOverscrollContent(Orientation.Vertical)
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            down(center)
+            // Stretch by 200
+            moveBy(Offset(0f, 200f))
+            state.overscroll.invalidationEnabled = false
+        }
+
+        rule.runOnIdle {
+            assertThat(state.onPreScrollAvailable.y).isEqualTo(200f)
+            // No fling yet
+            assertThat(state.onPreFlingAvailable.y).isEqualTo(0f)
+            assertThat(state.scrollPosition).isEqualTo(0f)
+            assertThat(state.onPostFlingAvailable.y).isEqualTo(0f)
+        }
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            // TODO: use test API when VelocityPathFinder is made public / there is another API to
+            //  start a fling after some previous move events
+            // Relax by a total of 100: there will be 100 stretch left, and a high velocity
+            // (since we have two large moves, over a short period of time) left over to relax
+            // the stretch with.
+            moveBy(Offset(0f, -50f))
+            moveBy(Offset(0f, -50f))
+            up()
+        }
+
+        rule.runOnIdle {
+            // The velocity here will be higher than required to fully relax the stretch, so instead
+            // of consuming velocity, we will instead relax the stretch as part of the fling. As a
+            // result there should be some pre fling available, before we perform the fling
+            assertThat(state.onPreFlingAvailable.y).isLessThan(0f)
+            // There will be some leftover delta after relaxing the overscroll for pre scroll
+            assertThat(state.onPreScrollAvailable.y).isLessThan(200f)
+            // The scroll will consume the leftover velocity after relaxing
+            assertThat(state.scrollPosition).isGreaterThan(0f)
+        }
+    }
+
+    // Tests for b/265363356
+
+    @Test
+    fun stretchOverscroll_whenPulledWithSmallDelta_doesNotConsumesOppositePreScroll_pullLeft() {
+        val state = setStretchOverscrollContent(Orientation.Horizontal)
+        // Move to the end, since flinging left requires us to be at the right edge
+        state.dispatchRawDelta(1000f)
+        rule.runOnIdle { assertThat(state.scrollPosition).isEqualTo(1000f) }
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            down(center)
+            // Try and stretch by 0.4f
+            moveBy(Offset(-0.4f, 0f))
+            // Pull 200 in the opposite direction - overscroll should have ignored the 0.4f, and
+            // so all 200 should be dispatched to the state with nothing being consumed
+            moveBy(Offset(200f, 0f))
+        }
+
+        rule.runOnIdle {
+            // The -0.4f should still have been dispatched to pre scroll, and then it will see the
+            // 200f after
+            assertThat(state.onPreScrollAvailable.x).isWithin(0.001f).of(199.6f)
+            // All 200f should be dispatched directly to the state
+            assertThat(state.scrollPosition).isEqualTo(800f)
+            // The -0.4f should still have been dispatched to post scroll, but the 200f is fully
+            // consumed by the scroll
+            assertThat(state.onPostScrollAvailable.x).isWithin(0.001f).of(-0.4f)
+        }
+    }
+
+    @Test
+    fun stretchOverscroll_whenPulledWithSmallDelta_doesNotConsumesOppositePreScroll_pullTop() {
+        val state = setStretchOverscrollContent(Orientation.Vertical)
+        // Move to the end, since flinging up requires us to be at the bottom edge
+        state.dispatchRawDelta(1000f)
+        rule.runOnIdle { assertThat(state.scrollPosition).isEqualTo(1000f) }
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            down(center)
+            // Try and stretch by 0.4f
+            moveBy(Offset(0f, -0.4f))
+            // Pull 200 in the opposite direction - overscroll should have ignored the 0.4f, and
+            // so all 200 should be dispatched to the state with nothing being consumed
+            moveBy(Offset(0f, 200f))
+        }
+
+        rule.runOnIdle {
+            // The -0.4f should still have been dispatched to pre scroll, and then it will see the
+            // 200f after
+            assertThat(state.onPreScrollAvailable.y).isWithin(0.001f).of(199.6f)
+            // All 200f should be dispatched directly to the state
+            assertThat(state.scrollPosition).isEqualTo(800f)
+            // The -0.4f should still have been dispatched to post scroll, but the 200f is fully
+            // consumed by the scroll
+            assertThat(state.onPostScrollAvailable.y).isWithin(0.001f).of(-0.4f)
+        }
+    }
+
+    @Test
+    fun stretchOverscroll_whenPulledWithSmallDelta_doesNotConsumesOppositePreScroll_pullRight() {
+        val state = setStretchOverscrollContent(Orientation.Horizontal)
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            down(center)
+            // Try and stretch by 0.4f (the max scroll value is 1000)
+            moveBy(Offset(0.4f, 0f))
+            // Pull 200 in the opposite direction - overscroll should have ignored the 0.4f, and
+            // so all -200 should be dispatched to the state with nothing being consumed
+            moveBy(Offset(-200f, 0f))
+        }
+
+        rule.runOnIdle {
+            // The extra 0.4f should still have been dispatched to pre scroll, and then it will see
+            // the -200f after
+            assertThat(state.onPreScrollAvailable.x).isWithin(0.001f).of(-199.6f)
+            // All -200f should be dispatched directly to the state
+            assertThat(state.scrollPosition).isEqualTo(200f)
+            // The extra 0.4f should still have been dispatched to post scroll, but the 1000f and
+            // -200f are fully consumed by the scroll
+            assertThat(state.onPostScrollAvailable.x).isWithin(0.001f).of(0.4f)
+        }
+    }
+
+    @Test
+    fun stretchOverscroll_whenPulledWithSmallDelta_doesNotConsumesOppositePreScroll_pullBottom() {
+        val state = setStretchOverscrollContent(Orientation.Vertical)
+
+        rule.onNodeWithTag(OverscrollBox).performTouchInput {
+            down(center)
+            // Try and stretch by 0.4f (the max scroll value is 1000)
+            moveBy(Offset(0f, 0.4f))
+            // Pull 200 in the opposite direction - overscroll should have ignored the 0.4f, and
+            // so all -200 should be dispatched to the state with nothing being consumed
+            moveBy(Offset(0f, -200f))
+        }
+
+        rule.runOnIdle {
+            // The extra 0.4f should still have been dispatched to pre scroll, and then it will see
+            // the -200f after
+            assertThat(state.onPreScrollAvailable.y).isWithin(0.001f).of(-199.6f)
+            // All -200f should be dispatched directly to the state
+            assertThat(state.scrollPosition).isEqualTo(200f)
+            // The extra 0.4f should still have been dispatched to post scroll, but the 1000f and
+            // -200f are fully consumed by the scroll
+            assertThat(state.onPostScrollAvailable.y).isWithin(0.001f).of(0.4f)
+        }
+    }
+
+    private fun setStretchOverscrollContent(orientation: Orientation): TestState {
+        animationScaleRule.setAnimationDurationScale(1f)
+        val state = TestState()
+        rule.setContent {
+            WithTouchSlop(touchSlop = 0f) {
+                state.overscroll =
+                    ScrollableDefaults.overscrollEffect() as AndroidEdgeEffectOverscrollEffect
+                Box(
+                    Modifier.testTag(OverscrollBox)
+                        .size(250.dp)
+                        .nestedScroll(state.nestedScrollConnection)
+                        .scrollable(
+                            state = state,
+                            orientation = orientation,
+                            // Match typical scroll container behavior where the content is moved,
+                            // not the viewport
+                            reverseDirection =
+                                ScrollableDefaults.reverseDirection(
+                                    layoutDirection = LocalLayoutDirection.current,
+                                    orientation = orientation,
+                                    reverseScrolling = false
+                                ),
+                            overscrollEffect = state.overscroll
+                        )
+                        .overscroll(state.overscroll)
+                )
+            }
+        }
+        return state
+    }
+}
+
+/**
+ * Returns a default [ScrollableState] with a [scrollPosition] clamped between 0f and 1000f, and
+ * exposes properties for seeing nested scroll available delta and velocities.
+ */
+private class TestState : ScrollableState {
+    var scrollPosition by mutableStateOf(0f)
+        private set
+
+    var onPreScrollAvailable: Offset = Offset.Zero
+        private set
+
+    var onPostScrollAvailable: Offset = Offset.Zero
+        private set
+
+    var onPreFlingAvailable: Velocity = Velocity.Zero
+        private set
+
+    var onPostFlingAvailable: Velocity = Velocity.Zero
+        private set
+
+    lateinit var overscroll: AndroidEdgeEffectOverscrollEffect
+
+    // Using ScrollableState here instead of ScrollState as ScrollState will automatically round to
+    // an int, and we need to assert floating point values
+    private val scrollableState = ScrollableState {
+        val newPosition = (scrollPosition + it).coerceIn(0f, 1000f)
+        val consumed = newPosition - scrollPosition
+        scrollPosition = newPosition
+        consumed
+    }
+
+    val nestedScrollConnection =
+        object : NestedScrollConnection {
+            override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
+                onPreScrollAvailable += available
+                return Offset.Zero
+            }
+
+            override fun onPostScroll(
+                consumed: Offset,
+                available: Offset,
+                source: NestedScrollSource
+            ): Offset {
+                onPostScrollAvailable += available
+                return Offset.Zero
+            }
+
+            override suspend fun onPreFling(available: Velocity): Velocity {
+                onPreFlingAvailable += available
+                return Velocity.Zero
+            }
+
+            override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
+                onPostFlingAvailable += available
+                return Velocity.Zero
+            }
+        }
+
+    override suspend fun scroll(
+        scrollPriority: MutatePriority,
+        block: suspend ScrollScope.() -> Unit
+    ) = scrollableState.scroll(scrollPriority, block)
+
+    override fun dispatchRawDelta(delta: Float) = scrollableState.dispatchRawDelta(delta)
+
+    override val isScrollInProgress: Boolean
+        get() = scrollableState.isScrollInProgress
+}
+
+private const val OverscrollBox = "box"
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/StretchOverscrollScreenshotTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/StretchOverscrollScreenshotTest.kt
new file mode 100644
index 0000000..e86f231
--- /dev/null
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/StretchOverscrollScreenshotTest.kt
@@ -0,0 +1,231 @@
+/*
+ * 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.foundation
+
+import android.os.Build
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.wrapContentSize
+import androidx.compose.foundation.text.BasicText
+import androidx.compose.runtime.Composable
+import androidx.compose.testutils.assertAgainstGolden
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clipToBounds
+import androidx.compose.ui.draw.drawBehind
+import androidx.compose.ui.draw.rotate
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.input.nestedscroll.NestedScrollSource
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.captureToImage
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.screenshot.AndroidXScreenshotTestRule
+import androidx.test.screenshot.ScreenshotTestRule
+import androidx.test.screenshot.matchers.MSSIMMatcher
+import androidx.testutils.AnimationDurationScaleRule
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Screenshot test for stretch overscroll (S+) - we currently only run screenshot tests on API 33,
+ * so it is not possible to screenshot test glow overscroll in this way (we would have
+ * synchronization issues anyway, since glow recedes on its own, and doesn't follow animation
+ * scale).
+ */
+@LargeTest
+@RunWith(AndroidJUnit4::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
+class StretchOverscrollScreenshotTest {
+    @get:Rule val rule = createComposeRule()
+
+    @get:Rule val screenshotRule = AndroidXScreenshotTestRule(GOLDEN_FOUNDATION)
+
+    @get:Rule
+    val animationScaleRule: AnimationDurationScaleRule = AnimationDurationScaleRule.create()
+
+    private val overscrollTag = "overscrollTag"
+
+    /** Pull right to stretch from the left */
+    @Test
+    fun stretch_left() {
+        stretchAndAssertAgainstGolden(Offset(150f, 0f), screenshotRule, "overscroll_left")
+    }
+
+    /** Pull down to stretch from the top */
+    @Test
+    fun stretch_top() {
+        stretchAndAssertAgainstGolden(Offset(0f, 150f), screenshotRule, "overscroll_top")
+    }
+
+    /** Pull left to stretch from the right */
+    @Test
+    fun stretch_right() {
+        stretchAndAssertAgainstGolden(Offset(-150f, 0f), screenshotRule, "overscroll_right")
+    }
+
+    /** Pull up to stretch from the bottom */
+    @Test
+    fun stretch_bottom() {
+        stretchAndAssertAgainstGolden(Offset(0f, -150f), screenshotRule, "overscroll_bottom")
+    }
+
+    @Composable
+    private fun OverscrollContent(
+        orientation: Orientation,
+        overscrollEffect: OverscrollEffect,
+        onDrawOverscroll: () -> Unit
+    ) {
+        Box(Modifier.fillMaxSize().wrapContentSize(Alignment.Center)) {
+            Box(Modifier.testTag(overscrollTag).clipToBounds()) {
+                if (orientation == Orientation.Vertical) {
+                    Row {
+                        Stripes(
+                            orientation = Orientation.Vertical,
+                            showText = false,
+                            modifier = Modifier.border(1.dp, Color.Black)
+                        )
+                        Stripes(
+                            orientation = Orientation.Vertical,
+                            showText = true,
+                            modifier =
+                                Modifier.border(1.dp, Color.Black)
+                                    .overscroll(overscrollEffect)
+                                    .drawBehind { onDrawOverscroll() }
+                        )
+                        Stripes(
+                            orientation = Orientation.Vertical,
+                            showText = false,
+                            modifier = Modifier.border(1.dp, Color.Black)
+                        )
+                    }
+                } else {
+                    Column {
+                        Stripes(
+                            orientation = Orientation.Horizontal,
+                            showText = false,
+                            modifier = Modifier.border(1.dp, Color.Black)
+                        )
+                        Stripes(
+                            orientation = Orientation.Horizontal,
+                            showText = true,
+                            modifier =
+                                Modifier.border(1.dp, Color.Black)
+                                    .overscroll(overscrollEffect)
+                                    .drawBehind { onDrawOverscroll() }
+                        )
+                        Stripes(
+                            orientation = Orientation.Horizontal,
+                            showText = false,
+                            modifier = Modifier.border(1.dp, Color.Black)
+                        )
+                    }
+                }
+            }
+        }
+    }
+
+    @Composable
+    private fun Stripes(
+        orientation: Orientation,
+        showText: Boolean,
+        modifier: Modifier = Modifier
+    ) {
+        val mainAxisSize = 100.dp
+        val crossAxisSize = 50.dp
+        Box {
+            if (orientation == Orientation.Vertical) {
+                Column(modifier.size(width = crossAxisSize, height = mainAxisSize)) {
+                    repeat(10) {
+                        Stripe(index = it, width = crossAxisSize, height = mainAxisSize / 10)
+                    }
+                }
+                if (showText) {
+                    Box(Modifier.matchParentSize().wrapContentSize(Alignment.Center)) {
+                        BasicText(
+                            "Stretch",
+                            Modifier.rotate(90f),
+                            style = TextStyle(color = Color.White)
+                        )
+                    }
+                }
+            } else {
+                Row(modifier.size(width = mainAxisSize, height = crossAxisSize)) {
+                    repeat(10) {
+                        Stripe(index = it, width = mainAxisSize / 10, height = crossAxisSize)
+                    }
+                }
+                if (showText) {
+                    Box(Modifier.matchParentSize().wrapContentSize(Alignment.Center)) {
+                        BasicText("Stretch", style = TextStyle(color = Color.White))
+                    }
+                }
+            }
+        }
+    }
+
+    @Composable
+    private fun Stripe(index: Int, width: Dp, height: Dp) {
+        val color = if (index % 2 == 0) Color.Red else Color.Blue
+        Spacer(Modifier.size(width = width, height = height).background(color))
+    }
+
+    private fun stretchAndAssertAgainstGolden(
+        offset: Offset,
+        screenshotRule: ScreenshotTestRule,
+        goldenIdentifier: String
+    ) {
+        animationScaleRule.setAnimationDurationScale(1f)
+        // Due to b/302303969 there are no guarantees runOnIdle() will wait for drawing to happen,
+        // so we need to manually synchronize drawing
+        var hasDrawn = false
+        lateinit var overscrollEffect: AndroidEdgeEffectOverscrollEffect
+        require(offset.x == 0f || offset.y == 0f) { "Only one direction is supported" }
+        require(offset != Offset.Zero) { "Offset must be non-zero" }
+        val orientation = if (offset.y != 0f) Orientation.Vertical else Orientation.Horizontal
+        rule.setContent {
+            overscrollEffect = rememberOverscrollEffect() as AndroidEdgeEffectOverscrollEffect
+            OverscrollContent(orientation, overscrollEffect, onDrawOverscroll = { hasDrawn = true })
+        }
+        rule.waitUntil { hasDrawn }
+        rule.runOnIdle {
+            overscrollEffect.applyToScroll(offset, NestedScrollSource.UserInput) { Offset.Zero }
+            // Disable further invalidations to avoid infinitely invalidating and causing us to
+            // never become idle for test synchronization
+            overscrollEffect.invalidationEnabled = false
+            hasDrawn = false
+        }
+        rule.waitUntil { hasDrawn }
+        rule
+            .onNodeWithTag(overscrollTag)
+            .captureToImage()
+            .assertAgainstGolden(screenshotRule, goldenIdentifier, MSSIMMatcher(1.0))
+    }
+}
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/StretchOverscrollTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/StretchOverscrollTest.kt
deleted file mode 100644
index 9787779..0000000
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/StretchOverscrollTest.kt
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation
-
-import android.os.Build
-import androidx.compose.foundation.gestures.Orientation
-import androidx.compose.foundation.gestures.ScrollScope
-import androidx.compose.foundation.gestures.ScrollableDefaults
-import androidx.compose.foundation.gestures.ScrollableState
-import androidx.compose.foundation.gestures.scrollable
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.size
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.setValue
-import androidx.compose.testutils.WithTouchSlop
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.platform.testTag
-import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.compose.ui.test.onNodeWithTag
-import androidx.compose.ui.test.performTouchInput
-import androidx.compose.ui.unit.dp
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.MediumTest
-import androidx.test.filters.SdkSuppress
-import androidx.testutils.AnimationDurationScaleRule
-import com.google.common.truth.Truth.assertThat
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@MediumTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
-@RunWith(AndroidJUnit4::class)
-class StretchOverscrollTest {
-    @get:Rule val rule = createComposeRule()
-
-    @get:Rule
-    val animationScaleRule: AnimationDurationScaleRule =
-        AnimationDurationScaleRule.createForAllTests(1f)
-
-    @Test
-    fun stretchOverscroll_whenPulled_consumesOppositePreScroll_pullLeft() {
-        val state = setStretchOverscrollContent(Orientation.Horizontal)
-
-        rule.onNodeWithTag(OverscrollBox).performTouchInput {
-            down(center)
-            // Stretch by 200
-            moveBy(Offset(-200f, 0f))
-            // Pull 200 in the opposite direction - because we had 200 pixels of stretch before,
-            // this should only relax the existing overscroll, and not dispatch anything to the
-            // state
-            moveBy(Offset(200f, 0f))
-        }
-
-        rule.runOnIdle {
-            // All 200 should have been consumed by overscroll that was relaxing the existing
-            // stretch
-            assertThat(state.scrollPosition).isEqualTo(0f)
-        }
-    }
-
-    @Test
-    fun stretchOverscroll_whenPulledWithSmallDelta_doesNotConsumesOppositePreScroll_pullLeft() {
-        val state = setStretchOverscrollContent(Orientation.Horizontal)
-
-        rule.onNodeWithTag(OverscrollBox).performTouchInput {
-            down(center)
-            // Try and stretch by 0.4f
-            moveBy(Offset(-0.4f, 0f))
-            // Pull 200 in the opposite direction - overscroll should have ignored the 0.4f, and
-            // so all 200 should be dispatched to the state with nothing being consumed
-            moveBy(Offset(200f, 0f))
-        }
-
-        rule.runOnIdle {
-            // All 200 should be dispatched directly to the state
-            assertThat(state.scrollPosition).isEqualTo(200f)
-        }
-    }
-
-    @Test
-    fun stretchOverscroll_whenPulled_consumesOppositePreScroll_pullTop() {
-        val state = setStretchOverscrollContent(Orientation.Vertical)
-
-        rule.onNodeWithTag(OverscrollBox).performTouchInput {
-            down(center)
-            // Stretch by 200
-            moveBy(Offset(0f, -200f))
-            // Pull 200 in the opposite direction - because we had 200 pixels of stretch before,
-            // this should only relax the existing overscroll, and not dispatch anything to the
-            // state
-            moveBy(Offset(0f, 200f))
-        }
-
-        rule.runOnIdle {
-            // All 200 should have been consumed by overscroll that was relaxing the existing
-            // stretch
-            assertThat(state.scrollPosition).isEqualTo(0f)
-        }
-    }
-
-    @Test
-    fun stretchOverscroll_whenPulledWithSmallDelta_doesNotConsumesOppositePreScroll_pullTop() {
-        val state = setStretchOverscrollContent(Orientation.Vertical)
-
-        rule.onNodeWithTag(OverscrollBox).performTouchInput {
-            down(center)
-            // Try and stretch by 0.4f
-            moveBy(Offset(0f, -0.4f))
-            // Pull 200 in the opposite direction - overscroll should have ignored the 0.4f, and
-            // so all 200 should be dispatched to the state with nothing being consumed
-            moveBy(Offset(0f, 200f))
-        }
-
-        rule.runOnIdle {
-            // All 200 should be dispatched directly to the state
-            assertThat(state.scrollPosition).isEqualTo(200f)
-        }
-    }
-
-    @Test
-    fun stretchOverscroll_whenPulled_consumesOppositePreScroll_pullRight() {
-        val state = setStretchOverscrollContent(Orientation.Horizontal)
-
-        rule.onNodeWithTag(OverscrollBox).performTouchInput {
-            down(center)
-            // Stretch by 200 (the max scroll value is 1000)
-            moveBy(Offset(1200f, 0f))
-            // Pull 200 in the opposite direction - because we had 200 pixels of stretch before,
-            // this should only relax the existing overscroll, and not dispatch anything to the
-            // state
-            moveBy(Offset(-200f, 0f))
-        }
-
-        rule.runOnIdle {
-            // All -200 should have been consumed by overscroll that was relaxing the existing
-            // stretch
-            assertThat(state.scrollPosition).isEqualTo(1000f)
-        }
-    }
-
-    @Test
-    fun stretchOverscroll_whenPulledWithSmallDelta_doesNotConsumesOppositePreScroll_pullRight() {
-        val state = setStretchOverscrollContent(Orientation.Horizontal)
-
-        rule.onNodeWithTag(OverscrollBox).performTouchInput {
-            down(center)
-            // Try and stretch by 0.4f (the max scroll value is 1000)
-            moveBy(Offset(1000.4f, 0f))
-            // Pull 200 in the opposite direction - overscroll should have ignored the 0.4f, and
-            // so all -200 should be dispatched to the state with nothing being consumed
-            moveBy(Offset(-200f, 0f))
-        }
-
-        rule.runOnIdle {
-            // All -200 should be dispatched directly to the state
-            assertThat(state.scrollPosition).isEqualTo(800f)
-        }
-    }
-
-    @Test
-    fun stretchOverscroll_whenPulled_consumesOppositePreScroll_pullBottom() {
-        val state = setStretchOverscrollContent(Orientation.Vertical)
-
-        rule.onNodeWithTag(OverscrollBox).performTouchInput {
-            down(center)
-            // Stretch by 200 (the max scroll value is 1000)
-            moveBy(Offset(0f, 1200f))
-            // Pull 200 in the opposite direction - because we had 200 pixels of stretch before,
-            // this should only relax the existing overscroll, and not dispatch anything to the
-            // state
-            moveBy(Offset(0f, -200f))
-        }
-
-        rule.runOnIdle {
-            // All -200 should have been consumed by overscroll that was relaxing the existing
-            // stretch
-            assertThat(state.scrollPosition).isEqualTo(1000f)
-        }
-    }
-
-    @Test
-    fun stretchOverscroll_whenPulledWithSmallDelta_doesNotConsumesOppositePreScroll_pullBottom() {
-        val state = setStretchOverscrollContent(Orientation.Vertical)
-
-        rule.onNodeWithTag(OverscrollBox).performTouchInput {
-            down(center)
-            // Try and stretch by 0.4f (the max scroll value is 1000)
-            moveBy(Offset(0f, 1000.4f))
-            // Pull 200 in the opposite direction - overscroll should have ignored the 0.4f, and
-            // so all -200 should be dispatched to the state with nothing being consumed
-            moveBy(Offset(0f, -200f))
-        }
-
-        rule.runOnIdle {
-            // All -200 should be dispatched directly to the state
-            assertThat(state.scrollPosition).isEqualTo(800f)
-        }
-    }
-
-    private fun setStretchOverscrollContent(orientation: Orientation): TestScrollableState {
-        animationScaleRule.setAnimationDurationScale(1f)
-        val state = TestScrollableState()
-        rule.setContent {
-            WithTouchSlop(touchSlop = 0f) {
-                val overscroll = ScrollableDefaults.overscrollEffect()
-                Box(
-                    Modifier.testTag(OverscrollBox)
-                        .size(100.dp)
-                        .scrollable(
-                            state = state,
-                            orientation = orientation,
-                            overscrollEffect = overscroll
-                        )
-                        .overscroll(overscroll)
-                )
-            }
-        }
-        return state
-    }
-}
-
-/** Returns a default [ScrollableState] with a [scrollPosition] clamped between 0f and 1000f. */
-private class TestScrollableState : ScrollableState {
-    var scrollPosition by mutableStateOf(0f)
-        private set
-
-    // Using ScrollableState here instead of ScrollState as ScrollState will automatically round to
-    // an int, and we need to assert floating point values
-    private val scrollableState = ScrollableState {
-        val newPosition = (scrollPosition + it).coerceIn(0f, 1000f)
-        val consumed = newPosition - scrollPosition
-        scrollPosition = newPosition
-        consumed
-    }
-
-    override suspend fun scroll(
-        scrollPriority: MutatePriority,
-        block: suspend ScrollScope.() -> Unit
-    ) = scrollableState.scroll(scrollPriority, block)
-
-    override fun dispatchRawDelta(delta: Float) = scrollableState.dispatchRawDelta(delta)
-
-    override val isScrollInProgress: Boolean
-        get() = scrollableState.isScrollInProgress
-}
-
-private const val OverscrollBox = "box"
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/gestures/snapping/SnapFlingBehaviorTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/gestures/snapping/SnapFlingBehaviorTest.kt
index f9f245d..c7f63dc 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/gestures/snapping/SnapFlingBehaviorTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/gestures/snapping/SnapFlingBehaviorTest.kt
@@ -181,6 +181,43 @@
     }
 
     @Test
+    fun performFling_invalidOffsets_shouldNotPropagateNans_calculateSnapOffset() {
+        val testLayoutInfoProvider =
+            object : SnapLayoutInfoProvider {
+                override fun calculateSnapOffset(velocity: Float): Float = Float.NaN
+            }
+        lateinit var testFlingBehavior: TargetedFlingBehavior
+        val exception =
+            kotlin.runCatching {
+                rule.setContent {
+                    testFlingBehavior = rememberSnapFlingBehavior(testLayoutInfoProvider)
+                    VelocityEffect(testFlingBehavior, TestVelocity)
+                }
+            }
+        assert(exception.isFailure)
+    }
+
+    @Test
+    fun performFling_invalidOffsets_shouldNotPropagateNans_calculateApproachOffset() {
+        val testLayoutInfoProvider =
+            object : SnapLayoutInfoProvider {
+                override fun calculateApproachOffset(velocity: Float, decayOffset: Float): Float =
+                    Float.NaN
+
+                override fun calculateSnapOffset(velocity: Float): Float = 0.0f
+            }
+        lateinit var testFlingBehavior: TargetedFlingBehavior
+        val exception =
+            kotlin.runCatching {
+                rule.setContent {
+                    testFlingBehavior = rememberSnapFlingBehavior(testLayoutInfoProvider)
+                    VelocityEffect(testFlingBehavior, TestVelocity)
+                }
+            }
+        assert(exception.isFailure)
+    }
+
+    @Test
     fun findClosestOffset_noFlingDirection_shouldReturnAbsoluteDistance() {
         val testLayoutInfoProvider = TestLayoutInfoProvider()
         val offset = testLayoutInfoProvider.calculateSnapOffset(0f)
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/BasicTextLinkTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/BasicTextLinkTest.kt
index 976902d..2050d0c 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/BasicTextLinkTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/BasicTextLinkTest.kt
@@ -25,6 +25,7 @@
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.layout.width
 import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.text.selection.fetchTextLayoutResult
 import androidx.compose.foundation.text.selection.gestures.util.longPress
 import androidx.compose.foundation.verticalScroll
 import androidx.compose.runtime.Composable
@@ -544,6 +545,40 @@
 
     @Test
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    fun link_onFocus_restoresOriginalStyle_afterFocusLost() {
+        val textWithLink = buildAnnotatedString {
+            withLink(
+                Url("link", TextLinkStyles(focusedStyle = SpanStyle(background = Color.Blue)))
+            ) {
+                append("text")
+            }
+        }
+        setupContent {
+            Column {
+                Box(Modifier.size(10.dp).focusable().testTag("box"))
+                BasicText(text = textWithLink, style = TextStyle(color = Color.White))
+            }
+        }
+
+        // link captures focus
+        rule
+            .onNode(hasClickAction(), useUnmergedTree = true)
+            .requestFocus()
+            .captureToImage()
+            .assertContainsColor(Color.Blue)
+
+        // link loses focus
+        rule.onNodeWithTag("box").requestFocus()
+
+        // verify link restores its unfocused style
+        rule
+            .onNode(hasClickAction(), useUnmergedTree = true)
+            .captureToImage()
+            .assertDoesNotContainColor(Color.Blue)
+    }
+
+    @Test
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
     fun link_withinOtherStyle_onFocus_focusedStyleUsed() {
         val textWithLink = buildAnnotatedString {
             withStyle(SpanStyle(color = Color.Green)) {
@@ -819,6 +854,40 @@
         }
     }
 
+    @Test
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    fun link_doesNotReplaceNestedStyle_whenEmptyStyle() {
+        val textWithLink = buildAnnotatedString {
+            withLink(Url("link", TextLinkStyles(focusedStyle = SpanStyle(Color.Blue)))) {
+                withStyle(SpanStyle(Color.Green)) { append("text") }
+            }
+        }
+        setupContent { BasicText(text = textWithLink, style = TextStyle(color = Color.White)) }
+
+        rule
+            .onNode(hasClickAction(), useUnmergedTree = true)
+            .captureToImage()
+            .assertDoesNotContainColor(Color.Blue)
+            .assertContainsColor(Color.Green)
+
+        rule
+            .onNode(hasClickAction(), useUnmergedTree = true)
+            .requestFocus()
+            .captureToImage()
+            .assertDoesNotContainColor(Color.Blue)
+            .assertContainsColor(Color.Green)
+    }
+
+    @Test
+    fun link_doesNotModifyAnnotations_whenEmptyStyles() {
+        val textWithLink = buildAnnotatedString { withLink(Url("link")) { append("text") } }
+        setupContent { BasicText(text = textWithLink, style = TextStyle(color = Color.White)) }
+
+        val styles = rule.onNodeWithText("text").fetchTextLayoutResult().layoutInput.text.spanStyles
+
+        assertThat(styles).isEmpty()
+    }
+
     @Composable
     private fun TextWithLinks() =
         with(rule.density) {
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/BasicTextScreenshotTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/BasicTextScreenshotTest.kt
index c5820cf..855071a 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/BasicTextScreenshotTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/BasicTextScreenshotTest.kt
@@ -17,7 +17,7 @@
 package androidx.compose.foundation.text
 
 import android.os.Build
-import androidx.compose.foundation.GOLDEN_UI
+import androidx.compose.foundation.GOLDEN_FOUNDATION
 import androidx.compose.testutils.assertAgainstGolden
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.testTag
@@ -45,7 +45,7 @@
 class BasicTextScreenshotTest {
     @get:Rule val rule = createComposeRule()
 
-    @get:Rule val screenshotRule = AndroidXScreenshotTestRule(GOLDEN_UI)
+    @get:Rule val screenshotRule = AndroidXScreenshotTestRule(GOLDEN_FOUNDATION)
 
     private val textTag = "text"
 
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/CoreTextFieldHandwritingBoundsTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/CoreTextFieldHandwritingBoundsTest.kt
index 0dcf7fe..f5b5060 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/CoreTextFieldHandwritingBoundsTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/CoreTextFieldHandwritingBoundsTest.kt
@@ -19,12 +19,10 @@
 import android.view.inputmethod.CursorAnchorInfo
 import android.view.inputmethod.ExtractedText
 import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.safeContentPadding
 import androidx.compose.foundation.setFocusableContent
-import androidx.compose.foundation.text.handwriting.HandwritingBoundsVerticalOffset
 import androidx.compose.foundation.text.handwriting.isStylusHandwritingSupported
 import androidx.compose.foundation.text.input.InputMethodInterceptor
 import androidx.compose.foundation.text.input.internal.InputMethodManager
@@ -40,8 +38,8 @@
 import androidx.compose.ui.test.assertIsFocused
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.test.onNodeWithTag
-import androidx.compose.ui.test.requestFocus
 import androidx.compose.ui.text.input.TextFieldValue
+import androidx.compose.ui.unit.dp
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
 import com.google.common.truth.Truth.assertThat
@@ -122,48 +120,6 @@
         fakeImm.expectStylusHandwriting(true)
     }
 
-    @Test
-    fun coreTextField_stylusPointerInOverlappingArea_focusedEditorStartHandwriting() {
-        inputMethodManagerFactory = { fakeImm }
-
-        val editorTag1 = "CoreTextField1"
-        val editorTag2 = "CoreTextField2"
-        val spacerTag = "Spacer"
-
-        setContent {
-            Column(Modifier.safeContentPadding()) {
-                EditLine(Modifier.testTag(editorTag1))
-                Spacer(
-                    modifier =
-                        Modifier.fillMaxWidth()
-                            .height(HandwritingBoundsVerticalOffset)
-                            .testTag(spacerTag)
-                )
-                EditLine(Modifier.testTag(editorTag2))
-            }
-        }
-
-        rule.onNodeWithTag(editorTag2).requestFocus()
-        rule.waitForIdle()
-
-        // Spacer's height equals to HandwritingBoundsVerticalPadding, both editor will receive the
-        // event.
-        rule.onNodeWithTag(spacerTag).performStylusHandwriting()
-        rule.waitForIdle()
-
-        // Assert that focus didn't change, handwriting is started on the focused editor 2.
-        rule.onNodeWithTag(editorTag2).assertIsFocused()
-        fakeImm.expectStylusHandwriting(true)
-
-        rule.onNodeWithTag(editorTag1).requestFocus()
-        rule.onNodeWithTag(spacerTag).performStylusHandwriting()
-        rule.waitForIdle()
-
-        // Now handwriting is performed on the focused editor 1.
-        rule.onNodeWithTag(editorTag1).assertIsFocused()
-        fakeImm.expectStylusHandwriting(true)
-    }
-
     @Composable
     fun EditLine(modifier: Modifier = Modifier) {
         var value by remember { mutableStateOf(TextFieldValue()) }
@@ -175,7 +131,7 @@
                     .fillMaxWidth()
                     // make the size of TextFields equal to padding, so that touch bounds of editors
                     // in the same column/row are overlapping.
-                    .height(HandwritingBoundsVerticalOffset)
+                    .height(40.dp)
         )
     }
 
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/CoreTextFieldHandwritingTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/CoreTextFieldHandwritingTest.kt
index 07de86e..c8cc949 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/CoreTextFieldHandwritingTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/CoreTextFieldHandwritingTest.kt
@@ -219,10 +219,7 @@
 
         focusWindow.value = false
         rule.waitForIdle()
-        performHandwritingAndExpect(stylusHandwritingStarted = false)
-
-        focusWindow.value = true
-        rule.waitForIdle()
+        // only losing window focus does not stop the ongoing input session
         performHandwritingAndExpect(stylusHandwritingStarted = true)
     }
 
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/CoreTextFieldInputServiceIntegrationTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/CoreTextFieldInputServiceIntegrationTest.kt
index 4f6b65f..18afddd 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/CoreTextFieldInputServiceIntegrationTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/CoreTextFieldInputServiceIntegrationTest.kt
@@ -502,7 +502,7 @@
     }
 
     @Test
-    fun textField_stopAndStartInput_whenToggleWindowFocus() {
+    fun textField_onlyStartsInputConnection_whenToggleWindowFocus() {
         val value = TextFieldValue("abc")
         val focusRequester = FocusRequester()
 
@@ -525,13 +525,24 @@
 
         rule.runOnUiThread { focusRequester.requestFocus() }
 
-        rule.runOnIdle { inputMethodInterceptor.assertSessionActive() }
+        var firstInputConnection: InputConnection? = null
+        rule.runOnIdle {
+            inputMethodInterceptor.assertSessionActive()
+            inputMethodInterceptor.withInputConnection { firstInputConnection = this }
+        }
 
         focusWindow.value = false
-        rule.runOnIdle { inputMethodInterceptor.assertNoSessionActive() }
+        rule.runOnIdle { inputMethodInterceptor.assertSessionActive() }
 
         focusWindow.value = true
-        rule.runOnIdle { inputMethodInterceptor.assertSessionActive() }
+        var secondInputConnection: InputConnection? = null
+        rule.runOnIdle {
+            inputMethodInterceptor.assertSessionActive()
+            inputMethodInterceptor.withInputConnection { secondInputConnection = this }
+        }
+
+        // check that we have not created a separate input connection
+        assertThat(firstInputConnection).isSameInstanceAs(secondInputConnection)
     }
 
     private fun setContent(
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/FontScalingScreenshotTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/FontScalingScreenshotTest.kt
index 01ddcd8..427d031 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/FontScalingScreenshotTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/FontScalingScreenshotTest.kt
@@ -19,7 +19,7 @@
 import android.os.Build
 import androidx.activity.ComponentActivity
 import androidx.compose.foundation.Canvas
-import androidx.compose.foundation.GOLDEN_UI
+import androidx.compose.foundation.GOLDEN_FOUNDATION
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.runtime.Composable
@@ -59,7 +59,7 @@
 class FontScalingScreenshotTest {
     @get:Rule val rule = createAndroidComposeRule<ComponentActivity>()
 
-    @get:Rule val screenshotRule = AndroidXScreenshotTestRule(GOLDEN_UI)
+    @get:Rule val screenshotRule = AndroidXScreenshotTestRule(GOLDEN_FOUNDATION)
 
     private val containerTag = "container"
 
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/MinLinesMemoryLeakTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/MinLinesMemoryLeakTest.kt
new file mode 100644
index 0000000..186687e
--- /dev/null
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/MinLinesMemoryLeakTest.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.foundation.text
+
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.test.filters.LargeTest
+import leakcanary.DetectLeaksAfterTestSuccess
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.RuleChain
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+@LargeTest
+class MinLinesMemoryLeakTest(private val numLines: Int) {
+    companion object {
+        @JvmStatic
+        @Parameterized.Parameters
+        fun data() = arrayOf(1, 2, 100) // potential when numLines greater than 1
+    }
+
+    private val composeTestRule = createComposeRule()
+
+    @get:Rule
+    val ruleChain: RuleChain =
+        RuleChain.outerRule(DetectLeaksAfterTestSuccess()).around(composeTestRule)
+
+    @Test
+    fun MinLinesMemoryLeakTest() {
+        composeTestRule.setContent {
+            BasicText(
+                text = "Lorem ipsum dolor sit amet.",
+                minLines = numLines, // Set this to a non-default value (potential leak)
+            )
+        }
+        composeTestRule.waitForIdle()
+    }
+}
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/input/HandwritingDetectorTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/input/HandwritingDetectorTest.kt
index bdc32865..3a2502f 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/input/HandwritingDetectorTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/input/HandwritingDetectorTest.kt
@@ -21,7 +21,6 @@
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.safeContentPadding
-import androidx.compose.foundation.text.handwriting.HandwritingBoundsVerticalOffset
 import androidx.compose.foundation.text.handwriting.handwritingDetector
 import androidx.compose.foundation.text.handwriting.isStylusHandwritingSupported
 import androidx.compose.foundation.text.performStylusClick
@@ -32,11 +31,13 @@
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.unit.dp
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
 import com.google.common.truth.Truth.assertThat
 import org.junit.Assume
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -70,24 +71,14 @@
                 Spacer(
                     modifier =
                         Modifier.fillMaxWidth()
-                            .height(HandwritingBoundsVerticalOffset)
+                            .height(40.dp)
                             .handwritingDetector { callbackCount++ }
                             .testTag(detectorTag)
                 )
                 // This spacer is within the extended handwriting bounds of the detector
-                Spacer(
-                    modifier =
-                        Modifier.fillMaxWidth()
-                            .height(HandwritingBoundsVerticalOffset)
-                            .testTag(insideSpacerTag)
-                )
+                Spacer(modifier = Modifier.fillMaxWidth().height(10.dp).testTag(insideSpacerTag))
                 // This spacer is outside the extended handwriting bounds of the detector
-                Spacer(
-                    modifier =
-                        Modifier.fillMaxWidth()
-                            .height(HandwritingBoundsVerticalOffset)
-                            .testTag(outsideSpacerTag)
-                )
+                Spacer(modifier = Modifier.fillMaxWidth().height(10.dp).testTag(outsideSpacerTag))
             }
         }
     }
@@ -99,7 +90,10 @@
         assertHandwritingDelegationPrepared()
     }
 
+    // Extended bounds is reverted due to b/346850837 will enable it when we support extended
+    // bounds for handwriting again.
     @Test
+    @Ignore
     fun detector_handwritingInExtendedBounds_preparesDelegation() {
         // This spacer is within the extended handwriting bounds of the detector
         rule.onNodeWithTag(insideSpacerTag).performStylusHandwriting()
@@ -108,6 +102,7 @@
     }
 
     @Test
+    @Ignore
     fun detector_handwritingOutsideExtendedBounds_notPreparesDelegation() {
         // This spacer is outside the extended handwriting bounds of the detector
         rule.onNodeWithTag(outsideSpacerTag).performStylusHandwriting()
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/selection/TextSelectionColorsScreenshotTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/selection/TextSelectionColorsScreenshotTest.kt
index 4981d6f..42f8e7d 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/selection/TextSelectionColorsScreenshotTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/selection/TextSelectionColorsScreenshotTest.kt
@@ -17,7 +17,7 @@
 package androidx.compose.foundation.text.selection
 
 import android.os.Build
-import androidx.compose.foundation.GOLDEN_UI
+import androidx.compose.foundation.GOLDEN_FOUNDATION
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Row
@@ -60,7 +60,7 @@
 
     @get:Rule val rule = createComposeRule()
 
-    @get:Rule val screenshotRule = AndroidXScreenshotTestRule(GOLDEN_UI)
+    @get:Rule val screenshotRule = AndroidXScreenshotTestRule(GOLDEN_FOUNDATION)
 
     @Test
     fun text_defaultSelectionColors() {
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/textfield/TextFieldTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/textfield/TextFieldTest.kt
index 0caba94..ea33294 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/textfield/TextFieldTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/textfield/TextFieldTest.kt
@@ -78,8 +78,10 @@
 import androidx.compose.ui.platform.LocalFontFamilyResolver
 import androidx.compose.ui.platform.LocalLayoutDirection
 import androidx.compose.ui.platform.LocalTextToolbar
+import androidx.compose.ui.platform.LocalWindowInfo
 import androidx.compose.ui.platform.TextToolbar
 import androidx.compose.ui.platform.TextToolbarStatus
+import androidx.compose.ui.platform.WindowInfo
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.semantics.SemanticsActions
 import androidx.compose.ui.semantics.SemanticsProperties
@@ -1534,6 +1536,25 @@
 
         assertThat(tfvState.value.selection).isEqualTo(TextRange(targetOffset))
     }
+
+    @Test
+    fun doesNotStopBeingTextEditor_whenWindowFocusLost() {
+        var windowFocus by mutableStateOf(true)
+        inputMethodInterceptor.setContent {
+            CompositionLocalProvider(
+                LocalWindowInfo provides
+                    object : WindowInfo {
+                        override val isWindowFocused: Boolean
+                            get() = windowFocus
+                    }
+            ) {
+                BasicTextField("", {}, Modifier.testTag(Tag))
+            }
+        }
+        rule.onNodeWithTag(Tag).requestFocus()
+        rule.runOnIdle { windowFocus = false }
+        inputMethodInterceptor.assertSessionActive()
+    }
 }
 
 private fun SemanticsNodeInteraction.assertEditableTextEquals(
diff --git a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/AndroidOverscroll.android.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/AndroidOverscroll.android.kt
index 5207e43..d81a8c5 100644
--- a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/AndroidOverscroll.android.kt
+++ b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/AndroidOverscroll.android.kt
@@ -23,6 +23,7 @@
 import androidx.annotation.ColorInt
 import androidx.annotation.RequiresApi
 import androidx.annotation.VisibleForTesting
+import androidx.compose.foundation.EdgeEffectCompat.absorbToRelaxIfNeeded
 import androidx.compose.foundation.EdgeEffectCompat.distanceCompat
 import androidx.compose.foundation.EdgeEffectCompat.onAbsorbCompat
 import androidx.compose.foundation.EdgeEffectCompat.onPullDistanceCompat
@@ -52,7 +53,9 @@
 import androidx.compose.ui.platform.InspectorInfo
 import androidx.compose.ui.platform.InspectorValueInfo
 import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.platform.debugInspectorInfo
+import androidx.compose.ui.unit.Density
 import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.unit.Velocity
 import androidx.compose.ui.util.fastFilter
@@ -62,9 +65,12 @@
 @Composable
 internal actual fun rememberOverscrollEffect(): OverscrollEffect {
     val context = LocalContext.current
+    val density = LocalDensity.current
     val config = LocalOverscrollConfiguration.current
     return if (config != null) {
-        remember(context, config) { AndroidEdgeEffectOverscrollEffect(context, config) }
+        remember(context, density, config) {
+            AndroidEdgeEffectOverscrollEffect(context, density, config)
+        }
     } else {
         NoOpOverscrollEffect
     }
@@ -421,6 +427,7 @@
 
 internal class AndroidEdgeEffectOverscrollEffect(
     context: Context,
+    private val density: Density,
     overscrollConfig: OverscrollConfiguration
 ) : OverscrollEffect {
     private var pointerPosition: Offset? = null
@@ -445,49 +452,72 @@
         }
 
         if (!scrollCycleInProgress) {
-            stopOverscrollAnimation()
+            // We are starting a new scroll cycle: if there is an active stretch, we want to
+            // 'catch' it at its current point so that the user continues to manipulate the stretch
+            // with this new scroll, instead of letting the old stretch fade away underneath the
+            // user's input. To do this we pull with 0 offset, to put the stretch back into a
+            // 'pull' state, without changing its distance.
+            if (edgeEffectWrapper.isLeftStretched()) pullLeft(Offset.Zero)
+            if (edgeEffectWrapper.isRightStretched()) pullRight(Offset.Zero)
+            if (edgeEffectWrapper.isTopStretched()) pullTop(Offset.Zero)
+            if (edgeEffectWrapper.isBottomStretched()) pullBottom(Offset.Zero)
             scrollCycleInProgress = true
         }
-        // Relax existing stretches if needed before performing scroll
+        // Relax existing stretches if needed before performing scroll. If this is happening inside
+        // a fling, we relax faster than normal.
+        val destretchMultiplier = destretchMultiplier(source)
+        val destretchDelta = delta * destretchMultiplier
         val consumedPixelsY =
             when {
                 delta.y == 0f -> 0f
-                edgeEffectWrapper.isTopStretched() -> {
-                    pullTop(delta).also {
-                        // Release / reset state if we have fully relaxed the stretch
-                        if (!edgeEffectWrapper.isTopStretched()) {
-                            edgeEffectWrapper.getOrCreateTopEffect().onRelease()
+                edgeEffectWrapper.isTopStretched() && delta.y < 0f -> {
+                    val consumed =
+                        pullTop(destretchDelta).also {
+                            // Reset state if we have fully relaxed the stretch
+                            if (!edgeEffectWrapper.isTopStretched()) {
+                                edgeEffectWrapper.getOrCreateTopEffect().finish()
+                            }
                         }
-                    }
+                    // Avoid rounding / float errors from dividing if all the delta was consumed
+                    if (consumed == destretchDelta.y) delta.y else consumed / destretchMultiplier
                 }
-                edgeEffectWrapper.isBottomStretched() -> {
-                    pullBottom(delta).also {
-                        // Release / reset state if we have fully relaxed the stretch
-                        if (!edgeEffectWrapper.isBottomStretched()) {
-                            edgeEffectWrapper.getOrCreateBottomEffect().onRelease()
+                edgeEffectWrapper.isBottomStretched() && delta.y > 0f -> {
+                    val consumed =
+                        pullBottom(destretchDelta).also {
+                            // Reset state if we have fully relaxed the stretch
+                            if (!edgeEffectWrapper.isBottomStretched()) {
+                                edgeEffectWrapper.getOrCreateBottomEffect().finish()
+                            }
                         }
-                    }
+                    // Avoid rounding / float errors from dividing if all the delta was consumed
+                    if (consumed == destretchDelta.y) delta.y else consumed / destretchMultiplier
                 }
                 else -> 0f
             }
         val consumedPixelsX =
             when {
                 delta.x == 0f -> 0f
-                edgeEffectWrapper.isLeftStretched() -> {
-                    pullLeft(delta).also {
-                        // Release / reset state if we have fully relaxed the stretch
-                        if (!edgeEffectWrapper.isLeftStretched()) {
-                            edgeEffectWrapper.getOrCreateLeftEffect().onRelease()
+                edgeEffectWrapper.isLeftStretched() && delta.x < 0f -> {
+                    val consumed =
+                        pullLeft(destretchDelta).also {
+                            // Reset state if we have fully relaxed the stretch
+                            if (!edgeEffectWrapper.isLeftStretched()) {
+                                edgeEffectWrapper.getOrCreateLeftEffect().finish()
+                            }
                         }
-                    }
+                    // Avoid rounding / float errors from dividing if all the delta was consumed
+                    if (consumed == destretchDelta.x) delta.x else consumed / destretchMultiplier
                 }
-                edgeEffectWrapper.isRightStretched() -> {
-                    pullRight(delta).also {
-                        // Release / reset state if we have fully relaxed the stretch
-                        if (!edgeEffectWrapper.isRightStretched()) {
-                            edgeEffectWrapper.getOrCreateRightEffect().onRelease()
+                edgeEffectWrapper.isRightStretched() && delta.x > 0f -> {
+                    val consumed =
+                        pullRight(destretchDelta).also {
+                            // Reset state if we have fully relaxed the stretch
+                            if (!edgeEffectWrapper.isRightStretched()) {
+                                edgeEffectWrapper.getOrCreateRightEffect().finish()
+                            }
                         }
-                    }
+                    // Avoid rounding / float errors from dividing if all the delta was consumed
+                    if (consumed == destretchDelta.x) delta.x else consumed / destretchMultiplier
                 }
                 else -> 0f
             }
@@ -524,7 +554,14 @@
                 }
             needsInvalidation = appliedHorizontalOverscroll || appliedVerticalOverscroll
         }
-        needsInvalidation = releaseOppositeOverscroll(delta) || needsInvalidation
+
+        // If we have leftover delta (overscroll didn't consume), release any glow effects in the
+        // opposite direction. This is only relevant for glow, as stretch effects will relax in
+        // pre-scroll, hence we check leftForDelta - this will be zero if the stretch effect is
+        // consuming in pre-scroll.
+        if (leftForDelta != Offset.Zero) {
+            needsInvalidation = releaseOppositeOverscroll(delta) || needsInvalidation
+        }
         if (needsInvalidation) invalidateOverscroll()
 
         return consumedOffset + consumedByDelta
@@ -541,22 +578,26 @@
         }
         // Relax existing stretches before performing fling
         val consumedX =
-            if (velocity.x > 0f && edgeEffectWrapper.isLeftStretched()) {
-                edgeEffectWrapper.getOrCreateLeftEffect().onAbsorbCompat(velocity.x.roundToInt())
-                velocity.x
-            } else if (velocity.x < 0 && edgeEffectWrapper.isRightStretched()) {
-                edgeEffectWrapper.getOrCreateRightEffect().onAbsorbCompat(-velocity.x.roundToInt())
-                velocity.x
+            if (edgeEffectWrapper.isLeftStretched() && velocity.x < 0f) {
+                edgeEffectWrapper
+                    .getOrCreateLeftEffect()
+                    .absorbToRelaxIfNeeded(velocity.x, containerSize.width, density)
+            } else if (edgeEffectWrapper.isRightStretched() && velocity.x > 0f) {
+                -edgeEffectWrapper
+                    .getOrCreateRightEffect()
+                    .absorbToRelaxIfNeeded(-velocity.x, containerSize.width, density)
             } else {
                 0f
             }
         val consumedY =
-            if (velocity.y > 0f && edgeEffectWrapper.isTopStretched()) {
-                edgeEffectWrapper.getOrCreateTopEffect().onAbsorbCompat(velocity.y.roundToInt())
-                velocity.y
-            } else if (velocity.y < 0f && edgeEffectWrapper.isBottomStretched()) {
-                edgeEffectWrapper.getOrCreateBottomEffect().onAbsorbCompat(-velocity.y.roundToInt())
-                velocity.y
+            if (edgeEffectWrapper.isTopStretched() && velocity.y < 0f) {
+                edgeEffectWrapper
+                    .getOrCreateTopEffect()
+                    .absorbToRelaxIfNeeded(velocity.y, containerSize.height, density)
+            } else if (edgeEffectWrapper.isBottomStretched() && velocity.y > 0f) {
+                -edgeEffectWrapper
+                    .getOrCreateBottomEffect()
+                    .absorbToRelaxIfNeeded(-velocity.y, containerSize.height, density)
             } else {
                 0f
             }
@@ -568,6 +609,7 @@
         val leftForOverscroll = remainingVelocity - consumedByVelocity
 
         scrollCycleInProgress = false
+        // Stretch with any leftover velocity
         if (leftForOverscroll.x > 0) {
             edgeEffectWrapper
                 .getOrCreateLeftEffect()
@@ -586,8 +628,12 @@
                 .getOrCreateBottomEffect()
                 .onAbsorbCompat(-leftForOverscroll.y.roundToInt())
         }
-        if (leftForOverscroll != Velocity.Zero) invalidateOverscroll()
-        animateToRelease()
+        // Release any remaining effects, and invalidate if needed.
+        // For stretch this should only have an effect when velocity is exactly 0, since then the
+        // effects above will not be absorbed.
+        // For glow we don't absorb if we are already showing a glow from a drag
+        // (see onAbsorbCompat), so we need to manually release in this case as well.
+        animateToReleaseIfNeeded()
     }
 
     private var containerSize = Size.Zero
@@ -598,28 +644,6 @@
             return false
         }
 
-    private fun stopOverscrollAnimation(): Boolean {
-        var stopped = false
-        // Displacement doesn't matter here
-        if (edgeEffectWrapper.isLeftStretched()) {
-            pullLeft(Offset.Zero)
-            stopped = true
-        }
-        if (edgeEffectWrapper.isRightStretched()) {
-            pullRight(Offset.Zero)
-            stopped = true
-        }
-        if (edgeEffectWrapper.isTopStretched()) {
-            pullTop(Offset.Zero)
-            stopped = true
-        }
-        if (edgeEffectWrapper.isBottomStretched()) {
-            pullBottom(Offset.Zero)
-            stopped = true
-        }
-        return stopped
-    }
-
     internal fun updateSize(size: Size) {
         val initialSetSize = containerSize == Size.Zero
         val differentSize = size != containerSize
@@ -628,8 +652,7 @@
             edgeEffectWrapper.setSize(IntSize(size.width.roundToInt(), size.height.roundToInt()))
         }
         if (!initialSetSize && differentSize) {
-            invalidateOverscroll()
-            animateToRelease()
+            animateToReleaseIfNeeded()
         }
     }
 
@@ -696,33 +719,43 @@
         }
     }
 
-    // animate the edge effects to 0 (no overscroll). Usually needed when the finger is up.
-    private fun animateToRelease() {
+    /**
+     * Animate any pulled edge effects to 0 / resets overscroll. If an edge effect is already
+     * receding, onRelease will no-op. Invalidates any still active edge effects.
+     */
+    private fun animateToReleaseIfNeeded() {
         var needsInvalidation = false
         edgeEffectWrapper.forEachEffect {
             it.onRelease()
-            needsInvalidation = it.isFinished || needsInvalidation
+            needsInvalidation = !it.isFinished || needsInvalidation
         }
         if (needsInvalidation) invalidateOverscroll()
     }
 
+    /**
+     * Releases overscroll effects in the opposite direction to the current scroll [delta]. E.g.,
+     * when scrolling down, the top glow will show - if the user starts to scroll up, we need to
+     * release the existing top glow as we are no longer overscrolling in that direction.
+     *
+     * @return whether invalidation is needed (we released an animating edge effect)
+     */
     private fun releaseOppositeOverscroll(delta: Offset): Boolean {
         var needsInvalidation = false
         if (edgeEffectWrapper.isLeftAnimating() && delta.x < 0) {
             edgeEffectWrapper.getOrCreateLeftEffect().onReleaseWithOppositeDelta(delta = delta.x)
-            needsInvalidation = !edgeEffectWrapper.isLeftAnimating()
+            needsInvalidation = edgeEffectWrapper.isLeftAnimating()
         }
         if (edgeEffectWrapper.isRightAnimating() && delta.x > 0) {
             edgeEffectWrapper.getOrCreateRightEffect().onReleaseWithOppositeDelta(delta = delta.x)
-            needsInvalidation = needsInvalidation || !edgeEffectWrapper.isRightAnimating()
+            needsInvalidation = needsInvalidation || edgeEffectWrapper.isRightAnimating()
         }
         if (edgeEffectWrapper.isTopAnimating() && delta.y < 0) {
             edgeEffectWrapper.getOrCreateTopEffect().onReleaseWithOppositeDelta(delta = delta.y)
-            needsInvalidation = needsInvalidation || !edgeEffectWrapper.isTopAnimating()
+            needsInvalidation = needsInvalidation || edgeEffectWrapper.isTopAnimating()
         }
         if (edgeEffectWrapper.isBottomAnimating() && delta.y > 0) {
             edgeEffectWrapper.getOrCreateBottomEffect().onReleaseWithOppositeDelta(delta = delta.y)
-            needsInvalidation = needsInvalidation || !edgeEffectWrapper.isBottomAnimating()
+            needsInvalidation = needsInvalidation || edgeEffectWrapper.isBottomAnimating()
         }
         return needsInvalidation
     }
@@ -892,3 +925,18 @@
         rightEffectNegation?.setSize(size.height, size.width)
     }
 }
+
+/**
+ * When we are destretching inside a scroll that is caused by a fling
+ * ([NestedScrollSource.SideEffect]), we want to destretch quicker than normal. See
+ * [FlingDestretchFactor].
+ */
+private fun destretchMultiplier(source: NestedScrollSource): Float =
+    if (source == NestedScrollSource.SideEffect) FlingDestretchFactor else 1f
+
+/**
+ * When flinging the stretch towards scrolling content, it should destretch quicker than the fling
+ * would normally do. The visual effect of flinging the stretch looks strange as little appears to
+ * happen at first and then when the stretch disappears, the content starts scrolling quickly.
+ */
+private const val FlingDestretchFactor = 4f
diff --git a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/EdgeEffectCompat.android.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/EdgeEffectCompat.android.kt
index 7aadd3f..f078ec9 100644
--- a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/EdgeEffectCompat.android.kt
+++ b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/EdgeEffectCompat.android.kt
@@ -19,12 +19,16 @@
 import android.content.Context
 import android.os.Build
 import android.util.AttributeSet
+import android.view.ViewConfiguration
 import android.widget.EdgeEffect
 import androidx.annotation.DoNotInline
 import androidx.annotation.RequiresApi
 import androidx.compose.ui.unit.Density
 import androidx.compose.ui.unit.dp
 import kotlin.math.abs
+import kotlin.math.exp
+import kotlin.math.ln
+import kotlin.math.roundToInt
 
 internal object EdgeEffectCompat {
 
@@ -47,12 +51,45 @@
     fun EdgeEffect.onAbsorbCompat(velocity: Int) {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
             return this.onAbsorb(velocity)
-        } else if (this.isFinished) { // only absorb the glow effect if it is not active (finished)
+        } else if (this.isFinished) {
+            // Only absorb the glow effect if it is not active (finished) - dragging to start a glow
+            // and then releasing shouldn't add to the existing glow, it should just decay.
             this.onAbsorb(velocity)
         }
     }
 
     /**
+     * When relaxing a stretch with velocity (fling), if the velocity would fully relax the stretch
+     * with some remaining velocity, instead of absorbing we want to propagate the velocity and
+     * relax the overscroll as part of scroll, called within the fling - so for this case we do
+     * nothing and consume no velocity.
+     *
+     * If the velocity is not enough to fully relax the stretch, then we absorb it and consume all
+     * the velocity.
+     *
+     * @param velocity to absorb if needed
+     * @param edgeEffectLength the main axis bounds for this edge effect, needed to transform the
+     *   relative distance from [distanceCompat] into the absolute distance
+     * @return how much velocity was consumed
+     */
+    fun EdgeEffect.absorbToRelaxIfNeeded(
+        velocity: Float,
+        edgeEffectLength: Float,
+        density: Density
+    ): Float {
+        val flingDistance = flingDistance(density, velocity)
+        val actualDistance = distanceCompat * edgeEffectLength
+        return if (flingDistance <= actualDistance) {
+            onAbsorbCompat(velocity.roundToInt())
+            // Consume all velocity when absorbing
+            velocity
+        } else {
+            // Consume nothing, we will relax the stretch in applyToScroll
+            0f
+        }
+    }
+
+    /**
      * Used for calls to [EdgeEffect.onRelease] that happen because of scroll delta in the opposite
      * direction to the overscroll. See [GlowEdgeEffectCompat].
      */
@@ -147,3 +184,28 @@
         }
     }
 }
+
+// These constants are copied from the Android spline decay rate
+private const val Inflection = 0.35f // Tension lines cross at (Inflection, 1)
+private val PlatformFlingScrollFriction = ViewConfiguration.getScrollFriction()
+private const val GravityEarth = 9.80665f
+private const val InchesPerMeter = 39.37f
+private val DecelerationRate = ln(0.78) / ln(0.9)
+private val DecelMinusOne = DecelerationRate - 1.0
+
+/**
+ * Copied from OverScroller, this returns the distance that a fling with the given velocity will go.
+ *
+ * @return The absolute distance that will be traveled by a fling of the given velocity
+ */
+private fun flingDistance(density: Density, velocity: Float): Float {
+    val magicPhysicalCoefficient =
+        (GravityEarth * InchesPerMeter * density.density * 160f * 0.84f).toDouble()
+    val l =
+        ln(Inflection * abs(velocity) / (PlatformFlingScrollFriction * magicPhysicalCoefficient))
+    val distance =
+        PlatformFlingScrollFriction *
+            magicPhysicalCoefficient *
+            exp(DecelerationRate / DecelMinusOne * l)
+    return distance.toFloat()
+}
diff --git a/compose/foundation/foundation/src/androidUnitTest/kotlin/androidx/compose/foundation/gestures/DraggableAnchorsTest.kt b/compose/foundation/foundation/src/androidUnitTest/kotlin/androidx/compose/foundation/gestures/DraggableAnchorsTest.kt
index dbe355f..a636fb7 100644
--- a/compose/foundation/foundation/src/androidUnitTest/kotlin/androidx/compose/foundation/gestures/DraggableAnchorsTest.kt
+++ b/compose/foundation/foundation/src/androidUnitTest/kotlin/androidx/compose/foundation/gestures/DraggableAnchorsTest.kt
@@ -91,6 +91,26 @@
         assertThat(anchors.positionOf(A)).isEqualTo(100f)
         assertThat(anchors.hasPositionFor(A)).isTrue()
     }
+
+    @Test
+    fun draggableAnchors_equality_equalAnchors() {
+        val anchors1 = DraggableAnchors { A at 100f }
+        val anchors2 = DraggableAnchors { A at 100f }
+        assertThat(anchors1).isEqualTo(anchors2)
+    }
+
+    @Test
+    fun draggableAnchors_equality_inequalAnchors() {
+        val anchors1 = DraggableAnchors { A at 100f }
+        val anchors2 = DraggableAnchors { B at 100f }
+        assertThat(anchors1).isNotEqualTo(anchors2)
+    }
+
+    @Test
+    fun draggableAnchors_equality_differentObject() {
+        val anchors = DraggableAnchors { A at 100f }
+        assertThat(anchors).isNotEqualTo("Test")
+    }
 }
 
 private enum class TestValue {
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/AnchoredDraggable.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/AnchoredDraggable.kt
index 9d6d74a..5ddc1e0 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/AnchoredDraggable.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/AnchoredDraggable.kt
@@ -540,7 +540,7 @@
  */
 interface DraggableAnchors<T> {
 
-    /** The amount of anchors */
+    /** The number of anchors */
     val size: Int
 
     /**
@@ -576,10 +576,10 @@
      */
     fun closestAnchor(position: Float, searchUpwards: Boolean): T?
 
-    /** The smallest anchor, or [Float.NEGATIVE_INFINITY] if the anchors are empty. */
+    /** The smallest anchor position, or [Float.NEGATIVE_INFINITY] if the anchors are empty. */
     fun minPosition(): Float
 
-    /** The biggest anchor, or [Float.POSITIVE_INFINITY] if the anchors are empty. */
+    /** The biggest anchor position, or [Float.POSITIVE_INFINITY] if the anchors are empty. */
     fun maxPosition(): Float
 
     /** Get the anchor key at the specified index, or null if the index is out of bounds. */
@@ -1310,7 +1310,7 @@
  * updated ro the [targetValue] without updating the offset.
  *
  * @param targetValue The target value of the animation
- * @param velocity The velocity the animation should start with
+ * @param velocity The velocity the animation should start with, in px/s
  * @param snapAnimationSpec The animation spec used if the velocity is not high enough to perform a
  *   decay to the [targetValue] using the [decayAnimationSpec]
  * @param decayAnimationSpec The animation spec used if the velocity is high enough to perform a
@@ -1580,7 +1580,7 @@
     override fun equals(other: Any?): Boolean {
         if (this === other) return true
 
-        other as DefaultDraggableAnchors<*>
+        if (other !is DefaultDraggableAnchors<*>) return false
 
         if (keys != other.keys) return false
         if (!anchors.contentEquals(other.anchors)) return false
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/snapping/PagerSnapLayoutInfoProvider.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/snapping/PagerSnapLayoutInfoProvider.kt
index deac658..1f7188c 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/snapping/PagerSnapLayoutInfoProvider.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/snapping/PagerSnapLayoutInfoProvider.kt
@@ -69,6 +69,9 @@
             debugLog { "Approach Velocity=$velocity" }
             val effectivePageSizePx = pagerState.pageSize + pagerState.pageSpacing
 
+            // Page Size is Zero, do not proceed.
+            if (effectivePageSizePx == 0) return 0f
+
             // given this velocity, where can I go with a decay animation.
             val animationOffsetPx = decayOffset
 
@@ -244,8 +247,13 @@
             "layoutDirection=$layoutDirection"
     }
     // how many pages have I scrolled using a drag gesture.
+    val pageSize = pagerState.layoutInfo.pageSize
     val offsetFromSnappedPosition =
-        pagerState.dragGestureDelta() / pagerState.layoutInfo.pageSize.toFloat()
+        if (pageSize == 0) {
+            0f
+        } else {
+            pagerState.dragGestureDelta() / pageSize.toFloat()
+        }
 
     // we're only interested in the decimal part of the offset.
     val offsetFromSnappedPositionOverflow =
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/snapping/SnapFlingBehavior.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/snapping/SnapFlingBehavior.kt
index 134e790..e4e0ac9 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/snapping/SnapFlingBehavior.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/snapping/SnapFlingBehavior.kt
@@ -117,8 +117,13 @@
 
                 val initialOffset =
                     snapLayoutInfoProvider.calculateApproachOffset(initialVelocity, decayOffset)
-                var remainingScrollOffset =
-                    abs(initialOffset) * sign(initialVelocity) // ensure offset sign is correct
+
+                check(!initialOffset.isNaN()) {
+                    "calculateApproachOffset returned NaN. Please use a valid value."
+                }
+
+                // ensure offset sign and value are correct
+                var remainingScrollOffset = abs(initialOffset) * sign(initialVelocity)
 
                 onRemainingScrollOffsetUpdate(remainingScrollOffset) // First Scroll Offset
 
@@ -128,9 +133,15 @@
                         onRemainingScrollOffsetUpdate(remainingScrollOffset)
                     }
 
-                remainingScrollOffset =
+                val finalSnapOffset =
                     snapLayoutInfoProvider.calculateSnapOffset(animationState.velocity)
 
+                check(!finalSnapOffset.isNaN()) {
+                    "calculateSnapOffset returned NaN. Please use a valid value."
+                }
+
+                remainingScrollOffset = finalSnapOffset
+
                 debugLog { "Settling Final Bound=$remainingScrollOffset" }
 
                 animateWithTarget(
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyDsl.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyDsl.kt
index 4dd7d8fb3..efa21df 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyDsl.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyDsl.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.foundation.lazy
 
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.gestures.FlingBehavior
 import androidx.compose.foundation.gestures.ScrollableDefaults
 import androidx.compose.foundation.internal.JvmDefaultWithCompatibility
@@ -112,6 +113,7 @@
      * Note: More investigations needed to make sure sticky headers API is suitable for various more
      * generic usecases, e.g. in grids. This API is experimental until the answer is found.
      */
+    @ExperimentalFoundationApi
     fun stickyHeader(
         key: Any? = null,
         contentType: Any? = null,
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListBeyondBoundsModifier.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListBeyondBoundsModifier.kt
index 3f99e0e..11d3c6b 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListBeyondBoundsModifier.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListBeyondBoundsModifier.kt
@@ -33,10 +33,6 @@
 internal class LazyListBeyondBoundsState(val state: LazyListState, val beyondBoundsItemCount: Int) :
     LazyLayoutBeyondBoundsState {
 
-    override fun remeasure() {
-        state.remeasurement?.forceRemeasure()
-    }
-
     override val itemCount: Int
         get() = state.layoutInfo.totalItemsCount
 
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListIntervalContent.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListIntervalContent.kt
index cb509d2..4639b4c 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListIntervalContent.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListIntervalContent.kt
@@ -16,16 +16,19 @@
 
 package androidx.compose.foundation.lazy
 
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.lazy.layout.LazyLayoutIntervalContent
 import androidx.compose.foundation.lazy.layout.MutableIntervalList
 import androidx.compose.runtime.Composable
 
+@ExperimentalFoundationApi
 internal class LazyListIntervalContent(
     content: LazyListScope.() -> Unit,
 ) : LazyLayoutIntervalContent<LazyListInterval>(), LazyListScope {
     override val intervals: MutableIntervalList<LazyListInterval> = MutableIntervalList()
 
     private var _headerIndexes: MutableList<Int>? = null
+    @Suppress("PrimitiveInCollection")
     val headerIndexes: List<Int>
         get() = _headerIndexes ?: emptyList()
 
@@ -61,6 +64,7 @@
         contentType: Any?,
         content: @Composable LazyItemScope.() -> Unit
     ) {
+        @Suppress("PrimitiveInCollection")
         val headersIndexes = _headerIndexes ?: mutableListOf<Int>().also { _headerIndexes = it }
         headersIndexes.add(intervals.size)
 
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListItemProvider.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListItemProvider.kt
index 6f0bbbe..93283ce 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListItemProvider.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListItemProvider.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.foundation.lazy
 
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.lazy.layout.LazyLayoutItemProvider
 import androidx.compose.foundation.lazy.layout.LazyLayoutKeyIndexMap
 import androidx.compose.foundation.lazy.layout.LazyLayoutPinnableItem
@@ -26,6 +27,7 @@
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberUpdatedState
 
+@OptIn(ExperimentalFoundationApi::class)
 internal interface LazyListItemProvider : LazyLayoutItemProvider {
     val keyIndexMap: LazyLayoutKeyIndexMap
     /** The list of indexes of the sticky header items */
@@ -34,6 +36,7 @@
     val itemScope: LazyItemScopeImpl
 }
 
+@OptIn(ExperimentalFoundationApi::class)
 @Composable
 internal fun rememberLazyListItemProviderLambda(
     state: LazyListState,
@@ -61,6 +64,7 @@
     }
 }
 
+@OptIn(ExperimentalFoundationApi::class)
 private class LazyListItemProviderImpl
 constructor(
     private val state: LazyListState,
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListMeasuredItemProvider.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListMeasuredItemProvider.kt
index ce1a5d3..329f134 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListMeasuredItemProvider.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListMeasuredItemProvider.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.foundation.lazy
 
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.lazy.layout.LazyLayoutKeyIndexMap
 import androidx.compose.foundation.lazy.layout.LazyLayoutMeasureScope
 import androidx.compose.foundation.lazy.layout.LazyLayoutMeasuredItemProvider
@@ -23,8 +24,8 @@
 import androidx.compose.ui.unit.Constraints
 
 /** Abstracts away the subcomposition from the measuring logic. */
-internal abstract class LazyListMeasuredItemProvider
-constructor(
+@OptIn(ExperimentalFoundationApi::class)
+internal abstract class LazyListMeasuredItemProvider(
     constraints: Constraints,
     isVertical: Boolean,
     private val itemProvider: LazyListItemProvider,
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListScrollPosition.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListScrollPosition.kt
index 43b1adf..d8d9515 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListScrollPosition.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListScrollPosition.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.foundation.lazy
 
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.lazy.layout.LazyLayoutNearestRangeState
 import androidx.compose.foundation.lazy.layout.findIndexByKey
 import androidx.compose.runtime.getValue
@@ -88,6 +89,7 @@
      * were items added or removed before our current first visible item and keep this item as the
      * first visible one even given that its index has been changed.
      */
+    @OptIn(ExperimentalFoundationApi::class)
     fun updateScrollPositionIfTheFirstItemWasMoved(
         itemProvider: LazyListItemProvider,
         index: Int
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGrid.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGrid.kt
index 57c7da8..6611091 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGrid.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGrid.kt
@@ -143,6 +143,7 @@
 /** lazy grid slots configuration */
 internal class LazyGridSlots(val sizes: IntArray, val positions: IntArray)
 
+@OptIn(ExperimentalFoundationApi::class)
 @Composable
 private fun rememberLazyGridMeasurePolicy(
     /** Items provider of the list. */
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridBeyondBoundsModifier.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridBeyondBoundsModifier.kt
index 432176a..da43aa2 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridBeyondBoundsModifier.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridBeyondBoundsModifier.kt
@@ -29,10 +29,6 @@
     val state: LazyGridState,
 ) : LazyLayoutBeyondBoundsState {
 
-    override fun remeasure() {
-        state.remeasurement?.forceRemeasure()
-    }
-
     override val itemCount: Int
         get() = state.layoutInfo.totalItemsCount
 
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridItemProvider.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridItemProvider.kt
index 324adbb..07116974 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridItemProvider.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridItemProvider.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.foundation.lazy.grid
 
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.lazy.layout.LazyLayoutItemProvider
 import androidx.compose.foundation.lazy.layout.LazyLayoutKeyIndexMap
 import androidx.compose.foundation.lazy.layout.LazyLayoutPinnableItem
@@ -26,6 +27,7 @@
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberUpdatedState
 
+@OptIn(ExperimentalFoundationApi::class)
 internal interface LazyGridItemProvider : LazyLayoutItemProvider {
     val keyIndexMap: LazyLayoutKeyIndexMap
     val spanLayoutProvider: LazyGridSpanLayoutProvider
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridMeasuredItemProvider.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridMeasuredItemProvider.kt
index adfaebf..f4716a1 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridMeasuredItemProvider.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridMeasuredItemProvider.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.foundation.lazy.grid
 
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.lazy.layout.LazyLayoutKeyIndexMap
 import androidx.compose.foundation.lazy.layout.LazyLayoutMeasureScope
 import androidx.compose.foundation.lazy.layout.LazyLayoutMeasuredItemProvider
@@ -23,8 +24,8 @@
 import androidx.compose.ui.unit.Constraints
 
 /** Abstracts away the subcomposition from the measuring logic. */
-internal abstract class LazyGridMeasuredItemProvider
-constructor(
+@OptIn(ExperimentalFoundationApi::class)
+internal abstract class LazyGridMeasuredItemProvider(
     private val itemProvider: LazyGridItemProvider,
     private val measureScope: LazyLayoutMeasureScope,
     private val defaultMainAxisSpacing: Int
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridScrollPosition.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridScrollPosition.kt
index 9a34965..36a2a29 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridScrollPosition.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridScrollPosition.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.foundation.lazy.grid
 
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.lazy.layout.LazyLayoutNearestRangeState
 import androidx.compose.foundation.lazy.layout.findIndexByKey
 import androidx.compose.runtime.getValue
@@ -89,6 +90,7 @@
      * were items added or removed before our current first visible item and keep this item as the
      * first visible one even given that its index has been changed.
      */
+    @OptIn(ExperimentalFoundationApi::class)
     fun updateScrollPositionIfTheFirstItemWasMoved(
         itemProvider: LazyGridItemProvider,
         index: Int
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutBeyondBoundsModifierLocal.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutBeyondBoundsModifierLocal.kt
index cb2a701..ee560bc 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutBeyondBoundsModifierLocal.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutBeyondBoundsModifierLocal.kt
@@ -27,12 +27,18 @@
 import androidx.compose.ui.layout.BeyondBoundsLayout.LayoutDirection.Companion.Below
 import androidx.compose.ui.layout.BeyondBoundsLayout.LayoutDirection.Companion.Left
 import androidx.compose.ui.layout.BeyondBoundsLayout.LayoutDirection.Companion.Right
+import androidx.compose.ui.layout.Measurable
+import androidx.compose.ui.layout.MeasureResult
+import androidx.compose.ui.layout.MeasureScope
 import androidx.compose.ui.layout.ModifierLocalBeyondBoundsLayout
 import androidx.compose.ui.modifier.ModifierLocalMap
 import androidx.compose.ui.modifier.ModifierLocalModifierNode
 import androidx.compose.ui.modifier.modifierLocalMapOf
+import androidx.compose.ui.node.LayoutModifierNode
 import androidx.compose.ui.node.ModifierNodeElement
+import androidx.compose.ui.node.remeasureSync
 import androidx.compose.ui.platform.InspectorInfo
+import androidx.compose.ui.unit.Constraints
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.LayoutDirection.Ltr
 import androidx.compose.ui.unit.LayoutDirection.Rtl
@@ -117,7 +123,15 @@
     private var reverseLayout: Boolean,
     private var layoutDirection: LayoutDirection,
     private var orientation: Orientation
-) : Modifier.Node(), ModifierLocalModifierNode, BeyondBoundsLayout {
+) : Modifier.Node(), ModifierLocalModifierNode, BeyondBoundsLayout, LayoutModifierNode {
+
+    override fun MeasureScope.measure(
+        measurable: Measurable,
+        constraints: Constraints
+    ): MeasureResult {
+        val placeable = measurable.measure(constraints)
+        return layout(placeable.width, placeable.height) { placeable.place(0, 0) }
+    }
 
     override val providedValues: ModifierLocalMap
         get() = modifierLocalMapOf(ModifierLocalBeyondBoundsLayout to this)
@@ -135,7 +149,8 @@
     ): T? {
         // If the lazy list is empty, or if it does not have any visible items (Which implies
         // that there isn't space to add a single item), we don't attempt to layout any more items.
-        if (state.itemCount <= 0 || !state.hasVisibleItems) {
+        // if the node is not yet attached or we haven't completed at least one layout pass..
+        if (state.itemCount <= 0 || !state.hasVisibleItems || !isAttached) {
             return block.invoke(emptyBeyondBoundsScope)
         }
 
@@ -149,13 +164,12 @@
         var interval = beyondBoundsInfo.addInterval(startIndex, startIndex)
         var found: T? = null
         while (found == null && interval.hasMoreContent(direction)) {
-
             // Add one extra beyond bounds item.
             interval =
                 addNextInterval(interval, direction).also {
                     beyondBoundsInfo.removeInterval(interval)
                 }
-            state.remeasure()
+            remeasureSync()
 
             // When we invoke this block, the beyond bounds items are present.
             found =
@@ -169,7 +183,7 @@
 
         // Dispose the items that are beyond the visible bounds.
         beyondBoundsInfo.removeInterval(interval)
-        state.remeasure()
+        remeasureSync()
         return found
     }
 
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutBeyondBoundsState.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutBeyondBoundsState.kt
index 00e8670..c0dbc69 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutBeyondBoundsState.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutBeyondBoundsState.kt
@@ -16,13 +16,12 @@
 
 package androidx.compose.foundation.lazy.layout
 
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.ui.util.fastForEach
 import kotlin.math.min
 
 internal interface LazyLayoutBeyondBoundsState {
 
-    fun remeasure()
-
     val itemCount: Int
 
     val hasVisibleItems: Boolean
@@ -32,6 +31,7 @@
     val lastPlacedIndex: Int
 }
 
+@OptIn(ExperimentalFoundationApi::class)
 internal fun LazyLayoutItemProvider.calculateLazyLayoutPinnedIndices(
     pinnedItemList: LazyLayoutPinnedItemList,
     beyondBoundsInfo: LazyLayoutBeyondBoundsInfo,
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory.kt
index 3761c12..0565551 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.foundation.lazy.layout
 
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.DisposableEffect
 import androidx.compose.runtime.ReusableContentHost
@@ -31,6 +32,7 @@
  * 3) Adds state restoration on top of the composable returned by [itemProvider] with help of
  *    [saveableStateHolder].
  */
+@OptIn(ExperimentalFoundationApi::class)
 internal class LazyLayoutItemContentFactory(
     private val saveableStateHolder: SaveableStateHolder,
     val itemProvider: () -> LazyLayoutItemProvider,
@@ -115,6 +117,7 @@
  * Hack around skippable functions to force skip SaveableStateProvider and Item block when nothing
  * changed. It allows us to skip heavy-weight composition local providers.
  */
+@OptIn(ExperimentalFoundationApi::class)
 @Composable
 private fun SkippableItem(
     itemProvider: LazyLayoutItemProvider,
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutItemProvider.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutItemProvider.kt
index d158768..b00756a 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutItemProvider.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutItemProvider.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.foundation.lazy.layout
 
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.Stable
 
@@ -28,6 +29,7 @@
  * change.
  */
 @Stable
+@ExperimentalFoundationApi
 interface LazyLayoutItemProvider {
 
     /** The total number of items in the lazy layout (visible or not). */
@@ -62,6 +64,7 @@
  * Finds a position of the item with the given key in the lists. This logic allows us to detect when
  * there were items added or removed before our current first item.
  */
+@OptIn(ExperimentalFoundationApi::class)
 internal fun LazyLayoutItemProvider.findIndexByKey(
     key: Any?,
     lastKnownIndex: Int,
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutMeasureScope.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutMeasureScope.kt
index f393626..d6c9b25 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutMeasureScope.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutMeasureScope.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.foundation.lazy.layout
 
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.runtime.Stable
 import androidx.compose.ui.geometry.Size
 import androidx.compose.ui.geometry.isSpecified
@@ -45,6 +46,7 @@
  * change.
  */
 @Stable
+@ExperimentalFoundationApi
 sealed interface LazyLayoutMeasureScope : MeasureScope {
     /**
      * Subcompose and measure the item of lazy layout.
@@ -94,6 +96,7 @@
         }
 }
 
+@OptIn(ExperimentalFoundationApi::class)
 internal class LazyLayoutMeasureScopeImpl
 internal constructor(
     private val itemContentFactory: LazyLayoutItemContentFactory,
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutSemantics.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutSemantics.kt
index dddefb9..a373688 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutSemantics.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutSemantics.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.foundation.lazy.layout
 
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
@@ -35,6 +36,7 @@
 import androidx.compose.ui.semantics.verticalScrollAxisRange
 import kotlinx.coroutines.launch
 
+@OptIn(ExperimentalFoundationApi::class)
 @Composable
 internal fun Modifier.lazyLayoutSemantics(
     itemProviderLambda: () -> LazyLayoutItemProvider,
@@ -52,6 +54,7 @@
             reverseScrolling = reverseScrolling,
         )
 
+@OptIn(ExperimentalFoundationApi::class)
 private class LazyLayoutSemanticsModifier(
     val itemProviderLambda: () -> LazyLayoutItemProvider,
     val state: LazyLayoutSemanticState,
@@ -105,6 +108,7 @@
     }
 }
 
+@OptIn(ExperimentalFoundationApi::class)
 private class LazyLayoutSemanticsModifierNode(
     private var itemProviderLambda: () -> LazyLayoutItemProvider,
     private var state: LazyLayoutSemanticState,
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridBeyondBoundsModifier.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridBeyondBoundsModifier.kt
index 1041f78..c29f54c 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridBeyondBoundsModifier.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridBeyondBoundsModifier.kt
@@ -31,10 +31,6 @@
     val state: LazyStaggeredGridState,
 ) : LazyLayoutBeyondBoundsState {
 
-    override fun remeasure() {
-        state.remeasurement?.forceRemeasure()
-    }
-
     override val itemCount: Int
         get() = state.layoutInfo.totalItemsCount
 
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridItemProvider.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridItemProvider.kt
index 525a52f..dfc9923 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridItemProvider.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridItemProvider.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.foundation.lazy.staggeredgrid
 
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.lazy.layout.LazyLayoutItemProvider
 import androidx.compose.foundation.lazy.layout.LazyLayoutKeyIndexMap
 import androidx.compose.foundation.lazy.layout.LazyLayoutPinnableItem
@@ -26,6 +27,7 @@
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberUpdatedState
 
+@OptIn(ExperimentalFoundationApi::class)
 internal interface LazyStaggeredGridItemProvider : LazyLayoutItemProvider {
     val spanProvider: LazyStaggeredGridSpanProvider
     val keyIndexMap: LazyLayoutKeyIndexMap
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridMeasure.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridMeasure.kt
index e80a2f0..66a7fed 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridMeasure.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridMeasure.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.foundation.lazy.staggeredgrid
 
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.lazy.layout.LazyLayoutItemAnimator
 import androidx.compose.foundation.lazy.layout.LazyLayoutKeyIndexMap
 import androidx.compose.foundation.lazy.layout.LazyLayoutMeasureScope
@@ -46,6 +47,8 @@
 
 private const val DebugLoggingEnabled = false
 
+@Suppress("BanInlineOptIn")
+@OptIn(ExperimentalFoundationApi::class)
 private inline fun <T> withDebugLogging(
     scope: LazyLayoutMeasureScope,
     block: LazyLayoutMeasureScope.() -> T
@@ -77,6 +80,7 @@
     }
 }
 
+@OptIn(ExperimentalFoundationApi::class)
 internal fun LazyLayoutMeasureScope.measureStaggeredGrid(
     state: LazyStaggeredGridState,
     pinnedItems: List<Int>,
@@ -172,6 +176,7 @@
     )
 }
 
+@OptIn(ExperimentalFoundationApi::class)
 internal class LazyStaggeredGridMeasureContext(
     val state: LazyStaggeredGridState,
     val pinnedItems: List<Int>,
@@ -243,6 +248,7 @@
         get() = if (isFullSpan) FullSpan else start
 }
 
+@OptIn(ExperimentalFoundationApi::class)
 private fun LazyStaggeredGridMeasureContext.measure(
     initialScrollDelta: Int,
     initialItemIndices: IntArray,
@@ -1071,6 +1077,7 @@
 private fun LazyStaggeredGridMeasureContext.findPreviousItemIndex(item: Int, lane: Int): Int =
     laneInfo.findPreviousItemIndex(item, lane)
 
+@OptIn(ExperimentalFoundationApi::class)
 internal abstract class LazyStaggeredGridMeasureProvider(
     private val isVertical: Boolean,
     private val itemProvider: LazyStaggeredGridItemProvider,
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridMeasurePolicy.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridMeasurePolicy.kt
index 0a1ec49..7fa53f8 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridMeasurePolicy.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridMeasurePolicy.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.foundation.lazy.staggeredgrid
 
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.checkScrollableContainerConstraints
 import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.layout.PaddingValues
@@ -34,6 +35,7 @@
 import androidx.compose.ui.unit.constrainWidth
 import kotlinx.coroutines.CoroutineScope
 
+@OptIn(ExperimentalFoundationApi::class)
 @Composable
 internal fun rememberStaggeredGridMeasurePolicy(
     state: LazyStaggeredGridState,
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridScrollPosition.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridScrollPosition.kt
index 416e166..eef8c00 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridScrollPosition.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridScrollPosition.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.foundation.lazy.staggeredgrid
 
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.lazy.layout.LazyLayoutItemProvider
 import androidx.compose.foundation.lazy.layout.LazyLayoutNearestRangeState
 import androidx.compose.foundation.lazy.layout.findIndexByKey
@@ -129,6 +130,7 @@
      * were items added or removed before our current first visible item and keep this item as the
      * first visible one even given that its index has been changed.
      */
+    @OptIn(ExperimentalFoundationApi::class)
     fun updateScrollPositionIfTheFirstItemWasMoved(
         itemProvider: LazyLayoutItemProvider,
         indices: IntArray
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerBeyondBoundsModifier.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerBeyondBoundsModifier.kt
index 7050e1b..0be75d97 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerBeyondBoundsModifier.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerBeyondBoundsModifier.kt
@@ -33,9 +33,6 @@
     private val state: PagerState,
     private val beyondViewportPageCount: Int
 ) : LazyLayoutBeyondBoundsState {
-    override fun remeasure() {
-        state.remeasurement?.forceRemeasure()
-    }
 
     override val itemCount: Int
         get() = state.pageCount
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerMeasure.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerMeasure.kt
index 1201e17..5bdfc9b 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerMeasure.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerMeasure.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.foundation.pager
 
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.gestures.snapping.SnapPosition
 import androidx.compose.foundation.gestures.snapping.calculateDistanceToDesiredSnapPosition
@@ -37,6 +38,7 @@
 import kotlin.math.abs
 import kotlinx.coroutines.CoroutineScope
 
+@OptIn(ExperimentalFoundationApi::class)
 internal fun LazyLayoutMeasureScope.measurePager(
     pageCount: Int,
     pagerItemProvider: PagerLazyLayoutItemProvider,
@@ -560,6 +562,7 @@
     }
 }
 
+@OptIn(ExperimentalFoundationApi::class)
 private fun LazyLayoutMeasureScope.getAndMeasure(
     index: Int,
     childConstraints: Constraints,
@@ -589,6 +592,7 @@
     )
 }
 
+@OptIn(ExperimentalFoundationApi::class)
 private fun LazyLayoutMeasureScope.calculatePagesOffsets(
     pages: List<MeasuredPage>,
     extraPagesBefore: List<MeasuredPage>,
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerMeasurePolicy.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerMeasurePolicy.kt
index de7d2a6..5e3ddb13 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerMeasurePolicy.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerMeasurePolicy.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.foundation.pager
 
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.checkScrollableContainerConstraints
 import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.gestures.snapping.SnapPosition
@@ -37,6 +38,7 @@
 import androidx.compose.ui.unit.offset
 import kotlinx.coroutines.CoroutineScope
 
+@OptIn(ExperimentalFoundationApi::class)
 @Composable
 internal fun rememberPagerMeasurePolicy(
     itemProviderLambda: () -> PagerLazyLayoutItemProvider,
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerScrollPosition.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerScrollPosition.kt
index 7576c9e..bb3da93 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerScrollPosition.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerScrollPosition.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.foundation.pager
 
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.lazy.layout.LazyLayoutNearestRangeState
 import androidx.compose.foundation.lazy.layout.findIndexByKey
 import androidx.compose.runtime.getValue
@@ -81,6 +82,7 @@
         lastKnownCurrentPageKey = null
     }
 
+    @OptIn(ExperimentalFoundationApi::class)
     fun matchPageWithKey(itemProvider: PagerLazyLayoutItemProvider, index: Int): Int {
         val newIndex = itemProvider.findIndexByKey(lastKnownCurrentPageKey, index)
         if (index != newIndex) {
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/ClickableText.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/ClickableText.kt
index 6ba88a2..2247b1d 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/ClickableText.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/ClickableText.kt
@@ -61,9 +61,13 @@
  * @see BasicText
  * @see androidx.compose.ui.input.pointer.pointerInput
  * @see androidx.compose.foundation.gestures.detectTapGestures
+ * @see androidx.compose.ui.text.LinkAnnotation
  */
 @Composable
-@Deprecated("Use Text or BasicText and pass an AnnotatedString that contains a LinkAnnotation")
+@Deprecated(
+    "Use Text or BasicText and pass an AnnotatedString that contains a LinkAnnotation. " +
+        "Check LinkAnnotation's documentation for more details and samples."
+)
 fun ClickableText(
     text: AnnotatedString,
     modifier: Modifier = Modifier,
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/CoreTextField.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/CoreTextField.kt
index 530e37b..6b6deb5 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/CoreTextField.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/CoreTextField.kt
@@ -345,7 +345,7 @@
         }
 
     // Hide the keyboard if made disabled or read-only while focused (b/237308379).
-    val writeable by rememberUpdatedState(enabled && !readOnly && windowInfo.isWindowFocused)
+    val writeable by rememberUpdatedState(enabled && !readOnly)
     LaunchedEffect(Unit) {
         try {
             snapshotFlow { writeable }
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/TextLinkScope.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/TextLinkScope.kt
index c869f8b..647183fa 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/TextLinkScope.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/TextLinkScope.kt
@@ -46,7 +46,7 @@
 import androidx.compose.ui.text.LinkAnnotation
 import androidx.compose.ui.text.SpanStyle
 import androidx.compose.ui.text.TextLayoutResult
-import androidx.compose.ui.text.buildAnnotatedString
+import androidx.compose.ui.text.TextLinkStyles
 import androidx.compose.ui.unit.Density
 import androidx.compose.ui.unit.IntOffset
 import androidx.compose.ui.unit.LayoutDirection
@@ -65,7 +65,31 @@
     var textLayoutResult: TextLayoutResult? by mutableStateOf(null)
 
     /** [initialText] with applied links styling to it from [LinkAnnotation.styles] */
-    internal var text: AnnotatedString = initialText
+    internal var text: AnnotatedString
+
+    init {
+        text =
+            initialText.flatMapAnnotations {
+                // If link styles don't contain a non-null style for at least one of the states,
+                // we don't add any additional style to the list of annotations
+                if (
+                    it.item is LinkAnnotation && !(it.item as LinkAnnotation).styles.isNullOrEmpty()
+                ) {
+                    arrayListOf(
+                        // original link annotation
+                        it,
+                        // SpanStyle from the link styling object, or default SpanStyle otherwise
+                        AnnotatedString.Range(
+                            (it.item as LinkAnnotation).styles?.style ?: SpanStyle(),
+                            it.start,
+                            it.end
+                        )
+                    )
+                } else {
+                    arrayListOf(it)
+                }
+            }
+    }
 
     // Additional span style annotations applied to the AnnotatedString. These SpanStyles are coming
     // from LinkAnnotation's style arguments
@@ -165,29 +189,31 @@
                     )
             )
 
-            val isHovered by interactionSource.collectIsHoveredAsState()
-            val isFocused by interactionSource.collectIsFocusedAsState()
-            val isPressed by interactionSource.collectIsPressedAsState()
+            if (!range.item.styles.isNullOrEmpty()) {
+                val isHovered by interactionSource.collectIsHoveredAsState()
+                val isFocused by interactionSource.collectIsFocusedAsState()
+                val isPressed by interactionSource.collectIsPressedAsState()
 
-            StyleAnnotation(
-                isHovered,
-                isFocused,
-                isPressed,
-                range.item.styles?.style,
-                range.item.styles?.focusedStyle,
-                range.item.styles?.hoveredStyle,
-                range.item.styles?.pressedStyle,
-            ) {
-                // we calculate the latest style based on the link state and apply it to the
-                // initialText's style. This allows us to merge the style with the original instead
-                // of fully replacing it
-                val mergedStyle =
-                    range.item.styles
-                        ?.style
-                        .mergeOrUse(if (isFocused) range.item.styles?.focusedStyle else null)
-                        .mergeOrUse(if (isHovered) range.item.styles?.hoveredStyle else null)
-                        .mergeOrUse(if (isPressed) range.item.styles?.pressedStyle else null)
-                mergedStyle?.let { replaceStyle(it, range.start, range.end) }
+                StyleAnnotation(
+                    isHovered,
+                    isFocused,
+                    isPressed,
+                    range.item.styles?.style,
+                    range.item.styles?.focusedStyle,
+                    range.item.styles?.hoveredStyle,
+                    range.item.styles?.pressedStyle,
+                ) {
+                    // we calculate the latest style based on the link state and apply it to the
+                    // initialText's style. This allows us to merge the style with the original
+                    // instead of fully replacing it
+                    val mergedStyle =
+                        range.item.styles
+                            ?.style
+                            .mergeOrUse(if (isFocused) range.item.styles?.focusedStyle else null)
+                            .mergeOrUse(if (isHovered) range.item.styles?.hoveredStyle else null)
+                            .mergeOrUse(if (isPressed) range.item.styles?.pressedStyle else null)
+                    replaceStyle(range, mergedStyle)
+                }
             }
         }
     }
@@ -214,12 +240,11 @@
     internal fun applyAnnotators(): AnnotatedString {
         val styledText =
             if (annotators.isEmpty()) text
-            else
-                buildAnnotatedString {
-                    append(initialText)
-                    val scope = TextAnnotatorScope(this)
-                    annotators.fastForEach { it.invoke(scope) }
-                }
+            else {
+                val scope = TextAnnotatorScope(text)
+                annotators.fastForEach { it.invoke(scope) }
+                scope.styledText
+            }
         text = styledText
         return styledText
     }
@@ -234,6 +259,11 @@
     }
 }
 
+private fun TextLinkStyles?.isNullOrEmpty(): Boolean {
+    return this == null ||
+        (style == null && focusedStyle == null && hoveredStyle == null && pressedStyle == null)
+}
+
 /** Interface holding the width, height and positioning logic. */
 internal class TextRangeLayoutMeasureResult
 internal constructor(val width: Int, val height: Int, val place: () -> IntOffset)
@@ -257,9 +287,33 @@
     override fun Density.modifyParentData(parentData: Any?) = this@TextRangeLayoutModifier
 }
 
-/** Provides methods to add styles to text inside a [TextLinkScope.StyleAnnotation] function. */
-private class TextAnnotatorScope(private val builder: AnnotatedString.Builder) {
-    fun replaceStyle(style: SpanStyle, start: Int, end: Int) {
-        builder.addStyle(style, start, end)
+/**
+ * Provides methods to update styles of the text inside a [TextLinkScope.StyleAnnotation] function.
+ */
+private class TextAnnotatorScope(private val initialText: AnnotatedString) {
+    var styledText = initialText
+
+    fun replaceStyle(linkRange: AnnotatedString.Range<LinkAnnotation>, newStyle: SpanStyle?) {
+        var linkFound = false
+        styledText =
+            initialText.mapAnnotations {
+                // if we found a link annotation on previous iteration, we need to update the
+                // SpanStyle
+                // on this iteration. This SpanStyle with the same range as the link annotation
+                // coming right after the link annotation corresponds to the link styling
+                val annotation =
+                    if (
+                        linkFound &&
+                            it.item is SpanStyle &&
+                            it.start == linkRange.start &&
+                            it.end == linkRange.end
+                    ) {
+                        AnnotatedString.Range(newStyle ?: SpanStyle(), it.start, it.end)
+                    } else {
+                        it
+                    }
+                linkFound = linkRange == it
+                annotation
+            }
     }
 }
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/handwriting/StylusHandwriting.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/handwriting/StylusHandwriting.kt
index ec3ac9b..944f65b 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/handwriting/StylusHandwriting.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/handwriting/StylusHandwriting.kt
@@ -218,5 +218,5 @@
 internal expect val isStylusHandwritingSupported: Boolean
 
 /** The amount of the padding added to the handwriting bounds of an editor. */
-internal val HandwritingBoundsVerticalOffset = 40.dp
-internal val HandwritingBoundsHorizontalOffset = 10.dp
+internal val HandwritingBoundsVerticalOffset = 0.dp
+internal val HandwritingBoundsHorizontalOffset = 0.dp
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/input/TextFieldState.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/input/TextFieldState.kt
index 2bd4b5a..6337cc0 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/input/TextFieldState.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/input/TextFieldState.kt
@@ -607,6 +607,13 @@
  *
  * If you need to store a [TextFieldState] in another object, use the [TextFieldState.Saver] object
  * to manually save and restore the state.
+ *
+ * @param initialText The initial text state. If a different value is passed in a subsequent
+ *   recomposition, the value of the state will _not_ be updated. To update the state after it's
+ *   initialized, call methods on [TextFieldState].
+ * @param initialSelection The initial selection state. If a different value is passed in a
+ *   subsequent recomposition, the value of the state will _not_ be updated. To update the state
+ *   after it's initialized, call methods on [TextFieldState].
  */
 @Composable
 fun rememberTextFieldState(
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/input/internal/TextFieldDecoratorModifier.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/input/internal/TextFieldDecoratorModifier.kt
index a04a59b..cd38a53 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/input/internal/TextFieldDecoratorModifier.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/input/internal/TextFieldDecoratorModifier.kt
@@ -355,7 +355,12 @@
     private var windowInfo: WindowInfo? = null
 
     private val isFocused: Boolean
-        get() = isElementFocused && windowInfo?.isWindowFocused == true
+        get() {
+            // make sure that we read both window focus and element focus for snapshot aware
+            // callers to successfully update when either one changes
+            val isWindowFocused = windowInfo?.isWindowFocused == true
+            return isElementFocused && isWindowFocused
+        }
 
     /**
      * We observe text changes to show/hide text toolbar and cursor handles. This job is only run
@@ -678,7 +683,6 @@
         observeReads {
             windowInfo = currentValueOf(LocalWindowInfo)
             onFocusChange()
-            startInputSessionOnWindowFocusChange()
         }
     }
 
@@ -712,15 +716,6 @@
         stylusHandwritingTrigger?.resetReplayCache()
     }
 
-    private fun startInputSessionOnWindowFocusChange() {
-        if (windowInfo == null) return
-        // b/326323000: We do not dispose input session on just window focus change until another
-        // item requests focus and we lose element focus status which is handled by onFocusEvent.
-        if (windowInfo?.isWindowFocused == true && isElementFocused) {
-            startInputSession(fromTap = false)
-        }
-    }
-
     private fun requireKeyboardController(): SoftwareKeyboardController =
         currentValueOf(LocalSoftwareKeyboardController) ?: error("No software keyboard controller")
 
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/MinLinesConstrainer.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/MinLinesConstrainer.kt
index 283083b..d3d5f65 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/MinLinesConstrainer.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/MinLinesConstrainer.kt
@@ -77,7 +77,9 @@
             return MinLinesConstrainer(
                     layoutDirection,
                     resolveDefaults(paramStyle, layoutDirection),
-                    density,
+                    // other density implementations may hold references to views/activities
+                    // which the cache outlives, potentially causing memory leak.
+                    Density(density.density, density.fontScale),
                     fontFamilyResolver
                 )
                 .also { last = it }
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextAnnotatedStringNode.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextAnnotatedStringNode.kt
index 881527f..41b3de2 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextAnnotatedStringNode.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextAnnotatedStringNode.kt
@@ -133,10 +133,8 @@
     /** Element has text parameters to update */
     internal fun updateText(text: AnnotatedString): Boolean {
         val charDiff = this.text.text != text.text
-        val spanDiff = this.text.spanStyles != text.spanStyles
-        val paragraphDiff = this.text.paragraphStyles != text.paragraphStyles
         val annotationDiff = !this.text.hasEqualAnnotations(text)
-        val anyDiff = charDiff || spanDiff || paragraphDiff || annotationDiff
+        val anyDiff = charDiff || annotationDiff
 
         if (anyDiff) {
             this.text = text
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/BasicContextMenuRepresentation.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/BasicContextMenuRepresentation.desktop.kt
deleted file mode 100644
index cdc9fb2..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/BasicContextMenuRepresentation.desktop.kt
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation
-
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.IntrinsicSize
-import androidx.compose.foundation.layout.PaddingValues
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.RowScope
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.sizeIn
-import androidx.compose.foundation.layout.width
-import androidx.compose.foundation.text.BasicText
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.shadow
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.input.pointer.PointerEventType
-import androidx.compose.ui.input.pointer.pointerInput
-import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.window.Popup
-import androidx.compose.ui.window.PopupProperties
-import androidx.compose.ui.window.rememberCursorPositionProvider
-
-// Design of basic represenation is from Material specs:
-// https://material.io/design/interaction/states.html#hover
-// https://material.io/components/menus#specs
-
-val LightDefaultContextMenuRepresentation =
-    DefaultContextMenuRepresentation(
-        backgroundColor = Color.White,
-        textColor = Color.Black,
-        itemHoverColor = Color.Black.copy(alpha = 0.04f)
-    )
-
-val DarkDefaultContextMenuRepresentation =
-    DefaultContextMenuRepresentation(
-        backgroundColor = Color(0xFF121212), // like surface in darkColors
-        textColor = Color.White,
-        itemHoverColor = Color.White.copy(alpha = 0.04f)
-    )
-
-class DefaultContextMenuRepresentation(
-    private val backgroundColor: Color,
-    private val textColor: Color,
-    private val itemHoverColor: Color
-) : ContextMenuRepresentation {
-    @Composable
-    override fun Representation(state: ContextMenuState, items: List<ContextMenuItem>) {
-        val isOpen = state.status is ContextMenuState.Status.Open
-        if (isOpen) {
-            Popup(
-                popupPositionProvider = rememberCursorPositionProvider(),
-                onDismissRequest = { state.status = ContextMenuState.Status.Closed },
-                properties = PopupProperties(focusable = true)
-            ) {
-                Column(
-                    modifier =
-                        Modifier.shadow(8.dp)
-                            .background(backgroundColor)
-                            .padding(vertical = 4.dp)
-                            .width(IntrinsicSize.Max)
-                            .verticalScroll(rememberScrollState())
-                ) {
-                    items
-                        .distinctBy { it.label }
-                        .forEach { item ->
-                            MenuItemContent(
-                                itemHoverColor = itemHoverColor,
-                                onClick = {
-                                    state.status = ContextMenuState.Status.Closed
-                                    item.onClick()
-                                }
-                            ) {
-                                BasicText(text = item.label, style = TextStyle(color = textColor))
-                            }
-                        }
-                }
-            }
-        }
-    }
-}
-
-@Composable
-private fun MenuItemContent(
-    itemHoverColor: Color,
-    onClick: () -> Unit,
-    content: @Composable RowScope.() -> Unit
-) {
-    var hovered by remember { mutableStateOf(false) }
-    Row(
-        modifier =
-            Modifier.clickable(
-                    onClick = onClick,
-                )
-                .onHover { hovered = it }
-                .background(if (hovered) itemHoverColor else Color.Transparent)
-                .fillMaxWidth()
-                // Preferred min and max width used during the intrinsic measurement.
-                .sizeIn(minWidth = 112.dp, maxWidth = 280.dp, minHeight = 32.dp)
-                .padding(PaddingValues(horizontal = 16.dp, vertical = 0.dp)),
-        verticalAlignment = Alignment.CenterVertically
-    ) {
-        content()
-    }
-}
-
-private fun Modifier.onHover(onHover: (Boolean) -> Unit) =
-    pointerInput(Unit) {
-        awaitPointerEventScope {
-            while (true) {
-                val event = awaitPointerEvent()
-                when (event.type) {
-                    PointerEventType.Enter -> onHover(true)
-                    PointerEventType.Exit -> onHover(false)
-                }
-            }
-        }
-    }
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/BasicTooltip.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/BasicTooltip.desktop.kt
deleted file mode 100644
index e906226..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/BasicTooltip.desktop.kt
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation
-
-import androidx.compose.foundation.layout.Box
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.window.Popup
-import androidx.compose.ui.window.PopupPositionProvider
-import androidx.compose.ui.window.PopupProperties
-
-/**
- * BasicTooltipBox that wraps a composable with a tooltip.
- *
- * Tooltip that provides a descriptive message for an anchor. It can be used to call the users
- * attention to the anchor.
- *
- * @param positionProvider [PopupPositionProvider] that will be used to place the tooltip relative
- *   to the anchor content.
- * @param tooltip the composable that will be used to populate the tooltip's content.
- * @param state handles the state of the tooltip's visibility.
- * @param modifier the [Modifier] to be applied to this BasicTooltipBox.
- * @param focusable [Boolean] that determines if the tooltip is focusable. When true, the tooltip
- *   will consume touch events while it's shown and will have accessibility focus move to the first
- *   element of the component. When false, the tooltip won't consume touch events while it's shown
- *   but assistive-tech users will need to swipe or drag to get to the first element of the
- *   component.
- * @param enableUserInput [Boolean] which determines if this BasicTooltipBox will handle long press
- *   and mouse hover to trigger the tooltip through the state provided.
- * @param content the composable that the tooltip will anchor to.
- */
-@Composable
-actual fun BasicTooltipBox(
-    positionProvider: PopupPositionProvider,
-    tooltip: @Composable () -> Unit,
-    state: BasicTooltipState,
-    modifier: Modifier,
-    focusable: Boolean,
-    enableUserInput: Boolean,
-    content: @Composable () -> Unit
-) {
-    // TODO: Reuse android implementation - there is no platform specifics here.
-    //  Use expect/actual only for string resources
-    Box(modifier = modifier) {
-        content()
-        if (state.isVisible) {
-            Popup(
-                popupPositionProvider = positionProvider,
-                onDismissRequest = { state.dismiss() },
-                properties =
-                    PopupProperties(
-                        // TODO(b/326167778): focusable = true cannot work with mouse
-                        focusable = false
-                    )
-            ) {
-                tooltip()
-            }
-        }
-    }
-}
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/Clickable.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/Clickable.desktop.kt
deleted file mode 100644
index b5e7252..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/Clickable.desktop.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation
-
-import androidx.compose.ui.input.key.KeyEvent
-import androidx.compose.ui.input.key.KeyEventType.Companion.KeyDown
-import androidx.compose.ui.input.key.KeyEventType.Companion.KeyUp
-import androidx.compose.ui.input.key.key
-import androidx.compose.ui.input.key.nativeKeyCode
-import androidx.compose.ui.input.key.type
-import androidx.compose.ui.node.DelegatableNode
-import java.awt.event.KeyEvent.VK_ENTER
-
-internal actual fun DelegatableNode.isComposeRootInScrollableContainer(): Boolean {
-    return false
-}
-
-// TODO: b/168524931 - should this depend on the input device?
-internal actual val TapIndicationDelay: Long = 0L
-
-/**
- * Whether the specified [KeyEvent] should trigger a press for a clickable component, i.e. whether
- * it is associated with a press of the enter key.
- */
-internal actual val KeyEvent.isPress: Boolean
-    get() = type == KeyDown && key.nativeKeyCode == VK_ENTER
-
-/**
- * Whether the specified [KeyEvent] should trigger a click for a clickable component, i.e. whether
- * it is associated with a release of the enter key.
- */
-internal actual val KeyEvent.isClick: Boolean
-    get() = type == KeyUp && key.nativeKeyCode == VK_ENTER
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/ContextMenuProvider.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/ContextMenuProvider.desktop.kt
deleted file mode 100644
index e38f648..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/ContextMenuProvider.desktop.kt
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation
-
-import androidx.compose.foundation.gestures.awaitEachGesture
-import androidx.compose.foundation.layout.Box
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.runtime.ProvidableCompositionLocal
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.runtime.staticCompositionLocalOf
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.geometry.Rect
-import androidx.compose.ui.input.pointer.AwaitPointerEventScope
-import androidx.compose.ui.input.pointer.PointerEvent
-import androidx.compose.ui.input.pointer.changedToDown
-import androidx.compose.ui.input.pointer.isSecondaryPressed
-import androidx.compose.ui.input.pointer.pointerInput
-import androidx.compose.ui.util.fastAll
-
-/**
- * Defines a container where context menu is available. Menu is triggered by right mouse clicks.
- * Representation of menu is defined by [LocalContextMenuRepresentation]`
- *
- * @param items List of context menu items. Final context menu contains all items from descendant
- *   [ContextMenuArea] and [ContextMenuDataProvider].
- * @param state [ContextMenuState] of menu controlled by this area.
- * @param enabled If false then gesture detector is disabled.
- * @param content The content of the [ContextMenuArea].
- */
-@Composable
-fun ContextMenuArea(
-    items: () -> List<ContextMenuItem>,
-    state: ContextMenuState = remember { ContextMenuState() },
-    enabled: Boolean = true,
-    content: @Composable () -> Unit
-) {
-    val data = ContextMenuData(items, LocalContextMenuData.current)
-
-    ContextMenuDataProvider(data) {
-        Box(Modifier.contextMenuDetector(state, enabled), propagateMinConstraints = true) {
-            content()
-        }
-        LocalContextMenuRepresentation.current.Representation(state, data.allItems)
-    }
-}
-
-/**
- * Adds items to the hierarchy of context menu items. Can be used, for example, to customize context
- * menu of text fields.
- *
- * @param items List of context menu items. Final context menu contains all items from descendant
- *   [ContextMenuArea] and [ContextMenuDataProvider].
- * @param content The content of the [ContextMenuDataProvider].
- * @see [[ContextMenuArea]]
- */
-@Composable
-fun ContextMenuDataProvider(items: () -> List<ContextMenuItem>, content: @Composable () -> Unit) {
-    ContextMenuDataProvider(ContextMenuData(items, LocalContextMenuData.current), content)
-}
-
-@Composable
-internal fun ContextMenuDataProvider(data: ContextMenuData, content: @Composable () -> Unit) {
-    CompositionLocalProvider(LocalContextMenuData provides data) { content() }
-}
-
-private val LocalContextMenuData = staticCompositionLocalOf<ContextMenuData?> { null }
-
-private fun Modifier.contextMenuDetector(
-    state: ContextMenuState,
-    enabled: Boolean = true
-): Modifier {
-    return if (enabled && state.status == ContextMenuState.Status.Closed) {
-        this.pointerInput(state) {
-            awaitEachGesture {
-                val event = awaitEventFirstDown()
-                if (event.buttons.isSecondaryPressed) {
-                    event.changes.forEach { it.consume() }
-                    state.status = ContextMenuState.Status.Open(Rect(event.changes[0].position, 0f))
-                }
-            }
-        }
-    } else {
-        Modifier
-    }
-}
-
-private suspend fun AwaitPointerEventScope.awaitEventFirstDown(): PointerEvent {
-    var event: PointerEvent
-    do {
-        event = awaitPointerEvent()
-    } while (!event.changes.fastAll { it.changedToDown() })
-    return event
-}
-
-/**
- * Individual element of context menu.
- *
- * @param label The text to be displayed as a context menu item.
- * @param onClick The action to be executed after click on the item.
- */
-class ContextMenuItem(val label: String, val onClick: () -> Unit) {
-    override fun equals(other: Any?): Boolean {
-        if (this === other) return true
-        if (other == null || this::class != other::class) return false
-
-        other as ContextMenuItem
-
-        if (label != other.label) return false
-        if (onClick != other.onClick) return false
-
-        return true
-    }
-
-    override fun hashCode(): Int {
-        var result = label.hashCode()
-        result = 31 * result + onClick.hashCode()
-        return result
-    }
-
-    override fun toString(): String {
-        return "ContextMenuItem(label='$label')"
-    }
-}
-
-/**
- * Data container contains all [ContextMenuItem]s were defined previously in the hierarchy.
- * [ContextMenuRepresentation] uses it to display context menu.
- */
-class ContextMenuData(val items: () -> List<ContextMenuItem>, val next: ContextMenuData?) {
-
-    internal val allItems: List<ContextMenuItem> by lazy { allItemsSeq.toList() }
-
-    internal val allItemsSeq: Sequence<ContextMenuItem>
-        get() = sequence {
-            yieldAll(items())
-            next?.let { yieldAll(it.allItemsSeq) }
-        }
-
-    override fun equals(other: Any?): Boolean {
-        if (this === other) return true
-        if (other == null || this::class != other::class) return false
-
-        other as ContextMenuData
-
-        if (items != other.items) return false
-        if (next != other.next) return false
-
-        return true
-    }
-
-    override fun hashCode(): Int {
-        var result = items.hashCode()
-        result = 31 * result + (next?.hashCode() ?: 0)
-        return result
-    }
-}
-
-/**
- * Represents a state of context menu in [ContextMenuArea]. [status] is implemented via
- * [androidx.compose.runtime.MutableState] so it's possible to track it inside @Composable
- * functions.
- */
-class ContextMenuState {
-    sealed class Status {
-        class Open(val rect: Rect) : Status() {
-            override fun equals(other: Any?): Boolean {
-                if (this === other) return true
-                if (other == null || this::class != other::class) return false
-
-                other as Open
-
-                if (rect != other.rect) return false
-
-                return true
-            }
-
-            override fun hashCode(): Int {
-                return rect.hashCode()
-            }
-
-            override fun toString(): String {
-                return "Open(rect=$rect)"
-            }
-        }
-
-        object Closed : Status()
-    }
-
-    var status: Status by mutableStateOf(Status.Closed)
-}
-
-/**
- * Implementations of this interface are responsible for displaying context menus. There are two
- * implementations out of the box: [LightDefaultContextMenuRepresentation] and
- * [DarkDefaultContextMenuRepresentation]. To change currently used representation, different value
- * for [LocalContextMenuRepresentation] could be provided.
- */
-interface ContextMenuRepresentation {
-    @Composable fun Representation(state: ContextMenuState, items: List<ContextMenuItem>)
-}
-
-/** Composition local that keeps [ContextMenuRepresentation] which is used by [ContextMenuArea]s. */
-val LocalContextMenuRepresentation: ProvidableCompositionLocal<ContextMenuRepresentation> =
-    staticCompositionLocalOf {
-        LightDefaultContextMenuRepresentation
-    }
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/DarkTheme.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/DarkTheme.desktop.kt
deleted file mode 100644
index 7021d2e..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/DarkTheme.desktop.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation
-
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.ReadOnlyComposable
-import org.jetbrains.skiko.SystemTheme
-import org.jetbrains.skiko.currentSystemTheme
-
-/**
- * This function should be used to help build responsive UIs that follow the system setting, to
- * avoid harsh contrast changes when switching between applications.
- *
- * This function returns `true` if the [Configuration.UI_MODE_NIGHT_YES] bit is set. It is also
- * possible for this bit to be [Configuration.UI_MODE_NIGHT_UNDEFINED], in which case light theme is
- * treated as the default, and this function returns `false`.
- *
- * It is also recommended to provide user accessible overrides in your application, so users can
- * choose to force an always-light or always-dark theme. To do this, you should provide the current
- * theme value in a CompositionLocal or similar to components further down your hierarchy, only
- * calling this effect once at the top level if no user override has been set. This also helps avoid
- * multiple calls to this effect, which can be expensive as it queries system configuration.
- *
- * For example, to draw a white rectangle when in dark theme, and a black rectangle when in light
- * theme:
- *
- * @sample androidx.compose.foundation.samples.DarkThemeSample
- * @return `true` if the system is considered to be in 'dark theme'.
- */
-@Composable
-@ReadOnlyComposable
-internal actual fun _isSystemInDarkTheme(): Boolean {
-    return currentSystemTheme == SystemTheme.DARK
-}
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/DesktopOverscroll.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/DesktopOverscroll.desktop.kt
deleted file mode 100644
index 94ca5b1..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/DesktopOverscroll.desktop.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation
-
-import androidx.compose.runtime.Composable
-
-@Composable internal actual fun rememberOverscrollEffect(): OverscrollEffect = NoOpOverscrollEffect
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/DesktopPlatform.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/DesktopPlatform.desktop.kt
deleted file mode 100644
index 15969ef..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/DesktopPlatform.desktop.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation
-
-internal enum class DesktopPlatform {
-    Linux,
-    Windows,
-    MacOS,
-    Unknown;
-
-    companion object {
-        /** Identify OS on which the application is currently running. */
-        val Current: DesktopPlatform by lazy {
-            val name = System.getProperty("os.name")
-            when {
-                name?.startsWith("Linux") == true -> Linux
-                name?.startsWith("Win") == true -> Windows
-                name == "Mac OS X" -> MacOS
-                else -> Unknown
-            }
-        }
-    }
-}
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/Scrollbar.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/Scrollbar.desktop.kt
deleted file mode 100644
index 95b8e38..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/Scrollbar.desktop.kt
+++ /dev/null
@@ -1,577 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation
-
-import androidx.compose.animation.animateColorAsState
-import androidx.compose.animation.core.TweenSpec
-import androidx.compose.foundation.gestures.awaitEachGesture
-import androidx.compose.foundation.gestures.awaitFirstDown
-import androidx.compose.foundation.gestures.detectTapAndPress
-import androidx.compose.foundation.gestures.drag
-import androidx.compose.foundation.gestures.scrollBy
-import androidx.compose.foundation.interaction.DragInteraction
-import androidx.compose.foundation.interaction.MutableInteractionSource
-import androidx.compose.foundation.interaction.collectIsHoveredAsState
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.lazy.LazyListState
-import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.CompositionLocal
-import androidx.compose.runtime.DisposableEffect
-import androidx.compose.runtime.Immutable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.MutableState
-import androidx.compose.runtime.derivedStateOf
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.rememberUpdatedState
-import androidx.compose.runtime.setValue
-import androidx.compose.runtime.staticCompositionLocalOf
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.composed
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.Shape
-import androidx.compose.ui.input.pointer.pointerInput
-import androidx.compose.ui.input.pointer.positionChange
-import androidx.compose.ui.layout.Layout
-import androidx.compose.ui.layout.MeasurePolicy
-import androidx.compose.ui.platform.LocalDensity
-import androidx.compose.ui.platform.LocalLayoutDirection
-import androidx.compose.ui.unit.Constraints
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.LayoutDirection
-import androidx.compose.ui.unit.constrainHeight
-import androidx.compose.ui.unit.constrainWidth
-import androidx.compose.ui.unit.dp
-import kotlin.math.abs
-import kotlin.math.roundToInt
-import kotlin.math.sign
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.runBlocking
-
-/**
- * [CompositionLocal] used to pass [ScrollbarStyle] down the tree. This value is typically set in
- * some "Theme" composable function (DesktopTheme, MaterialTheme)
- */
-val LocalScrollbarStyle = staticCompositionLocalOf { defaultScrollbarStyle() }
-
-/**
- * Defines visual style of scrollbars (thickness, shapes, colors, etc). Can be passed as a parameter
- * of scrollbar through [LocalScrollbarStyle]
- */
-@Immutable
-data class ScrollbarStyle(
-    val minimalHeight: Dp,
-    val thickness: Dp,
-    val shape: Shape,
-    val hoverDurationMillis: Int,
-    val unhoverColor: Color,
-    val hoverColor: Color
-)
-
-/** Simple default [ScrollbarStyle] without applying MaterialTheme. */
-fun defaultScrollbarStyle() =
-    ScrollbarStyle(
-        minimalHeight = 16.dp,
-        thickness = 8.dp,
-        shape = RoundedCornerShape(4.dp),
-        hoverDurationMillis = 300,
-        unhoverColor = Color.Black.copy(alpha = 0.12f),
-        hoverColor = Color.Black.copy(alpha = 0.50f)
-    )
-
-/**
- * Vertical scrollbar that can be attached to some scrollable component (ScrollableColumn,
- * LazyColumn) and share common state with it.
- *
- * Can be placed independently.
- *
- * Example: val state = rememberScrollState(0f)
- *
- *     Box(Modifier.fillMaxSize()) {
- *         Box(modifier = Modifier.verticalScroll(state)) {
- *             ...
- *         }
- *         VerticalScrollbar(
- *             Modifier.align(Alignment.CenterEnd).fillMaxHeight(),
- *             rememberScrollbarAdapter(state)
- *         )
- *     }
- *
- * @param adapter [ScrollbarAdapter] that will be used to communicate with scrollable component
- * @param modifier the modifier to apply to this layout
- * @param reverseLayout reverse the direction of scrolling and layout, when `true` and
- *   [LazyListState.firstVisibleItemIndex] == 0 then scrollbar will be at the bottom of the
- *   container. It is usually used in pair with `LazyColumn(reverseLayout = true)`
- * @param style [ScrollbarStyle] to define visual style of scrollbar
- * @param interactionSource optional [MutableInteractionSource] that will be used to dispatch
- *   [DragInteraction.Start] when this Scrollbar is being dragged.
- */
-@Composable
-fun VerticalScrollbar(
-    adapter: ScrollbarAdapter,
-    modifier: Modifier = Modifier,
-    reverseLayout: Boolean = false,
-    style: ScrollbarStyle = LocalScrollbarStyle.current,
-    interactionSource: MutableInteractionSource? = null
-) = Scrollbar(adapter, modifier, reverseLayout, style, interactionSource, isVertical = true)
-
-/**
- * Horizontal scrollbar that can be attached to some scrollable component
- * (Modifier.verticalScroll(), LazyRow) and share common state with it.
- *
- * Can be placed independently.
- *
- * Example: val state = rememberScrollState(0f)
- *
- *     Box(Modifier.fillMaxSize()) {
- *         Box(modifier = Modifier.verticalScroll(state)) {
- *             ...
- *         }
- *         HorizontalScrollbar(
- *             Modifier.align(Alignment.BottomCenter).fillMaxWidth(),
- *             rememberScrollbarAdapter(state)
- *         )
- *     }
- *
- * @param adapter [ScrollbarAdapter] that will be used to communicate with scrollable component
- * @param modifier the modifier to apply to this layout
- * @param reverseLayout reverse the direction of scrolling and layout, when `true` and
- *   [LazyListState.firstVisibleItemIndex] == 0 then scrollbar will be at the end of the container.
- *   It is usually used in pair with `LazyRow(reverseLayout = true)`
- * @param style [ScrollbarStyle] to define visual style of scrollbar
- * @param interactionSource optional [MutableInteractionSource] that will be used to dispatch
- *   [DragInteraction.Start] when this Scrollbar is being dragged.
- */
-@Composable
-fun HorizontalScrollbar(
-    adapter: ScrollbarAdapter,
-    modifier: Modifier = Modifier,
-    reverseLayout: Boolean = false,
-    style: ScrollbarStyle = LocalScrollbarStyle.current,
-    interactionSource: MutableInteractionSource? = null
-) =
-    Scrollbar(
-        adapter,
-        modifier,
-        if (LocalLayoutDirection.current == LayoutDirection.Rtl) !reverseLayout else reverseLayout,
-        style,
-        interactionSource,
-        isVertical = false
-    )
-
-// TODO(demin): do we need to stop dragging if cursor is beyond constraints?
-@Composable
-private fun Scrollbar(
-    adapter: ScrollbarAdapter,
-    modifier: Modifier = Modifier,
-    reverseLayout: Boolean,
-    style: ScrollbarStyle,
-    interactionSource: MutableInteractionSource?,
-    isVertical: Boolean
-) =
-    with(LocalDensity.current) {
-        @Suppress("NAME_SHADOWING")
-        val interactionSource = interactionSource ?: remember { MutableInteractionSource() }
-        val dragInteraction = remember { mutableStateOf<DragInteraction.Start?>(null) }
-        DisposableEffect(interactionSource) {
-            onDispose {
-                dragInteraction.value?.let { interaction ->
-                    interactionSource.tryEmit(DragInteraction.Cancel(interaction))
-                    dragInteraction.value = null
-                }
-            }
-        }
-
-        var containerSize by remember { mutableStateOf(0) }
-        val isHovered by interactionSource.collectIsHoveredAsState()
-
-        val isHighlighted by remember {
-            derivedStateOf { isHovered || dragInteraction.value is DragInteraction.Start }
-        }
-
-        val minimalHeight = style.minimalHeight.toPx()
-        val sliderAdapter =
-            remember(adapter, containerSize, minimalHeight, reverseLayout) {
-                SliderAdapter(adapter, containerSize, minimalHeight, reverseLayout)
-            }
-
-        val scrollThickness = style.thickness.roundToPx()
-        val measurePolicy =
-            if (isVertical) {
-                remember(sliderAdapter, scrollThickness) {
-                    verticalMeasurePolicy(sliderAdapter, { containerSize = it }, scrollThickness)
-                }
-            } else {
-                remember(sliderAdapter, scrollThickness) {
-                    horizontalMeasurePolicy(sliderAdapter, { containerSize = it }, scrollThickness)
-                }
-            }
-
-        val color by
-            animateColorAsState(
-                if (isHighlighted) style.hoverColor else style.unhoverColor,
-                animationSpec = TweenSpec(durationMillis = style.hoverDurationMillis)
-            )
-
-        val isVisible = sliderAdapter.size < containerSize
-
-        Layout(
-            {
-                Box(
-                    Modifier.background(if (isVisible) color else Color.Transparent, style.shape)
-                        .scrollbarDrag(
-                            interactionSource = interactionSource,
-                            draggedInteraction = dragInteraction,
-                            onDelta = { offset ->
-                                sliderAdapter.rawPosition += if (isVertical) offset.y else offset.x
-                            },
-                            onFinished = { sliderAdapter.rawPosition = sliderAdapter.position }
-                        )
-                )
-            },
-            modifier
-                .hoverable(interactionSource = interactionSource)
-                .scrollOnPressOutsideSlider(isVertical, sliderAdapter, adapter, containerSize),
-            measurePolicy
-        )
-    }
-
-private fun Modifier.scrollbarDrag(
-    interactionSource: MutableInteractionSource,
-    draggedInteraction: MutableState<DragInteraction.Start?>,
-    onDelta: (Offset) -> Unit,
-    onFinished: () -> Unit
-): Modifier = composed {
-    val currentInteractionSource by rememberUpdatedState(interactionSource)
-    val currentDraggedInteraction by rememberUpdatedState(draggedInteraction)
-    val currentOnDelta by rememberUpdatedState(onDelta)
-    val currentOnFinished by rememberUpdatedState(onFinished)
-    pointerInput(Unit) {
-        awaitEachGesture {
-            val down = awaitFirstDown(requireUnconsumed = false)
-            val interaction = DragInteraction.Start()
-            currentInteractionSource.tryEmit(interaction)
-            currentDraggedInteraction.value = interaction
-            val isSuccess =
-                drag(down.id) { change ->
-                    currentOnDelta.invoke(change.positionChange())
-                    change.consume()
-                }
-            val finishInteraction =
-                if (isSuccess) {
-                    DragInteraction.Stop(interaction)
-                } else {
-                    DragInteraction.Cancel(interaction)
-                }
-            currentInteractionSource.tryEmit(finishInteraction)
-            currentDraggedInteraction.value = null
-            currentOnFinished.invoke()
-        }
-    }
-}
-
-private fun Modifier.scrollOnPressOutsideSlider(
-    isVertical: Boolean,
-    sliderAdapter: SliderAdapter,
-    scrollbarAdapter: ScrollbarAdapter,
-    containerSize: Int
-) = composed {
-    var targetOffset: Offset? by remember { mutableStateOf(null) }
-
-    if (targetOffset != null) {
-        val targetPosition = if (isVertical) targetOffset!!.y else targetOffset!!.x
-
-        LaunchedEffect(targetPosition) {
-            var delay = PressTimeoutMillis * 3
-            while (targetPosition !in sliderAdapter.bounds) {
-                val oldSign = sign(targetPosition - sliderAdapter.position)
-                scrollbarAdapter.scrollTo(
-                    containerSize,
-                    scrollbarAdapter.scrollOffset + oldSign * containerSize
-                )
-                val newSign = sign(targetPosition - sliderAdapter.position)
-
-                if (oldSign != newSign) {
-                    break
-                }
-
-                delay(delay)
-                delay = PressTimeoutMillis
-            }
-        }
-    }
-    Modifier.pointerInput(Unit) {
-        detectTapAndPress(
-            onPress = { offset ->
-                targetOffset = offset
-                tryAwaitRelease()
-                targetOffset = null
-            },
-            onTap = {}
-        )
-    }
-}
-
-/**
- * Create and [remember] [ScrollbarAdapter] for scrollable container and current instance of
- * [scrollState]
- */
-@Composable
-fun rememberScrollbarAdapter(scrollState: ScrollState): ScrollbarAdapter =
-    remember(scrollState) { ScrollbarAdapter(scrollState) }
-
-/**
- * Create and [remember] [ScrollbarAdapter] for lazy scrollable container and current instance of
- * [scrollState]
- */
-@Composable
-fun rememberScrollbarAdapter(
-    scrollState: LazyListState,
-): ScrollbarAdapter {
-    return remember(scrollState) { ScrollbarAdapter(scrollState) }
-}
-
-/**
- * ScrollbarAdapter for Modifier.verticalScroll and Modifier.horizontalScroll
- *
- * [scrollState] is instance of [ScrollState] which is used by scrollable component
- *
- * Example: val state = rememberScrollState(0f)
- *
- *     Box(Modifier.fillMaxSize()) {
- *         Box(modifier = Modifier.verticalScroll(state)) {
- *             ...
- *         }
- *         VerticalScrollbar(
- *             Modifier.align(Alignment.CenterEnd).fillMaxHeight(),
- *             rememberScrollbarAdapter(state)
- *         )
- *     }
- */
-fun ScrollbarAdapter(scrollState: ScrollState): ScrollbarAdapter =
-    ScrollableScrollbarAdapter(scrollState)
-
-private class ScrollableScrollbarAdapter(private val scrollState: ScrollState) : ScrollbarAdapter {
-    override val scrollOffset: Float
-        get() = scrollState.value.toFloat()
-
-    override suspend fun scrollTo(containerSize: Int, scrollOffset: Float) {
-        scrollState.scrollTo(scrollOffset.roundToInt())
-    }
-
-    override fun maxScrollOffset(containerSize: Int) = scrollState.maxValue.toFloat()
-}
-
-/**
- * ScrollbarAdapter for lazy lists.
- *
- * [scrollState] is instance of [LazyListState] which is used by scrollable component
- *
- * Scrollbar size and position will be dynamically changed on the current visible content.
- *
- * Example: Box(Modifier.fillMaxSize()) { val state = rememberLazyListState()
- *
- *         LazyColumn(state = state) {
- *             ...
- *         }
- *         VerticalScrollbar(
- *             Modifier.align(Alignment.CenterEnd),
- *             rememberScrollbarAdapter(state)
- *         )
- *     }
- */
-fun ScrollbarAdapter(scrollState: LazyListState): ScrollbarAdapter =
-    LazyScrollbarAdapter(scrollState)
-
-private class LazyScrollbarAdapter(private val scrollState: LazyListState) : ScrollbarAdapter {
-    override val scrollOffset: Float
-        get() =
-            scrollState.firstVisibleItemIndex * averageItemSize +
-                scrollState.firstVisibleItemScrollOffset
-
-    override suspend fun scrollTo(containerSize: Int, scrollOffset: Float) {
-        val distance = scrollOffset - [email protected]
-
-        // if we scroll less than containerSize we need to use scrollBy function to avoid
-        // undesirable scroll jumps (when an item size is different)
-        //
-        // if we scroll more than containerSize we should immediately jump to this position
-        // without recreating all items between the current and the new position
-        if (abs(distance) <= containerSize) {
-            scrollState.scrollBy(distance)
-        } else {
-            snapTo(containerSize, scrollOffset)
-        }
-    }
-
-    private suspend fun snapTo(containerSize: Int, scrollOffset: Float) {
-        // In case of very big values, we can catch an overflow, so convert values to double and
-        // coerce them
-        //        val averageItemSize = 26.000002f
-        //        val scrollOffsetCoerced = 2.54490608E8.toFloat()
-        //        val index = (scrollOffsetCoerced / averageItemSize).toInt() // 9788100
-        //        val offset = (scrollOffsetCoerced - index * averageItemSize) // -16.0
-        //        println(offset)
-
-        val maximumValue = maxScrollOffset(containerSize).toDouble()
-        val scrollOffsetCoerced = scrollOffset.toDouble().coerceIn(0.0, maximumValue)
-        val averageItemSize = averageItemSize.toDouble()
-
-        val index =
-            (scrollOffsetCoerced / averageItemSize)
-                .toInt()
-                .coerceAtLeast(0)
-                .coerceAtMost(itemCount - 1)
-
-        val offset = (scrollOffsetCoerced - index * averageItemSize).toInt().coerceAtLeast(0)
-
-        scrollState.scrollToItem(index = index, scrollOffset = offset)
-    }
-
-    override fun maxScrollOffset(containerSize: Int) =
-        (averageItemSize * itemCount - containerSize).coerceAtLeast(0f)
-
-    private val itemCount
-        get() = scrollState.layoutInfo.totalItemsCount
-
-    private val averageItemSize by derivedStateOf {
-        scrollState.layoutInfo.visibleItemsInfo.asSequence().map { it.size }.average().toFloat()
-    }
-}
-
-/** Defines how to scroll the scrollable component */
-interface ScrollbarAdapter {
-    /**
-     * Scroll offset of the content inside the scrollable component. Offset "100" means that the
-     * content is scrolled by 100 pixels from the start.
-     */
-    val scrollOffset: Float
-
-    /**
-     * Instantly jump to [scrollOffset] in pixels
-     *
-     * @param containerSize size of the scrollable container (for example, it is height of
-     *   ScrollableColumn if we use VerticalScrollbar)
-     * @param scrollOffset target value in pixels to jump to, value will be coerced to
-     *   0..maxScrollOffset
-     */
-    suspend fun scrollTo(containerSize: Int, scrollOffset: Float)
-
-    /**
-     * Maximum scroll offset of the content inside the scrollable component
-     *
-     * @param containerSize size of the scrollable component (for example, it is height of
-     *   ScrollableColumn if we use VerticalScrollbar)
-     */
-    fun maxScrollOffset(containerSize: Int): Float
-}
-
-private class SliderAdapter(
-    val adapter: ScrollbarAdapter,
-    val containerSize: Int,
-    val minHeight: Float,
-    val reverseLayout: Boolean
-) {
-    private val contentSize
-        get() = adapter.maxScrollOffset(containerSize) + containerSize
-
-    private val visiblePart
-        get() = containerSize.toFloat() / contentSize
-
-    val size
-        get() =
-            (containerSize * visiblePart)
-                .coerceAtLeast(minHeight)
-                .coerceAtMost(containerSize.toFloat())
-
-    private val scrollScale: Float
-        get() {
-            val extraScrollbarSpace = containerSize - size
-            val extraContentSpace = contentSize - containerSize
-            return if (extraContentSpace == 0f) 1f else extraScrollbarSpace / extraContentSpace
-        }
-
-    /** A position with cumulative offset, may be out of the container when dragging */
-    var rawPosition: Float = position
-        set(value) {
-            field = value
-            position = value
-        }
-
-    /** Actual scroll of content regarding slider layout */
-    private var scrollPosition: Float
-        get() = scrollScale * adapter.scrollOffset
-        set(value) {
-            runBlocking { adapter.scrollTo(containerSize, value / scrollScale) }
-        }
-
-    /** Actual position of a thumb within slider container */
-    var position: Float
-        get() = if (reverseLayout) containerSize - size - scrollPosition else scrollPosition
-        set(value) {
-            scrollPosition =
-                if (reverseLayout) {
-                    containerSize - size - value
-                } else {
-                    value
-                }
-        }
-
-    val bounds
-        get() = position..position + size
-}
-
-private fun verticalMeasurePolicy(
-    sliderAdapter: SliderAdapter,
-    setContainerSize: (Int) -> Unit,
-    scrollThickness: Int
-) = MeasurePolicy { measurables, constraints ->
-    setContainerSize(constraints.maxHeight)
-    val height = sliderAdapter.size.toInt()
-    val placeable =
-        measurables
-            .first()
-            .measure(Constraints.fixed(constraints.constrainWidth(scrollThickness), height))
-    layout(placeable.width, constraints.maxHeight) {
-        placeable.place(0, sliderAdapter.position.toInt())
-    }
-}
-
-private fun horizontalMeasurePolicy(
-    sliderAdapter: SliderAdapter,
-    setContainerSize: (Int) -> Unit,
-    scrollThickness: Int
-) = MeasurePolicy { measurables, constraints ->
-    setContainerSize(constraints.maxWidth)
-    val width = sliderAdapter.size.toInt()
-    val placeable =
-        measurables
-            .first()
-            .measure(Constraints.fixed(width, constraints.constrainHeight(scrollThickness)))
-    layout(constraints.maxWidth, placeable.height) {
-        placeable.place(sliderAdapter.position.toInt(), 0)
-    }
-}
-
-/**
- * The time that must elapse before a tap gesture sends onTapDown, if there's any doubt that the
- * gesture is a tap.
- */
-private const val PressTimeoutMillis: Long = 100L
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/TooltipArea.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/TooltipArea.desktop.kt
deleted file mode 100644
index cb4460ec..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/TooltipArea.desktop.kt
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation
-
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.rememberCoroutineScope
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.input.pointer.PointerEventPass
-import androidx.compose.ui.input.pointer.PointerEventType
-import androidx.compose.ui.input.pointer.PointerInputScope
-import androidx.compose.ui.input.pointer.changedToDown
-import androidx.compose.ui.input.pointer.pointerInput
-import androidx.compose.ui.layout.onGloballyPositioned
-import androidx.compose.ui.layout.positionInWindow
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.DpOffset
-import androidx.compose.ui.unit.IntOffset
-import androidx.compose.ui.unit.IntRect
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.window.PopupPositionProvider
-import androidx.compose.ui.window.rememberComponentRectPositionProvider
-import androidx.compose.ui.window.rememberCursorPositionProvider
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.launch
-
-/**
- * Sets the tooltip for an element.
- *
- * @param tooltip Composable content of the tooltip.
- * @param modifier The modifier to be applied to the layout.
- * @param contentAlignment The default alignment inside the Box.
- * @param propagateMinConstraints Whether the incoming min constraints should be passed to content.
- * @param delay Delay in milliseconds.
- * @param tooltipPlacement Defines position of the tooltip.
- * @param content Composable content that the current tooltip is set to.
- */
-@Composable
-@Deprecated(
-    "Use TooltipArea",
-    replaceWith = ReplaceWith("TooltipArea(tooltip, modifier, delay, tooltipPlacement, content)")
-)
-@Suppress("UNUSED_PARAMETER")
-fun BoxWithTooltip(
-    tooltip: @Composable () -> Unit,
-    modifier: Modifier = Modifier,
-    contentAlignment: Alignment = Alignment.TopStart,
-    propagateMinConstraints: Boolean = false,
-    delay: Int = 500,
-    tooltipPlacement: TooltipPlacement =
-        TooltipPlacement.CursorPoint(offset = DpOffset(0.dp, 16.dp)),
-    content: @Composable () -> Unit
-) = TooltipArea(tooltip, modifier, delay, tooltipPlacement, content)
-
-/**
- * Sets the tooltip for an element.
- *
- * @param tooltip Composable content of the tooltip.
- * @param modifier The modifier to be applied to the layout.
- * @param delayMillis Delay in milliseconds.
- * @param tooltipPlacement Defines position of the tooltip.
- * @param content Composable content that the current tooltip is set to.
- */
-@Composable
-fun TooltipArea(
-    tooltip: @Composable () -> Unit,
-    modifier: Modifier = Modifier,
-    delayMillis: Int = 500,
-    tooltipPlacement: TooltipPlacement =
-        TooltipPlacement.CursorPoint(offset = DpOffset(0.dp, 16.dp)),
-    content: @Composable () -> Unit
-) {
-    val mousePosition = remember { mutableStateOf(IntOffset.Zero) }
-    var parentBounds by remember { mutableStateOf(IntRect.Zero) }
-    val state = rememberBasicTooltipState(initialIsVisible = false)
-    val scope = rememberCoroutineScope()
-    var job: Job? by remember { mutableStateOf(null) }
-
-    fun startShowing() {
-        job?.cancel()
-        job =
-            scope.launch {
-                delay(delayMillis.toLong())
-                state.show()
-            }
-    }
-
-    fun hide() {
-        job?.cancel()
-        state.dismiss()
-    }
-
-    BasicTooltipBox(
-        positionProvider = tooltipPlacement.positionProvider(),
-        tooltip = tooltip,
-        modifier =
-            modifier
-                .onGloballyPositioned { coordinates ->
-                    val size = coordinates.size
-                    val position =
-                        IntOffset(
-                            coordinates.positionInWindow().x.toInt(),
-                            coordinates.positionInWindow().y.toInt()
-                        )
-                    parentBounds = IntRect(position, size)
-                }
-                /** TODO: b/296850580 Figure out touch input story for desktop */
-                .pointerInput(Unit) {
-                    awaitPointerEventScope {
-                        while (true) {
-                            val event = awaitPointerEvent()
-                            val position = event.changes.first().position
-                            when (event.type) {
-                                PointerEventType.Move -> {
-                                    mousePosition.value =
-                                        IntOffset(
-                                            position.x.toInt() + parentBounds.left,
-                                            position.y.toInt() + parentBounds.top
-                                        )
-                                }
-                                PointerEventType.Enter -> {
-                                    startShowing()
-                                }
-                                PointerEventType.Exit -> {
-                                    hide()
-                                }
-                            }
-                        }
-                    }
-                }
-                .pointerInput(Unit) { detectDown { hide() } },
-        focusable = false,
-        enableUserInput = true,
-        state = state,
-        content = content
-    )
-}
-
-private suspend fun PointerInputScope.detectDown(onDown: (Offset) -> Unit) {
-    while (true) {
-        awaitPointerEventScope {
-            val event = awaitPointerEvent(PointerEventPass.Initial)
-            val down = event.changes.find { it.changedToDown() }
-            if (down != null) {
-                onDown(down.position)
-            }
-        }
-    }
-}
-
-/** An interface for providing a [PopupPositionProvider] for the tooltip. */
-interface TooltipPlacement {
-    /** Returns [PopupPositionProvider] implementation. */
-    @Composable fun positionProvider(): PopupPositionProvider
-
-    /**
-     * [TooltipPlacement] implementation for providing a [PopupPositionProvider] that calculates the
-     * position of the popup relative to the current mouse cursor position.
-     *
-     * @param offset [DpOffset] to be added to the position of the popup.
-     * @param alignment The alignment of the popup relative to the current cursor position.
-     * @param windowMargin Defines the area within the window that limits the placement of the
-     *   popup.
-     */
-    class CursorPoint(
-        private val offset: DpOffset = DpOffset.Zero,
-        private val alignment: Alignment = Alignment.BottomEnd,
-        private val windowMargin: Dp = 4.dp
-    ) : TooltipPlacement {
-        @Composable
-        override fun positionProvider() =
-            rememberCursorPositionProvider(offset, alignment, windowMargin)
-    }
-
-    /**
-     * [TooltipPlacement] implementation for providing a [PopupPositionProvider] that calculates the
-     * position of the popup relative to the current component bounds.
-     *
-     * @param anchor The anchor point relative to the current component bounds.
-     * @param alignment The alignment of the popup relative to the [anchor] point.
-     * @param offset [DpOffset] to be added to the position of the popup.
-     */
-    class ComponentRect(
-        private val anchor: Alignment = Alignment.BottomCenter,
-        private val alignment: Alignment = Alignment.BottomCenter,
-        private val offset: DpOffset = DpOffset.Zero
-    ) : TooltipPlacement {
-        @Composable
-        override fun positionProvider() =
-            rememberComponentRectPositionProvider(anchor, alignment, offset)
-    }
-}
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/content/TransferableContent.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/content/TransferableContent.desktop.kt
deleted file mode 100644
index 4ace256..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/content/TransferableContent.desktop.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.content
-
-import androidx.compose.foundation.ExperimentalFoundationApi
-import androidx.compose.ui.platform.ClipEntry
-import java.awt.datatransfer.DataFlavor
-import java.awt.datatransfer.Transferable
-
-@ExperimentalFoundationApi
-actual class PlatformTransferableContent internal constructor(val transferable: Transferable)
-
-@ExperimentalFoundationApi
-actual fun TransferableContent.hasMediaType(mediaType: MediaType): Boolean {
-    return clipMetadata.isDataFlavorSupported(mediaType.dataFlavor)
-}
-
-internal actual fun ClipEntry.readPlainText(): String? {
-    return getTransferData(DataFlavor.stringFlavor) as String?
-}
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/content/internal/DragAndDropRequestPermission.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/content/internal/DragAndDropRequestPermission.desktop.kt
deleted file mode 100644
index 3eb9489..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/content/internal/DragAndDropRequestPermission.desktop.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.content.internal
-
-import androidx.compose.ui.draganddrop.DragAndDropEvent
-import androidx.compose.ui.node.DelegatableNode
-
-internal actual fun DelegatableNode.dragAndDropRequestPermission(event: DragAndDropEvent) {
-    /* no-op */
-}
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/content/internal/ReceiveContentDragAndDropNode.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/content/internal/ReceiveContentDragAndDropNode.desktop.kt
deleted file mode 100644
index 8cdfb48..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/content/internal/ReceiveContentDragAndDropNode.desktop.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.content.internal
-
-import androidx.compose.ui.draganddrop.DragAndDropEvent
-import androidx.compose.ui.draganddrop.DragAndDropModifierNode
-
-internal actual fun ReceiveContentDragAndDropNode(
-    receiveContentConfiguration: ReceiveContentConfiguration,
-    dragAndDropRequestPermission: (DragAndDropEvent) -> Unit
-): DragAndDropModifierNode {
-    return DragAndDropModifierNode()
-}
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/gestures/BringIntoViewSpec.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/gestures/BringIntoViewSpec.desktop.kt
deleted file mode 100644
index 4b06618..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/gestures/BringIntoViewSpec.desktop.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.gestures
-
-import androidx.compose.runtime.ProvidableCompositionLocal
-import androidx.compose.runtime.staticCompositionLocalOf
-
-/*
- * A composition local to customize the focus scrolling behavior used by some scrollable containers.
- * [LocalBringIntoViewSpec] has a platform defined behavior. The scroll default behavior will move
- * the least to bring the requested region into view.
- */
-@Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-actual val LocalBringIntoViewSpec: ProvidableCompositionLocal<BringIntoViewSpec> =
-    staticCompositionLocalOf {
-        BringIntoViewSpec.DefaultBringIntoViewSpec
-    }
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/gestures/DesktopScrollable.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/gestures/DesktopScrollable.desktop.kt
deleted file mode 100644
index ec05c06..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/gestures/DesktopScrollable.desktop.kt
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.gestures
-
-import androidx.compose.foundation.DesktopPlatform
-import androidx.compose.runtime.compositionLocalOf
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.input.pointer.PointerEvent
-import androidx.compose.ui.node.CompositionLocalConsumerModifierNode
-import androidx.compose.ui.node.currentValueOf
-import androidx.compose.ui.unit.Density
-import androidx.compose.ui.unit.IntSize
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.util.fastFold
-import java.awt.event.MouseWheelEvent
-import kotlin.math.sqrt
-
-// TODO(demin): Chrome on Windows/Linux uses different scroll strategy
-//  (always the same scroll offset, bounds-independent).
-//  Figure out why and decide if we can use this strategy instead of the current one.
-internal val LocalScrollConfig = compositionLocalOf {
-    when (DesktopPlatform.Current) {
-        DesktopPlatform.Linux -> LinuxGnomeConfig
-        DesktopPlatform.Windows -> WindowsWinUIConfig
-        DesktopPlatform.MacOS -> MacOSCocoaConfig
-        DesktopPlatform.Unknown -> WindowsWinUIConfig
-    }
-}
-
-internal actual fun CompositionLocalConsumerModifierNode.platformScrollConfig() =
-    currentValueOf(LocalScrollConfig)
-
-// TODO(demin): is this formula actually correct? some experimental values don't fit
-//  the formula
-internal object LinuxGnomeConfig : ScrollConfig {
-    // the formula was determined experimentally based on Ubuntu Nautilus behaviour
-    override fun Density.calculateMouseWheelScroll(event: PointerEvent, bounds: IntSize): Offset {
-        return if (event.shouldScrollByPage) {
-            calculateOffsetByPage(event, bounds)
-        } else {
-            Offset(
-                x = event.totalScrollDelta.x * sqrt(bounds.width.toFloat()),
-                y = event.totalScrollDelta.y * sqrt(bounds.height.toFloat())
-            )
-        } * -event.scrollAmount
-    }
-}
-
-internal object WindowsWinUIConfig : ScrollConfig {
-    // the formula was determined experimentally based on Windows Start behaviour
-    override fun Density.calculateMouseWheelScroll(event: PointerEvent, bounds: IntSize): Offset {
-        return if (event.shouldScrollByPage) {
-            calculateOffsetByPage(event, bounds)
-        } else {
-            Offset(
-                x = event.totalScrollDelta.x * (bounds.width / 20f),
-                y = event.totalScrollDelta.y * (bounds.height / 20f)
-            )
-        } * -event.scrollAmount
-    }
-}
-
-internal object MacOSCocoaConfig : ScrollConfig {
-    // the formula was determined experimentally based on MacOS Finder behaviour
-    // MacOS driver will send events with accelerating delta
-    override fun Density.calculateMouseWheelScroll(event: PointerEvent, bounds: IntSize): Offset {
-        return if (event.shouldScrollByPage) {
-            calculateOffsetByPage(event, bounds)
-        } else {
-            event.totalScrollDelta * 10.dp.toPx()
-        } * -event.scrollAmount
-    }
-}
-
-// TODO(demin): Chrome/Firefox on Windows scroll differently: value * 0.90f * bounds
-// the formula was determined experimentally based on Windows Start behaviour
-private fun calculateOffsetByPage(event: PointerEvent, bounds: IntSize): Offset {
-    return Offset(
-        x = event.totalScrollDelta.x * bounds.width,
-        y = event.totalScrollDelta.y * bounds.height
-    )
-}
-
-private val PointerEvent.scrollAmount
-    get() = (mouseEvent as? MouseWheelEvent)?.scrollAmount?.toFloat() ?: 1f
-
-private val PointerEvent.shouldScrollByPage
-    get() = (mouseEvent as? MouseWheelEvent)?.scrollType == MouseWheelEvent.WHEEL_BLOCK_SCROLL
-
-private val PointerEvent.totalScrollDelta
-    get() = this.changes.fastFold(Offset.Zero) { acc, c -> acc + c.scrollDelta }
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/lazy/layout/Lazy.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/lazy/layout/Lazy.desktop.kt
deleted file mode 100644
index 2f05c01..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/lazy/layout/Lazy.desktop.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.lazy.layout
-
-actual fun getDefaultLazyLayoutKey(index: Int): Any = DefaultLazyKey(index)
-
-private data class DefaultLazyKey(private val index: Int)
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/lazy/layout/PrefetchScheduler.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/lazy/layout/PrefetchScheduler.desktop.kt
deleted file mode 100644
index da15b5f..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/lazy/layout/PrefetchScheduler.desktop.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.lazy.layout
-
-import androidx.compose.foundation.ExperimentalFoundationApi
-import androidx.compose.runtime.Composable
-
-@ExperimentalFoundationApi
-@Composable
-actual fun rememberDefaultPrefetchScheduler(): PrefetchScheduler {
-    return NoOpPrefetchScheduler
-}
-
-@ExperimentalFoundationApi
-private object NoOpPrefetchScheduler : PrefetchScheduler {
-    override fun schedulePrefetch(prefetchRequest: PrefetchRequest) {}
-}
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/relocation/BringIntoViewResponder.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/relocation/BringIntoViewResponder.desktop.kt
deleted file mode 100644
index b9165f3..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/relocation/BringIntoViewResponder.desktop.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.relocation
-
-import androidx.compose.ui.geometry.Rect
-import androidx.compose.ui.layout.LayoutCoordinates
-import androidx.compose.ui.node.DelegatableNode
-
-/** Platform specific internal API to bring a rectangle into view. */
-internal actual fun DelegatableNode.defaultBringIntoViewParent(): BringIntoViewParent =
-    NoopBringIntoViewParent
-
-private object NoopBringIntoViewParent : BringIntoViewParent {
-    override suspend fun bringChildIntoView(
-        childCoordinates: LayoutCoordinates,
-        boundsProvider: () -> Rect?
-    ) {
-        // TODO(b/203204124): Implement this if desktop has a
-        //  concept similar to Android's View.requestRectangleOnScreen.
-    }
-}
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/ContextMenu.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/ContextMenu.desktop.kt
deleted file mode 100644
index 0ea9b78..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/ContextMenu.desktop.kt
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.text
-
-import androidx.compose.foundation.ContextMenuArea
-import androidx.compose.foundation.ContextMenuItem
-import androidx.compose.foundation.ContextMenuState
-import androidx.compose.foundation.DesktopPlatform
-import androidx.compose.foundation.text.input.internal.selection.TextFieldSelectionState
-import androidx.compose.foundation.text.selection.SelectionManager
-import androidx.compose.foundation.text.selection.TextFieldSelectionManager
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.snapshotFlow
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.platform.LocalLocalization
-import androidx.compose.ui.text.input.PasswordVisualTransformation
-
-@Composable
-internal actual fun ContextMenuArea(
-    manager: TextFieldSelectionManager,
-    content: @Composable () -> Unit
-) {
-    val state = remember { ContextMenuState() }
-    if (DesktopPlatform.Current == DesktopPlatform.MacOS) {
-        OpenMenuAdjuster(state) { manager.contextMenuOpenAdjustment(it) }
-    }
-    ContextMenuArea(manager.contextMenuItems(), state, content = content)
-}
-
-// todo implement
-@Composable
-internal actual inline fun ContextMenuArea(
-    selectionState: TextFieldSelectionState,
-    enabled: Boolean,
-    content: @Composable () -> Unit
-) {
-    content()
-}
-
-@Composable
-internal actual fun ContextMenuArea(manager: SelectionManager, content: @Composable () -> Unit) {
-    val state = remember { ContextMenuState() }
-    if (DesktopPlatform.Current == DesktopPlatform.MacOS) {
-        OpenMenuAdjuster(state) { manager.contextMenuOpenAdjustment(it) }
-    }
-    ContextMenuArea(manager.contextMenuItems(), state, content = content)
-}
-
-@Composable
-internal fun OpenMenuAdjuster(state: ContextMenuState, adjustAction: (Offset) -> Unit) {
-    LaunchedEffect(state) {
-        snapshotFlow { state.status }
-            .collect { status ->
-                if (status is ContextMenuState.Status.Open) {
-                    adjustAction(status.rect.center)
-                }
-            }
-    }
-}
-
-@Composable
-internal fun TextFieldSelectionManager.contextMenuItems(): () -> List<ContextMenuItem> {
-    val platformLocalization = LocalLocalization.current
-    return {
-        val result = mutableListOf<ContextMenuItem>()
-        val isPassword = visualTransformation is PasswordVisualTransformation
-        if (!value.selection.collapsed && !isPassword) {
-            result.add(
-                ContextMenuItem(platformLocalization.copy) {
-                    copy(false)
-                    focusRequester?.requestFocus()
-                }
-            )
-        }
-
-        if (!value.selection.collapsed && editable && !isPassword) {
-            result.add(
-                ContextMenuItem(platformLocalization.cut) {
-                    cut()
-                    focusRequester?.requestFocus()
-                }
-            )
-        }
-
-        if (editable && clipboardManager?.getText() != null) {
-            result.add(
-                ContextMenuItem(platformLocalization.paste) {
-                    paste()
-                    focusRequester?.requestFocus()
-                }
-            )
-        }
-
-        if (value.selection.length != value.text.length) {
-            result.add(
-                ContextMenuItem(platformLocalization.selectAll) {
-                    selectAll()
-                    focusRequester?.requestFocus()
-                }
-            )
-        }
-        result
-    }
-}
-
-@Composable
-internal fun SelectionManager.contextMenuItems(): () -> List<ContextMenuItem> {
-    val localization = LocalLocalization.current
-    return { listOf(ContextMenuItem(localization.copy) { copy() }) }
-}
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/DeadKeyCombiner.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/DeadKeyCombiner.desktop.kt
deleted file mode 100644
index 800f0da..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/DeadKeyCombiner.desktop.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.text
-
-import androidx.compose.ui.input.key.KeyEvent
-import androidx.compose.ui.input.key.utf16CodePoint
-
-internal actual class DeadKeyCombiner {
-    // TODO needs actual impl
-    actual fun consume(event: KeyEvent): Int? = event.utf16CodePoint
-}
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/KeyEventHelpers.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/KeyEventHelpers.desktop.kt
deleted file mode 100644
index a0b53a0..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/KeyEventHelpers.desktop.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.text
-
-import androidx.compose.ui.input.key.KeyEvent
-import org.jetbrains.skiko.orderEmojiAndSymbolsPopup
-
-internal actual fun KeyEvent.cancelsTextSelection(): Boolean = false
-
-internal actual fun showCharacterPalette() = orderEmojiAndSymbolsPopup()
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/KeyMapping.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/KeyMapping.desktop.kt
deleted file mode 100644
index 19b8e73..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/KeyMapping.desktop.kt
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.text
-
-import androidx.compose.foundation.DesktopPlatform
-import androidx.compose.ui.input.key.Key
-import androidx.compose.ui.input.key.KeyEvent
-import androidx.compose.ui.input.key.isAltPressed
-import androidx.compose.ui.input.key.isCtrlPressed
-import androidx.compose.ui.input.key.isMetaPressed
-import androidx.compose.ui.input.key.isShiftPressed
-import androidx.compose.ui.input.key.key
-import java.awt.event.KeyEvent as AwtKeyEvent
-
-internal actual val platformDefaultKeyMapping: KeyMapping =
-    when (DesktopPlatform.Current) {
-        DesktopPlatform.MacOS -> {
-            val common = commonKeyMapping(KeyEvent::isMetaPressed)
-            object : KeyMapping {
-                override fun map(event: KeyEvent): KeyCommand? {
-                    return when {
-                        event.isMetaPressed && event.isCtrlPressed ->
-                            when (event.key) {
-                                MappedKeys.Space -> KeyCommand.CHARACTER_PALETTE
-                                else -> null
-                            }
-                        event.isShiftPressed && event.isAltPressed ->
-                            when (event.key) {
-                                MappedKeys.DirectionLeft -> KeyCommand.SELECT_LEFT_WORD
-                                MappedKeys.DirectionRight -> KeyCommand.SELECT_RIGHT_WORD
-                                MappedKeys.DirectionUp -> KeyCommand.SELECT_PREV_PARAGRAPH
-                                MappedKeys.DirectionDown -> KeyCommand.SELECT_NEXT_PARAGRAPH
-                                else -> null
-                            }
-                        event.isShiftPressed && event.isMetaPressed ->
-                            when (event.key) {
-                                MappedKeys.DirectionLeft -> KeyCommand.SELECT_LINE_LEFT
-                                MappedKeys.DirectionRight -> KeyCommand.SELECT_LINE_RIGHT
-                                MappedKeys.DirectionUp -> KeyCommand.SELECT_HOME
-                                MappedKeys.DirectionDown -> KeyCommand.SELECT_END
-                                else -> null
-                            }
-                        event.isMetaPressed ->
-                            when (event.key) {
-                                MappedKeys.DirectionLeft -> KeyCommand.LINE_LEFT
-                                MappedKeys.DirectionRight -> KeyCommand.LINE_RIGHT
-                                MappedKeys.DirectionUp -> KeyCommand.HOME
-                                MappedKeys.DirectionDown -> KeyCommand.END
-                                MappedKeys.Backspace -> KeyCommand.DELETE_FROM_LINE_START
-                                else -> null
-                            }
-
-                        // Emacs-like shortcuts
-                        event.isCtrlPressed && event.isShiftPressed && event.isAltPressed -> {
-                            when (event.key) {
-                                MappedKeys.F -> KeyCommand.SELECT_RIGHT_WORD
-                                MappedKeys.B -> KeyCommand.SELECT_LEFT_WORD
-                                else -> null
-                            }
-                        }
-                        event.isCtrlPressed && event.isAltPressed -> {
-                            when (event.key) {
-                                MappedKeys.F -> KeyCommand.RIGHT_WORD
-                                MappedKeys.B -> KeyCommand.LEFT_WORD
-                                else -> null
-                            }
-                        }
-                        event.isCtrlPressed && event.isShiftPressed -> {
-                            when (event.key) {
-                                MappedKeys.F -> KeyCommand.SELECT_RIGHT_CHAR
-                                MappedKeys.B -> KeyCommand.SELECT_LEFT_CHAR
-                                MappedKeys.P -> KeyCommand.SELECT_UP
-                                MappedKeys.N -> KeyCommand.SELECT_DOWN
-                                MappedKeys.A -> KeyCommand.SELECT_LINE_START
-                                MappedKeys.E -> KeyCommand.SELECT_LINE_END
-                                else -> null
-                            }
-                        }
-                        event.isCtrlPressed -> {
-                            when (event.key) {
-                                MappedKeys.F -> KeyCommand.LEFT_CHAR
-                                MappedKeys.B -> KeyCommand.RIGHT_CHAR
-                                MappedKeys.P -> KeyCommand.UP
-                                MappedKeys.N -> KeyCommand.DOWN
-                                MappedKeys.A -> KeyCommand.LINE_START
-                                MappedKeys.E -> KeyCommand.LINE_END
-                                MappedKeys.H -> KeyCommand.DELETE_PREV_CHAR
-                                MappedKeys.D -> KeyCommand.DELETE_NEXT_CHAR
-                                MappedKeys.K -> KeyCommand.DELETE_TO_LINE_END
-                                MappedKeys.O -> KeyCommand.NEW_LINE
-                                else -> null
-                            }
-                        }
-                        // end of emacs-like shortcuts
-
-                        event.isShiftPressed ->
-                            when (event.key) {
-                                MappedKeys.MoveHome -> KeyCommand.SELECT_HOME
-                                MappedKeys.MoveEnd -> KeyCommand.SELECT_END
-                                else -> null
-                            }
-                        event.isAltPressed ->
-                            when (event.key) {
-                                MappedKeys.DirectionLeft -> KeyCommand.LEFT_WORD
-                                MappedKeys.DirectionRight -> KeyCommand.RIGHT_WORD
-                                MappedKeys.DirectionUp -> KeyCommand.PREV_PARAGRAPH
-                                MappedKeys.DirectionDown -> KeyCommand.NEXT_PARAGRAPH
-                                MappedKeys.Delete -> KeyCommand.DELETE_NEXT_WORD
-                                MappedKeys.Backspace -> KeyCommand.DELETE_PREV_WORD
-                                else -> null
-                            }
-                        else -> null
-                    } ?: common.map(event)
-                }
-            }
-        }
-        else -> defaultKeyMapping
-    }
-
-internal actual object MappedKeys {
-    actual val A: Key = Key(AwtKeyEvent.VK_A)
-    val B: Key = Key(AwtKeyEvent.VK_B)
-    val D: Key = Key(AwtKeyEvent.VK_D)
-    actual val C: Key = Key(AwtKeyEvent.VK_C)
-    val E: Key = Key(AwtKeyEvent.VK_E)
-    val F: Key = Key(AwtKeyEvent.VK_F)
-    actual val H: Key = Key(AwtKeyEvent.VK_H)
-    val K: Key = Key(AwtKeyEvent.VK_K)
-    val N: Key = Key(AwtKeyEvent.VK_N)
-    val O: Key = Key(AwtKeyEvent.VK_O)
-    val P: Key = Key(AwtKeyEvent.VK_P)
-    actual val V: Key = Key(AwtKeyEvent.VK_V)
-    actual val X: Key = Key(AwtKeyEvent.VK_X)
-    actual val Y: Key = Key(AwtKeyEvent.VK_Y)
-    actual val Z: Key = Key(AwtKeyEvent.VK_Z)
-    actual val Backslash: Key = Key(AwtKeyEvent.VK_BACK_SLASH)
-    actual val DirectionLeft: Key = Key(AwtKeyEvent.VK_LEFT)
-    actual val DirectionRight: Key = Key(AwtKeyEvent.VK_RIGHT)
-    actual val DirectionUp: Key = Key(AwtKeyEvent.VK_UP)
-    actual val DirectionDown: Key = Key(AwtKeyEvent.VK_DOWN)
-    actual val PageUp: Key = Key(AwtKeyEvent.VK_PAGE_UP)
-    actual val PageDown: Key = Key(AwtKeyEvent.VK_PAGE_DOWN)
-    actual val MoveHome: Key = Key(AwtKeyEvent.VK_HOME)
-    actual val MoveEnd: Key = Key(AwtKeyEvent.VK_END)
-    actual val Insert: Key = Key(AwtKeyEvent.VK_INSERT)
-    actual val Enter: Key = Key(AwtKeyEvent.VK_ENTER)
-    actual val Backspace: Key = Key(AwtKeyEvent.VK_BACK_SPACE)
-    actual val Delete: Key = Key(AwtKeyEvent.VK_DELETE)
-    actual val Paste: Key = Key(AwtKeyEvent.VK_PASTE)
-    actual val Cut: Key = Key(AwtKeyEvent.VK_CUT)
-    actual val Copy: Key = Key(AwtKeyEvent.VK_COPY)
-    actual val Tab: Key = Key(AwtKeyEvent.VK_TAB)
-    val Space: Key = Key(AwtKeyEvent.VK_SPACE)
-}
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/StringHelpers.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/StringHelpers.desktop.kt
deleted file mode 100644
index 43c84e4..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/StringHelpers.desktop.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.text
-
-import org.jetbrains.skia.BreakIterator
-
-internal actual fun String.findPrecedingBreak(index: Int): Int {
-    val it = BreakIterator.makeCharacterInstance()
-    it.setText(this)
-    return it.preceding(index)
-}
-
-internal actual fun String.findFollowingBreak(index: Int): Int {
-    val it = BreakIterator.makeCharacterInstance()
-    it.setText(this)
-    return it.following(index)
-}
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/TextFieldFocusModifier.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/TextFieldFocusModifier.desktop.kt
deleted file mode 100644
index 2c336bbe..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/TextFieldFocusModifier.desktop.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.text
-
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.focus.FocusManager
-
-/**
- * TextField consumes the D-pad keys, due to which we can't move focus once a TextField is focused.
- * To prevent this, this modifier can be used to intercept D-pad key events before they are sent to
- * the TextField. It intercepts and handles the directional (Up, Down, Left, Right & Center) D-pad
- * key presses, to move the focus between TextField and other focusable items on the screen.
- *
- * TODO: To be implemented if there's any specific handling required for desktop platform
- */
-internal actual fun Modifier.interceptDPadAndMoveFocus(
-    state: LegacyTextFieldState,
-    focusManager: FocusManager
-): Modifier = this
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/TextFieldKeyInput.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/TextFieldKeyInput.desktop.kt
deleted file mode 100644
index c56f4b3..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/TextFieldKeyInput.desktop.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.text
-
-import androidx.compose.ui.input.key.KeyEvent
-
-private fun Char.isPrintable(): Boolean {
-    val block = Character.UnicodeBlock.of(this)
-    return (!Character.isISOControl(this)) &&
-        this != java.awt.event.KeyEvent.CHAR_UNDEFINED &&
-        block != null &&
-        block != Character.UnicodeBlock.SPECIALS
-}
-
-actual val KeyEvent.isTypedEvent: Boolean
-    get() =
-        nativeKeyEvent.id == java.awt.event.KeyEvent.KEY_TYPED &&
-            nativeKeyEvent.keyChar.isPrintable()
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/TextPointerIcon.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/TextPointerIcon.desktop.kt
deleted file mode 100644
index 7e76272..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/TextPointerIcon.desktop.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.text
-
-import androidx.compose.ui.input.pointer.PointerIcon
-import java.awt.Cursor
-
-internal actual val textPointerIcon: PointerIcon = PointerIcon(Cursor(Cursor.TEXT_CURSOR))
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/TouchMode.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/TouchMode.desktop.kt
deleted file mode 100644
index 091b942..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/TouchMode.desktop.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.text
-
-internal actual val isInTouchMode = false
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/handwriting/StylusHandwriting.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/handwriting/StylusHandwriting.desktop.kt
deleted file mode 100644
index 5667100..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/handwriting/StylusHandwriting.desktop.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.text.handwriting
-
-internal actual val isStylusHandwritingSupported: Boolean = false
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/input/internal/DesktopTextInputSession.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/input/internal/DesktopTextInputSession.desktop.kt
deleted file mode 100644
index c72411d2..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/input/internal/DesktopTextInputSession.desktop.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.text.input.internal
-
-import androidx.compose.foundation.content.internal.ReceiveContentConfiguration
-import androidx.compose.ui.platform.PlatformTextInputSession
-import androidx.compose.ui.platform.ViewConfiguration
-import androidx.compose.ui.text.input.ImeAction
-import androidx.compose.ui.text.input.ImeOptions
-import kotlinx.coroutines.awaitCancellation
-import kotlinx.coroutines.flow.MutableSharedFlow
-
-/** Runs desktop-specific text input session logic. */
-internal actual suspend fun PlatformTextInputSession.platformSpecificTextInputSession(
-    state: TransformedTextFieldState,
-    layoutState: TextLayoutState,
-    imeOptions: ImeOptions,
-    receiveContentConfiguration: ReceiveContentConfiguration?,
-    onImeAction: ((ImeAction) -> Unit)?,
-    stylusHandwritingTrigger: MutableSharedFlow<Unit>?,
-    viewConfiguration: ViewConfiguration?
-): Nothing {
-    // TODO(b/267235947) Wire up desktop.
-    awaitCancellation()
-}
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/input/internal/LegacyPlatformTextInputServiceAdapter.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/input/internal/LegacyPlatformTextInputServiceAdapter.desktop.kt
deleted file mode 100644
index db9a9b9..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/input/internal/LegacyPlatformTextInputServiceAdapter.desktop.kt
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.text.input.internal
-
-import androidx.compose.foundation.text.input.internal.DesktopLegacyPlatformTextInputServiceAdapter.CurrentInput
-import androidx.compose.ui.geometry.Rect
-import androidx.compose.ui.layout.LayoutCoordinates
-import androidx.compose.ui.platform.PlatformTextInputMethodRequest
-import androidx.compose.ui.text.TextRange
-import androidx.compose.ui.text.input.CommitTextCommand
-import androidx.compose.ui.text.input.DeleteSurroundingTextInCodePointsCommand
-import androidx.compose.ui.text.input.EditCommand
-import androidx.compose.ui.text.input.ImeAction
-import androidx.compose.ui.text.input.ImeOptions
-import androidx.compose.ui.text.input.SetComposingTextCommand
-import androidx.compose.ui.text.input.TextFieldValue
-import androidx.compose.ui.text.substring
-import java.awt.Rectangle
-import java.awt.event.InputMethodEvent
-import java.awt.event.InputMethodListener
-import java.awt.font.TextHitInfo
-import java.awt.im.InputMethodRequests
-import java.text.AttributedCharacterIterator
-import java.text.AttributedString
-import java.text.CharacterIterator
-import java.util.Locale
-import kotlin.math.max
-import kotlin.math.min
-import kotlinx.coroutines.Job
-
-internal actual fun createLegacyPlatformTextInputServiceAdapter():
-    LegacyPlatformTextInputServiceAdapter = DesktopLegacyPlatformTextInputServiceAdapter()
-
-internal class DesktopLegacyPlatformTextInputServiceAdapter :
-    LegacyPlatformTextInputServiceAdapter() {
-
-    data class CurrentInput(
-        var value: TextFieldValue,
-        val onEditCommand: ((List<EditCommand>) -> Unit),
-        val onImeActionPerformed: ((ImeAction) -> Unit),
-        val imeAction: ImeAction,
-        var focusedRect: Rect? = null
-    )
-
-    private var job: Job? = null
-    private var currentInput: CurrentInput? = null
-
-    override fun startInput(
-        value: TextFieldValue,
-        imeOptions: ImeOptions,
-        onEditCommand: (List<EditCommand>) -> Unit,
-        onImeActionPerformed: (ImeAction) -> Unit
-    ) {
-        val node = textInputModifierNode ?: return
-        node.launchTextInputSession {
-            val input =
-                CurrentInput(value, onEditCommand, onImeActionPerformed, imeOptions.imeAction)
-            currentInput = input
-            try {
-                startInputMethod(LegacyTextInputMethodRequest(input, node.layoutCoordinates))
-            } finally {
-                currentInput = null
-            }
-        }
-    }
-
-    override fun stopInput() {
-        job?.cancel()
-        job = null
-    }
-
-    override fun updateState(oldValue: TextFieldValue?, newValue: TextFieldValue) {
-        currentInput?.let { input -> input.value = newValue }
-    }
-
-    override fun notifyFocusedRect(rect: Rect) {
-        currentInput?.let { input -> input.focusedRect = rect }
-    }
-
-    override fun startStylusHandwriting() {
-        // Noop for desktop
-    }
-}
-
-internal class LegacyTextInputMethodRequest(
-    private val input: CurrentInput,
-    private val coordinates: LayoutCoordinates?,
-) : PlatformTextInputMethodRequest, InputMethodRequests, InputMethodListener {
-
-    // This is required to support input of accented characters using press-and-hold method
-    // (http://support.apple.com/kb/PH11264). JDK currently properly supports this functionality
-    // only for TextComponent/JTextComponent descendants. For our editor component we need this
-    // workaround. After https://bugs.openjdk.java.net/browse/JDK-8074882 is fixed, this workaround
-    // should be replaced with a proper solution.
-    internal var charKeyPressed: Boolean = false
-    private var needToDeletePreviousChar: Boolean = false
-
-    override val inputMethodListener: InputMethodListener
-        get() = this
-
-    override val inputMethodRequests: InputMethodRequests
-        get() = this
-
-    override fun inputMethodTextChanged(event: InputMethodEvent) {
-        if (event.isConsumed) return
-        replaceInputMethodText(event)
-        event.consume()
-    }
-
-    override fun caretPositionChanged(event: InputMethodEvent) {
-        if (event.isConsumed) return
-        inputMethodCaretPositionChanged(event)
-        event.consume()
-    }
-
-    private fun inputMethodCaretPositionChanged(
-        @Suppress("UNUSED_PARAMETER") event: InputMethodEvent
-    ) {
-        // Which OSes and which input method could produce such events? We need to have some
-        // specific cases in mind before implementing this
-    }
-
-    // Visible for testing.
-    internal fun replaceInputMethodText(event: InputMethodEvent) {
-        if (event.text == null) {
-            return
-        }
-        val committed = event.text.toStringUntil(event.committedCharacterCount)
-        val composing = event.text.toStringFrom(event.committedCharacterCount)
-        val ops = mutableListOf<EditCommand>()
-
-        if (needToDeletePreviousChar && isMac && input.value.selection.min > 0) {
-            needToDeletePreviousChar = false
-            ops.add(DeleteSurroundingTextInCodePointsCommand(1, 0))
-        }
-
-        // newCursorPosition == 1 leads to effectively ignoring of this parameter in EditCommands
-        // processing. the cursor will be set after the inserted text.
-        if (committed.isNotEmpty()) {
-            ops.add(CommitTextCommand(committed, 1))
-        }
-        if (composing.isNotEmpty()) {
-            ops.add(SetComposingTextCommand(composing, 1))
-        }
-
-        input.onEditCommand.invoke(ops)
-    }
-
-    override fun getLocationOffset(x: Int, y: Int): TextHitInfo? {
-        if (input.value.composition != null) {
-            // TODO: to properly implement this method we need to somehow have access to
-            //  Paragraph at this point
-            return TextHitInfo.leading(0)
-        }
-        return null
-    }
-
-    override fun cancelLatestCommittedText(
-        attributes: Array<AttributedCharacterIterator.Attribute>?
-    ): AttributedCharacterIterator? {
-        return null
-    }
-
-    override fun getInsertPositionOffset(): Int {
-        val composedStartIndex = input.value.composition?.start ?: 0
-        val composedEndIndex = input.value.composition?.end ?: 0
-
-        val caretIndex = input.value.selection.start
-        if (caretIndex < composedStartIndex) {
-            return caretIndex
-        }
-        if (caretIndex < composedEndIndex) {
-            return composedStartIndex
-        }
-        return caretIndex - (composedEndIndex - composedStartIndex)
-    }
-
-    override fun getCommittedTextLength() =
-        input.value.text.length - (input.value.composition?.length ?: 0)
-
-    override fun getSelectedText(
-        attributes: Array<AttributedCharacterIterator.Attribute>?
-    ): AttributedCharacterIterator {
-        if (charKeyPressed) {
-            needToDeletePreviousChar = true
-        }
-        val str = input.value.text.substring(input.value.selection)
-        return AttributedString(str).iterator
-    }
-
-    override fun getTextLocation(offset: TextHitInfo): Rectangle? {
-        return input.focusedRect?.let {
-            val (x, y) = coordinates?.localToScreen(it.topRight) ?: return null
-            Rectangle(x.toInt(), y.toInt(), it.width.toInt(), it.height.toInt())
-        }
-    }
-
-    override fun getCommittedText(
-        beginIndex: Int,
-        endIndex: Int,
-        attributes: Array<AttributedCharacterIterator.Attribute>?
-    ): AttributedCharacterIterator {
-        val comp = input.value.composition
-        val text = input.value.text
-        val range = TextRange(beginIndex, endIndex.coerceAtMost(text.length))
-        if (comp == null) {
-            val res = text.substring(range)
-            return AttributedString(res).iterator
-        }
-        val committed =
-            text.substring(
-                TextRange(
-                    min(range.min, comp.min),
-                    max(range.max, comp.max).coerceAtMost(text.length)
-                )
-            )
-        return AttributedString(committed).iterator
-    }
-}
-
-private fun AttributedCharacterIterator.toStringUntil(index: Int): String {
-    val strBuf = StringBuffer()
-    var i = index
-    if (i > 0) {
-        var c: Char = setIndex(0)
-        while (i > 0) {
-            strBuf.append(c)
-            c = next()
-            i--
-        }
-    }
-    return String(strBuf)
-}
-
-private fun AttributedCharacterIterator.toStringFrom(index: Int): String {
-    val strBuf = StringBuffer()
-    var c: Char = setIndex(index)
-    while (c != CharacterIterator.DONE) {
-        strBuf.append(c)
-        c = next()
-    }
-    return String(strBuf)
-}
-
-internal val isMac = System.getProperty("os.name").lowercase(Locale.ENGLISH).startsWith("mac")
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/input/internal/TextFieldDragAndDropNode.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/input/internal/TextFieldDragAndDropNode.desktop.kt
deleted file mode 100644
index fdccc7e..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/input/internal/TextFieldDragAndDropNode.desktop.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.text.input.internal
-
-import androidx.compose.foundation.content.MediaType
-import androidx.compose.ui.draganddrop.DragAndDropEvent
-import androidx.compose.ui.draganddrop.DragAndDropModifierNode
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.platform.ClipEntry
-import androidx.compose.ui.platform.ClipMetadata
-
-/** System DragAndDrop is not yet supported on Desktop flavor of BTF2. */
-internal actual fun textFieldDragAndDropNode(
-    hintMediaTypes: () -> Set<MediaType>,
-    onDrop: (clipEntry: ClipEntry, clipMetadata: ClipMetadata) -> Boolean,
-    dragAndDropRequestPermission: (DragAndDropEvent) -> Unit,
-    onStarted: ((event: DragAndDropEvent) -> Unit)?,
-    onEntered: ((event: DragAndDropEvent) -> Unit)?,
-    onMoved: ((position: Offset) -> Unit)?,
-    onChanged: ((event: DragAndDropEvent) -> Unit)?,
-    onExited: ((event: DragAndDropEvent) -> Unit)?,
-    onEnded: ((event: DragAndDropEvent) -> Unit)?,
-): DragAndDropModifierNode {
-    return DragAndDropModifierNode()
-}
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/input/internal/TextFieldKeyEventHandler.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/input/internal/TextFieldKeyEventHandler.desktop.kt
deleted file mode 100644
index 00e60c9..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/input/internal/TextFieldKeyEventHandler.desktop.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.text.input.internal
-
-import androidx.compose.ui.input.key.KeyEvent
-
-/** Factory function to create a platform specific [TextFieldKeyEventHandler]. */
-internal actual fun createTextFieldKeyEventHandler() = object : TextFieldKeyEventHandler() {}
-
-internal actual val KeyEvent.isFromSoftKeyboard: Boolean
-    get() = false
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/input/internal/TextFieldLayoutStateCache.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/input/internal/TextFieldLayoutStateCache.desktop.kt
deleted file mode 100644
index 829e7d5..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/input/internal/TextFieldLayoutStateCache.desktop.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.text.input.internal
-
-import androidx.compose.ui.text.intl.PlatformLocale
-import androidx.compose.ui.text.style.TextDirection
-import java.text.DecimalFormatSymbols
-
-internal actual fun resolveTextDirectionForKeyboardTypePhone(
-    locale: PlatformLocale
-): TextDirection {
-    val symbols = DecimalFormatSymbols.getInstance(locale)
-    val zero = symbols.zeroDigit
-    val digitDirection = Character.getDirectionality(zero)
-    return if (
-        digitDirection == Character.DIRECTIONALITY_RIGHT_TO_LEFT ||
-            digitDirection == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC
-    ) {
-        TextDirection.Rtl
-    } else {
-        TextDirection.Ltr
-    }
-}
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/input/internal/ToCharArray.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/input/internal/ToCharArray.desktop.kt
deleted file mode 100644
index 3ffc862..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/input/internal/ToCharArray.desktop.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.text.input.internal
-
-import androidx.compose.foundation.text.input.TextFieldCharSequence
-
-internal actual fun CharSequence.toCharArray(
-    destination: CharArray,
-    destinationOffset: Int,
-    startIndex: Int,
-    endIndex: Int
-) {
-    @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
-    when (this) {
-        is TextFieldCharSequence ->
-            toCharArray(destination, destinationOffset, startIndex, endIndex)
-        is java.lang.String -> getChars(startIndex, endIndex, destination, destinationOffset)
-        is StringBuilder -> getChars(startIndex, endIndex, destination, destinationOffset)
-        else -> {
-            require(startIndex in indices && endIndex in 0..length) {
-                "Expected source [$startIndex, $endIndex) to be in [0, $length)"
-            }
-            val copyLength = endIndex - startIndex
-            require(
-                destinationOffset in destination.indices &&
-                    destinationOffset + copyLength in 0..destination.size
-            ) {
-                "Expected destination [$destinationOffset, ${destinationOffset + copyLength}) " +
-                    "to be in [0, ${destination.size})"
-            }
-
-            for (i in 0 until copyLength) {
-                destination[destinationOffset + i] = get(startIndex + i)
-            }
-        }
-    }
-}
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/input/internal/selection/DesktopTextFieldMagnifier.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/input/internal/selection/DesktopTextFieldMagnifier.desktop.kt
deleted file mode 100644
index 3a9ee1e..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/input/internal/selection/DesktopTextFieldMagnifier.desktop.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.text.input.internal.selection
-
-import androidx.compose.foundation.text.input.internal.TextLayoutState
-import androidx.compose.foundation.text.input.internal.TransformedTextFieldState
-
-/** There is no magnifier on Desktop. Return a noop [TextFieldMagnifierNode] implementation. */
-internal actual fun textFieldMagnifierNode(
-    textFieldState: TransformedTextFieldState,
-    textFieldSelectionState: TextFieldSelectionState,
-    textLayoutState: TextLayoutState,
-    visible: Boolean
-) =
-    object : TextFieldMagnifierNode() {
-        override fun update(
-            textFieldState: TransformedTextFieldState,
-            textFieldSelectionState: TextFieldSelectionState,
-            textLayoutState: TextLayoutState,
-            visible: Boolean
-        ) {}
-    }
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/selection/DesktopSelectionHandles.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/selection/DesktopSelectionHandles.desktop.kt
deleted file mode 100644
index c5a99e2..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/selection/DesktopSelectionHandles.desktop.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.text.selection
-
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.text.style.ResolvedTextDirection
-import androidx.compose.ui.unit.DpSize
-
-@Composable
-internal actual fun SelectionHandle(
-    offsetProvider: OffsetProvider,
-    isStartHandle: Boolean,
-    direction: ResolvedTextDirection,
-    handlesCrossed: Boolean,
-    minTouchTargetSize: DpSize,
-    modifier: Modifier,
-) {
-    // TODO
-}
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/selection/SelectionManager.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/selection/SelectionManager.desktop.kt
deleted file mode 100644
index f4b0c74..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/selection/SelectionManager.desktop.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.text.selection
-
-import androidx.compose.foundation.DesktopPlatform
-import androidx.compose.foundation.text.MappedKeys
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.input.key.KeyEvent
-import androidx.compose.ui.input.key.isCtrlPressed
-import androidx.compose.ui.input.key.isMetaPressed
-import androidx.compose.ui.input.key.key
-
-// this doesn't sounds very sustainable
-// it would end up being a function for any conceptual keyevent (selectall, cut, copy, paste)
-// TODO(b/1564937)
-internal actual fun isCopyKeyEvent(keyEvent: KeyEvent) =
-    keyEvent.key == MappedKeys.C &&
-        when (DesktopPlatform.Current) {
-            DesktopPlatform.MacOS -> keyEvent.isMetaPressed
-            else -> keyEvent.isCtrlPressed
-        } || keyEvent.key == MappedKeys.Copy
-
-/** Magnification is not supported on desktop. */
-internal actual fun Modifier.selectionMagnifier(manager: SelectionManager): Modifier = this
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/selection/TextFieldSelectionManager.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/selection/TextFieldSelectionManager.desktop.kt
deleted file mode 100644
index 7b9ce21..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/selection/TextFieldSelectionManager.desktop.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.text.selection
-
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.input.pointer.PointerEvent
-
-internal actual val PointerEvent.isShiftPressed: Boolean
-    get() = mouseEvent?.isShiftDown ?: false
-
-/** Magnification is not supported on desktop. */
-internal actual fun Modifier.textFieldMagnifier(manager: TextFieldSelectionManager): Modifier = this
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/window/WindowDraggableArea.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/window/WindowDraggableArea.desktop.kt
deleted file mode 100644
index da67d5e..0000000
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/window/WindowDraggableArea.desktop.kt
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.window
-
-import androidx.compose.foundation.gestures.awaitEachGesture
-import androidx.compose.foundation.gestures.awaitFirstDown
-import androidx.compose.foundation.layout.Box
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.input.pointer.pointerInput
-import androidx.compose.ui.unit.IntOffset
-import androidx.compose.ui.window.WindowScope
-import java.awt.MouseInfo
-import java.awt.Point
-import java.awt.Window
-import java.awt.event.MouseAdapter
-import java.awt.event.MouseEvent
-import java.awt.event.MouseMotionAdapter
-
-/**
- * WindowDraggableArea is a component that allows you to drag the window using the mouse.
- *
- * @param modifier The modifier to be applied to the layout.
- * @param content The content lambda.
- */
-@Composable
-fun WindowScope.WindowDraggableArea(
-    modifier: Modifier = Modifier,
-    content: @Composable () -> Unit = {}
-) {
-    val handler = remember { DragHandler(window) }
-
-    Box(
-        modifier =
-            modifier.pointerInput(Unit) {
-                awaitEachGesture {
-                    awaitFirstDown()
-                    handler.register()
-                }
-            }
-    ) {
-        content()
-    }
-}
-
-private class DragHandler(private val window: Window) {
-    private var location = window.location.toComposeOffset()
-    private var pointStart = MouseInfo.getPointerInfo().location.toComposeOffset()
-
-    private val dragListener =
-        object : MouseMotionAdapter() {
-            override fun mouseDragged(event: MouseEvent) = drag()
-        }
-    private val removeListener =
-        object : MouseAdapter() {
-            override fun mouseReleased(event: MouseEvent) {
-                window.removeMouseMotionListener(dragListener)
-                window.removeMouseListener(this)
-            }
-        }
-
-    fun register() {
-        location = window.location.toComposeOffset()
-        pointStart = MouseInfo.getPointerInfo().location.toComposeOffset()
-        window.addMouseListener(removeListener)
-        window.addMouseMotionListener(dragListener)
-    }
-
-    private fun drag() {
-        val point = MouseInfo.getPointerInfo().location.toComposeOffset()
-        val location = location + (point - pointStart)
-        window.setLocation(location.x, location.y)
-    }
-
-    private fun Point.toComposeOffset() = IntOffset(x, y)
-}
diff --git a/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/ScrollbarTest.kt b/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/ScrollbarTest.kt
deleted file mode 100644
index 5feaf7b..0000000
--- a/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/ScrollbarTest.kt
+++ /dev/null
@@ -1,561 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation
-
-import androidx.compose.foundation.gestures.LocalScrollConfig
-import androidx.compose.foundation.gestures.ScrollConfig
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.ColumnScope
-import androidx.compose.foundation.layout.fillMaxHeight
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.width
-import androidx.compose.foundation.lazy.LazyColumn
-import androidx.compose.foundation.lazy.LazyListState
-import androidx.compose.foundation.lazy.items
-import androidx.compose.foundation.lazy.rememberLazyListState
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.RectangleShape
-import androidx.compose.ui.input.pointer.PointerEvent
-import androidx.compose.ui.input.pointer.PointerEventType
-import androidx.compose.ui.platform.testTag
-import androidx.compose.ui.test.InternalTestApi
-import androidx.compose.ui.test.TouchInjectionScope
-import androidx.compose.ui.test.assertTopPositionInRootIsEqualTo
-import androidx.compose.ui.test.junit4.ComposeTestRule
-import androidx.compose.ui.test.junit4.DesktopComposeTestRule
-import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.compose.ui.test.onNodeWithTag
-import androidx.compose.ui.test.performTouchInput
-import androidx.compose.ui.unit.Density
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.IntSize
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.util.fastFold
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.runBlocking
-import org.junit.Assert.assertEquals
-import org.junit.Ignore
-import org.junit.Rule
-import org.junit.Test
-
-@Suppress("WrapUnaryOperator")
-class ScrollbarTest {
-    @get:Rule val rule = createComposeRule()
-
-    @Test
-    fun `drag slider to the middle`() {
-        runBlocking(Dispatchers.Main) {
-            rule.setContent {
-                TestBox(size = 100.dp, childSize = 20.dp, childCount = 10, scrollbarWidth = 10.dp)
-            }
-            rule.awaitIdle()
-
-            rule.onNodeWithTag("scrollbar").performTouchInput {
-                instantSwipe(start = Offset(0f, 25f), end = Offset(0f, 50f))
-            }
-            rule.awaitIdle()
-            rule.onNodeWithTag("box0").assertTopPositionInRootIsEqualTo(-50.dp)
-        }
-    }
-
-    @Test
-    fun `drag slider when it is hidden`() {
-        runBlocking(Dispatchers.Main) {
-            rule.setContent {
-                TestBox(size = 100.dp, childSize = 20.dp, childCount = 1, scrollbarWidth = 10.dp)
-            }
-            rule.awaitIdle()
-            rule.onNodeWithTag("scrollbar").performTouchInput {
-                instantSwipe(start = Offset(0f, 25f), end = Offset(0f, 50f))
-            }
-            rule.awaitIdle()
-            rule.onNodeWithTag("box0").assertTopPositionInRootIsEqualTo(0.dp)
-        }
-    }
-
-    @Test
-    fun `drag slider to the edges`() {
-        runBlocking(Dispatchers.Main) {
-            rule.setContent {
-                TestBox(size = 100.dp, childSize = 20.dp, childCount = 10, scrollbarWidth = 10.dp)
-            }
-            rule.awaitIdle()
-
-            rule.onNodeWithTag("scrollbar").performTouchInput {
-                instantSwipe(start = Offset(0f, 25f), end = Offset(0f, 500f))
-            }
-            rule.awaitIdle()
-            rule.onNodeWithTag("box0").assertTopPositionInRootIsEqualTo(-100.dp)
-
-            rule.onNodeWithTag("scrollbar").performTouchInput {
-                instantSwipe(start = Offset(0f, 99f), end = Offset(0f, -500f))
-            }
-            rule.awaitIdle()
-            rule.onNodeWithTag("box0").assertTopPositionInRootIsEqualTo(0.dp)
-        }
-    }
-
-    @Test
-    fun `drag outside slider`() {
-        runBlocking(Dispatchers.Main) {
-            rule.setContent {
-                TestBox(size = 100.dp, childSize = 20.dp, childCount = 10, scrollbarWidth = 10.dp)
-            }
-            rule.awaitIdle()
-
-            rule.onNodeWithTag("scrollbar").performTouchInput {
-                instantSwipe(start = Offset(10f, 25f), end = Offset(0f, 50f))
-            }
-            rule.awaitIdle()
-            rule.onNodeWithTag("box0").assertTopPositionInRootIsEqualTo(0.dp)
-        }
-    }
-
-    @Test
-    fun `drag outside slider and back`() {
-        runBlocking(Dispatchers.Main) {
-            rule.setContent {
-                TestBox(size = 100.dp, childSize = 20.dp, childCount = 10, scrollbarWidth = 10.dp)
-            }
-            rule.awaitIdle()
-
-            rule.onNodeWithTag("scrollbar").performTouchInput {
-                down(Offset(10f, 25f))
-                moveBy(Offset(0f, 50f))
-                moveBy(Offset(0f, -50f))
-                up()
-            }
-            rule.awaitIdle()
-            rule.onNodeWithTag("box0").assertTopPositionInRootIsEqualTo(0.dp)
-        }
-    }
-
-    // TODO(demin): write a test when we support DesktopComposeTestRule.mainClock:
-    //  see https://github.com/JetBrains/compose-jb/issues/637
-    //    fun `move mouse to the slider and drag it`() {
-    //        ...
-    //        rule.performMouseMove(0, 25)
-    //        rule.mainClock.advanceTimeByFrame()
-    //        down(Offset(0f, 25f))
-    //        rule.mainClock.advanceTimeByFrame()
-    //        moveTo(Offset(0f, 30f))
-    //        rule.mainClock.advanceTimeByFrame()
-    //        moveTo(Offset(0f, 50f))
-    //        rule.mainClock.advanceTimeByFrame()
-    //        up()
-    //        ...
-    //    }
-
-    // TODO(demin): enable after we resolve b/171889442
-    @Ignore("Enable after we resolve b/171889442")
-    @Test
-    fun `mouseScroll over slider`() {
-        runBlocking(Dispatchers.Main) {
-            rule.setContent {
-                TestBox(size = 100.dp, childSize = 20.dp, childCount = 10, scrollbarWidth = 10.dp)
-            }
-            rule.awaitIdle()
-
-            rule.performMouseScroll(0, 25, 1f)
-            rule.awaitIdle()
-            rule.onNodeWithTag("box0").assertTopPositionInRootIsEqualTo(-10.dp)
-        }
-    }
-
-    // TODO(demin): enable after we resolve b/171889442
-    @Ignore("Enable after we resolve b/171889442")
-    @Test
-    fun `mouseScroll over scrollbar outside slider`() {
-        runBlocking(Dispatchers.Main) {
-            rule.setContent {
-                TestBox(size = 100.dp, childSize = 20.dp, childCount = 10, scrollbarWidth = 10.dp)
-            }
-            rule.awaitIdle()
-
-            rule.performMouseScroll(0, 99, 1f)
-            rule.awaitIdle()
-            rule.onNodeWithTag("box0").assertTopPositionInRootIsEqualTo(-10.dp)
-        }
-    }
-
-    // TODO(demin): enable after we resolve b/171889442
-    @Ignore("Enable after we resolve b/171889442")
-    @Test
-    fun `vertical mouseScroll over horizontal scrollbar `() {
-        runBlocking(Dispatchers.Main) {
-            // TODO(demin): write tests for vertical mouse scrolling over
-            //  horizontalScrollbar for the case when we have two-way scrollable content:
-            //  Modifier.verticalScrollbar(...).horizontalScrollbar(...)
-            //  Content should scroll vertically.
-        }
-    }
-
-    @Test
-    fun `mouseScroll over column then drag to the beginning`() {
-        runBlocking(Dispatchers.Main) {
-            rule.setContent {
-                TestBox(size = 100.dp, childSize = 20.dp, childCount = 10, scrollbarWidth = 10.dp)
-            }
-            rule.awaitIdle()
-
-            rule.performMouseScroll(20, 25, 10f)
-            rule.awaitIdle()
-            rule.onNodeWithTag("box0").assertTopPositionInRootIsEqualTo(-100.dp)
-
-            rule.onNodeWithTag("scrollbar").performTouchInput {
-                instantSwipe(start = Offset(0f, 99f), end = Offset(0f, -500f))
-            }
-            rule.awaitIdle()
-            rule.onNodeWithTag("box0").assertTopPositionInRootIsEqualTo(0.dp)
-        }
-    }
-
-    @Test(timeout = 3000)
-    fun `press on scrollbar outside slider`() {
-        runBlocking(Dispatchers.Main) {
-            rule.setContent {
-                TestBox(size = 100.dp, childSize = 20.dp, childCount = 20, scrollbarWidth = 10.dp)
-            }
-            rule.awaitIdle()
-
-            rule.onNodeWithTag("scrollbar").performTouchInput { down(Offset(0f, 26f)) }
-
-            tryUntilSucceeded {
-                rule.awaitIdle()
-                rule.onNodeWithTag("box0").assertTopPositionInRootIsEqualTo(-100.dp)
-            }
-        }
-    }
-
-    @Test(timeout = 3000)
-    fun `press on the end of scrollbar outside slider`() {
-        runBlocking(Dispatchers.Main) {
-            rule.setContent {
-                TestBox(size = 100.dp, childSize = 20.dp, childCount = 20, scrollbarWidth = 10.dp)
-            }
-            rule.awaitIdle()
-
-            rule.onNodeWithTag("scrollbar").performTouchInput { down(Offset(0f, 99f)) }
-
-            tryUntilSucceeded {
-                rule.awaitIdle()
-                rule.onNodeWithTag("box0").assertTopPositionInRootIsEqualTo(-300.dp)
-            }
-        }
-    }
-
-    @Test(timeout = 3000)
-    fun `dynamically change content then drag slider to the end`() {
-        runBlocking(Dispatchers.Main) {
-            val isContentVisible = mutableStateOf(false)
-            rule.setContent {
-                TestBox(size = 100.dp, scrollbarWidth = 10.dp) {
-                    if (isContentVisible.value) {
-                        repeat(10) { Box(Modifier.size(20.dp).testTag("box$it")) }
-                    }
-                }
-            }
-            rule.awaitIdle()
-
-            isContentVisible.value = true
-            rule.awaitIdle()
-
-            rule.onNodeWithTag("scrollbar").performTouchInput {
-                instantSwipe(start = Offset(0f, 25f), end = Offset(0f, 500f))
-            }
-            rule.awaitIdle()
-            rule.onNodeWithTag("box0").assertTopPositionInRootIsEqualTo(-100.dp)
-        }
-    }
-
-    @Suppress("SameParameterValue")
-    @Test(timeout = 3000)
-    fun `scroll by less than one page in lazy list`() {
-        runBlocking(Dispatchers.Main) {
-            lateinit var state: LazyListState
-
-            rule.setContent {
-                state = rememberLazyListState()
-                LazyTestBox(
-                    state,
-                    size = 100.dp,
-                    childSize = 20.dp,
-                    childCount = 20,
-                    scrollbarWidth = 10.dp
-                )
-            }
-            rule.awaitIdle()
-
-            rule.onNodeWithTag("scrollbar").performTouchInput {
-                instantSwipe(start = Offset(0f, 0f), end = Offset(0f, 11f))
-            }
-            rule.awaitIdle()
-            assertEquals(2, state.firstVisibleItemIndex)
-            assertEquals(4, state.firstVisibleItemScrollOffset)
-        }
-    }
-
-    @Suppress("SameParameterValue")
-    @Test(timeout = 3000)
-    fun `scroll in reversed lazy list`() {
-        runBlocking(Dispatchers.Main) {
-            lateinit var state: LazyListState
-
-            rule.setContent {
-                state = rememberLazyListState()
-                LazyTestBox(
-                    state,
-                    size = 100.dp,
-                    childSize = 20.dp,
-                    childCount = 20,
-                    scrollbarWidth = 10.dp,
-                    reverseLayout = true
-                )
-            }
-            rule.awaitIdle()
-
-            rule.onNodeWithTag("scrollbar").performTouchInput {
-                instantSwipe(start = Offset(0f, 99f), end = Offset(0f, 88f))
-            }
-            rule.awaitIdle()
-            assertEquals(2, state.firstVisibleItemIndex)
-            assertEquals(4, state.firstVisibleItemScrollOffset)
-        }
-    }
-
-    @Suppress("SameParameterValue")
-    @Test(timeout = 3000)
-    fun `scroll by more than one page in lazy list`() {
-        runBlocking(Dispatchers.Main) {
-            lateinit var state: LazyListState
-
-            rule.setContent {
-                state = rememberLazyListState()
-                LazyTestBox(
-                    state,
-                    size = 100.dp,
-                    childSize = 20.dp,
-                    childCount = 20,
-                    scrollbarWidth = 10.dp
-                )
-            }
-            rule.awaitIdle()
-
-            rule.onNodeWithTag("scrollbar").performTouchInput {
-                instantSwipe(start = Offset(0f, 0f), end = Offset(0f, 26f))
-            }
-            rule.awaitIdle()
-            assertEquals(5, state.firstVisibleItemIndex)
-            assertEquals(4, state.firstVisibleItemScrollOffset)
-        }
-    }
-
-    @Suppress("SameParameterValue")
-    @Test(timeout = 3000)
-    fun `scroll outside of scrollbar bounds in lazy list`() {
-        runBlocking(Dispatchers.Main) {
-            lateinit var state: LazyListState
-
-            rule.setContent {
-                state = rememberLazyListState()
-                LazyTestBox(
-                    state,
-                    size = 100.dp,
-                    childSize = 20.dp,
-                    childCount = 20,
-                    scrollbarWidth = 10.dp
-                )
-            }
-            rule.awaitIdle()
-
-            rule.onNodeWithTag("scrollbar").performTouchInput {
-                instantSwipe(start = Offset(0f, 0f), end = Offset(0f, 10000f))
-            }
-            rule.awaitIdle()
-            assertEquals(15, state.firstVisibleItemIndex)
-            assertEquals(0, state.firstVisibleItemScrollOffset)
-
-            rule.onNodeWithTag("scrollbar").performTouchInput {
-                instantSwipe(start = Offset(0f, 99f), end = Offset(0f, -10000f))
-            }
-            rule.awaitIdle()
-            assertEquals(0, state.firstVisibleItemIndex)
-            assertEquals(0, state.firstVisibleItemScrollOffset)
-        }
-    }
-
-    @Test
-    fun `drag lazy slider when it is hidden`() {
-        runBlocking(Dispatchers.Main) {
-            rule.setContent {
-                LazyTestBox(
-                    size = 100.dp,
-                    childSize = 20.dp,
-                    childCount = 1,
-                    scrollbarWidth = 10.dp
-                )
-            }
-            rule.awaitIdle()
-            rule.onNodeWithTag("scrollbar").performTouchInput {
-                instantSwipe(start = Offset(0f, 25f), end = Offset(0f, 50f))
-            }
-            rule.awaitIdle()
-            rule.onNodeWithTag("box0").assertTopPositionInRootIsEqualTo(0.dp)
-        }
-    }
-
-    private suspend fun tryUntilSucceeded(block: suspend () -> Unit) {
-        while (true) {
-            try {
-                block()
-                break
-            } catch (e: Throwable) {
-                delay(10)
-            }
-        }
-    }
-
-    @OptIn(InternalTestApi::class)
-    private fun ComposeTestRule.performMouseScroll(x: Int, y: Int, delta: Float) {
-        (this as DesktopComposeTestRule)
-            .scene
-            .sendPointerEvent(
-                PointerEventType.Scroll,
-                Offset(x.toFloat(), y.toFloat()),
-                scrollDelta = Offset(x = 0f, y = delta)
-            )
-    }
-
-    @OptIn(InternalTestApi::class)
-    private fun ComposeTestRule.performMouseMove(x: Int, y: Int) {
-        (this as DesktopComposeTestRule)
-            .scene
-            .sendPointerEvent(PointerEventType.Move, Offset(x.toFloat(), y.toFloat()))
-    }
-
-    @Composable
-    private fun TestBox(
-        size: Dp,
-        childSize: Dp,
-        childCount: Int,
-        scrollbarWidth: Dp,
-    ) = withTestEnvironment {
-        Box(Modifier.size(size)) {
-            val state = rememberScrollState()
-
-            Column(Modifier.fillMaxSize().testTag("column").verticalScroll(state)) {
-                repeat(childCount) { Box(Modifier.size(childSize).testTag("box$it")) }
-            }
-
-            VerticalScrollbar(
-                adapter = rememberScrollbarAdapter(state),
-                modifier = Modifier.width(scrollbarWidth).fillMaxHeight().testTag("scrollbar")
-            )
-        }
-    }
-
-    @Composable
-    private fun TestBox(
-        size: Dp,
-        scrollbarWidth: Dp,
-        scrollableContent: @Composable ColumnScope.() -> Unit
-    ) = withTestEnvironment {
-        Box(Modifier.size(size)) {
-            val state = rememberScrollState()
-
-            Column(
-                Modifier.fillMaxSize().testTag("column").verticalScroll(state),
-                content = scrollableContent
-            )
-
-            VerticalScrollbar(
-                adapter = rememberScrollbarAdapter(state),
-                modifier = Modifier.width(scrollbarWidth).fillMaxHeight().testTag("scrollbar")
-            )
-        }
-    }
-
-    @Suppress("SameParameterValue")
-    @Composable
-    private fun LazyTestBox(
-        state: LazyListState = rememberLazyListState(),
-        size: Dp,
-        childSize: Dp,
-        childCount: Int,
-        scrollbarWidth: Dp,
-        reverseLayout: Boolean = false
-    ) = withTestEnvironment {
-        Box(Modifier.size(size)) {
-            LazyColumn(
-                Modifier.fillMaxSize().testTag("column"),
-                state,
-                reverseLayout = reverseLayout
-            ) {
-                items((0 until childCount).toList()) {
-                    Box(Modifier.size(childSize).testTag("box$it"))
-                }
-            }
-
-            VerticalScrollbar(
-                adapter = rememberScrollbarAdapter(state),
-                reverseLayout = reverseLayout,
-                modifier = Modifier.width(scrollbarWidth).fillMaxHeight().testTag("scrollbar")
-            )
-        }
-    }
-
-    private fun TouchInjectionScope.instantSwipe(start: Offset, end: Offset) {
-        down(start)
-        moveTo(end)
-        up()
-    }
-
-    @Composable
-    private fun withTestEnvironment(content: @Composable () -> Unit) =
-        CompositionLocalProvider(
-            LocalScrollbarStyle provides
-                ScrollbarStyle(
-                    minimalHeight = 16.dp,
-                    thickness = 8.dp,
-                    shape = RectangleShape,
-                    hoverDurationMillis = 300,
-                    unhoverColor = Color.Black,
-                    hoverColor = Color.Red
-                ),
-            LocalScrollConfig provides TestConfig,
-            content = content
-        )
-}
-
-internal object TestConfig : ScrollConfig {
-    // the formula was determined experimentally based on MacOS Finder behaviour
-    // MacOS driver will send events with accelerating delta
-    override fun Density.calculateMouseWheelScroll(event: PointerEvent, bounds: IntSize): Offset {
-        return -event.totalScrollDelta * 10.dp.toPx()
-    }
-}
-
-private val PointerEvent.totalScrollDelta
-    get() = this.changes.fastFold(Offset.Zero) { acc, c -> acc + c.scrollDelta }
diff --git a/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/gestures/DesktopScrollableTest.kt b/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/gestures/DesktopScrollableTest.kt
deleted file mode 100644
index 45f9d84..0000000
--- a/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/gestures/DesktopScrollableTest.kt
+++ /dev/null
@@ -1,222 +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.
- */
-
-@file:Suppress("DEPRECATION") // https://github.com/JetBrains/compose-jb/issues/1514
-
-package androidx.compose.foundation.gestures
-
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.size
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.input.mouse.MouseScrollEvent
-import androidx.compose.ui.input.mouse.MouseScrollOrientation
-import androidx.compose.ui.input.mouse.MouseScrollUnit
-import androidx.compose.ui.platform.TestComposeWindow
-import androidx.compose.ui.unit.Density
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.dp
-import com.google.common.truth.Truth.assertThat
-import kotlin.math.sqrt
-import org.junit.Ignore
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-// TODO(demin): convert to ComposeScene instead of TestComposeWindow,
-//  after that we won't need `window.render`
-@RunWith(JUnit4::class)
-@Ignore // TODO(b/217238066) remove after migration to ImageComposeScene (it will be upstreamed from
-// Compose MPP 1.0.0)
-class DesktopScrollableTest {
-    private val density = 2f
-
-    private fun window() = TestComposeWindow(width = 100, height = 100, density = Density(density))
-
-    private fun scrollLineLinux(bounds: Dp) = sqrt(bounds.value * density)
-
-    private fun scrollLineWindows(bounds: Dp) = bounds.value * density / 20f
-
-    private fun scrollLineMacOs() = density * 10f
-
-    private fun scrollPage(bounds: Dp) = bounds.value * density
-
-    @Test
-    fun `linux, scroll vertical`() {
-        val window = window()
-        val context = TestColumn()
-
-        window.setContent {
-            CompositionLocalProvider(LocalScrollConfig provides LinuxGnomeConfig) {
-                Box(
-                    Modifier.scrollable(
-                            orientation = Orientation.Vertical,
-                            state = context.controller()
-                        )
-                        .size(10.dp, 20.dp)
-                )
-            }
-        }
-
-        window.onMouseScroll(
-            x = 0,
-            y = 0,
-            event = MouseScrollEvent(MouseScrollUnit.Line(3f), MouseScrollOrientation.Vertical)
-        )
-        window.render()
-
-        assertThat(context.offset).isWithin(0.1f).of(-3 * scrollLineLinux(20.dp))
-
-        window.onMouseScroll(
-            x = 0,
-            y = 0,
-            event = MouseScrollEvent(MouseScrollUnit.Line(3f), MouseScrollOrientation.Vertical)
-        )
-        window.render()
-
-        assertThat(context.offset).isWithin(0.1f).of(-6 * scrollLineLinux(20.dp))
-    }
-
-    @Test
-    fun `windows, scroll vertical`() {
-        val window = window()
-        val context = TestColumn()
-
-        window.setContent {
-            CompositionLocalProvider(LocalScrollConfig provides WindowsWinUIConfig) {
-                Box(
-                    Modifier.scrollable(
-                            orientation = Orientation.Vertical,
-                            state = context.controller()
-                        )
-                        .size(10.dp, 20.dp)
-                )
-            }
-        }
-
-        window.onMouseScroll(
-            x = 0,
-            y = 0,
-            event = MouseScrollEvent(MouseScrollUnit.Line(-2f), MouseScrollOrientation.Vertical)
-        )
-        window.render()
-
-        assertThat(context.offset).isWithin(0.1f).of(2 * scrollLineWindows(20.dp))
-
-        window.onMouseScroll(
-            x = 0,
-            y = 0,
-            event = MouseScrollEvent(MouseScrollUnit.Line(4f), MouseScrollOrientation.Vertical)
-        )
-        window.render()
-
-        assertThat(context.offset).isWithin(0.1f).of(-2 * scrollLineWindows(20.dp))
-    }
-
-    @Test
-    fun `windows, scroll one page vertical`() {
-        val window = window()
-        val context = TestColumn()
-
-        window.setContent {
-            CompositionLocalProvider(LocalScrollConfig provides WindowsWinUIConfig) {
-                Box(
-                    Modifier.scrollable(
-                            orientation = Orientation.Vertical,
-                            state = context.controller()
-                        )
-                        .size(10.dp, 20.dp)
-                )
-            }
-        }
-
-        window.onMouseScroll(
-            x = 0,
-            y = 0,
-            event = MouseScrollEvent(MouseScrollUnit.Page(1f), MouseScrollOrientation.Vertical)
-        )
-        window.render()
-
-        assertThat(context.offset).isWithin(0.1f).of(-scrollPage(20.dp))
-    }
-
-    @Test
-    fun `macOS, scroll vertical`() {
-        val window = window()
-        val context = TestColumn()
-
-        window.setContent {
-            CompositionLocalProvider(LocalScrollConfig provides MacOSCocoaConfig) {
-                Box(
-                    Modifier.scrollable(
-                            orientation = Orientation.Vertical,
-                            state = context.controller()
-                        )
-                        .size(10.dp, 20.dp)
-                )
-            }
-        }
-
-        window.onMouseScroll(
-            x = 0,
-            y = 0,
-            event = MouseScrollEvent(MouseScrollUnit.Line(-5f), MouseScrollOrientation.Vertical)
-        )
-        window.render()
-
-        assertThat(context.offset).isWithin(0.1f).of(5f * scrollLineMacOs())
-    }
-
-    @Test
-    fun `scroll with different orientation`() {
-        val window = window()
-        val column = TestColumn()
-
-        window.setContent {
-            CompositionLocalProvider(LocalScrollConfig provides LinuxGnomeConfig) {
-                Box(
-                    Modifier.scrollable(
-                            orientation = Orientation.Vertical,
-                            state = column.controller()
-                        )
-                        .size(10.dp, 20.dp)
-                )
-            }
-        }
-
-        window.onMouseScroll(
-            x = 0,
-            y = 0,
-            event = MouseScrollEvent(MouseScrollUnit.Line(3f), MouseScrollOrientation.Horizontal)
-        )
-        window.render()
-
-        assertThat(column.offset).isEqualTo(0f)
-    }
-
-    private class TestColumn {
-        var offset = 0f
-            private set
-
-        @Composable fun controller() = ScrollableState(::consumeScrollDelta)
-
-        private fun consumeScrollDelta(delta: Float): Float {
-            offset += delta
-            return delta
-        }
-    }
-}
diff --git a/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/text/OWNERS b/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/text/OWNERS
deleted file mode 100644
index f897dda5..0000000
--- a/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/text/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 630734
-include /TEXT_OWNERS
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/text/input/internal/LegacyPlatformTextInputServiceAdapterTest.kt b/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/text/input/internal/LegacyPlatformTextInputServiceAdapterTest.kt
deleted file mode 100644
index 15308ff..0000000
--- a/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/text/input/internal/LegacyPlatformTextInputServiceAdapterTest.kt
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-@file:Suppress("DEPRECATION")
-
-package androidx.compose.foundation.text.input.internal
-
-import androidx.compose.foundation.text.LegacyTextFieldState
-import androidx.compose.foundation.text.input.internal.LegacyPlatformTextInputServiceAdapter.LegacyPlatformTextInputNode
-import androidx.compose.foundation.text.selection.TextFieldSelectionManager
-import androidx.compose.ui.layout.LayoutCoordinates
-import androidx.compose.ui.platform.DefaultViewConfiguration
-import androidx.compose.ui.platform.PlatformTextInputMethodRequest
-import androidx.compose.ui.platform.PlatformTextInputSession
-import androidx.compose.ui.platform.SoftwareKeyboardController
-import androidx.compose.ui.platform.ViewConfiguration
-import androidx.compose.ui.text.TextRange
-import androidx.compose.ui.text.input.EditProcessor
-import androidx.compose.ui.text.input.ImeOptions
-import androidx.compose.ui.text.input.TextFieldValue
-import androidx.compose.ui.text.input.TextInputService
-import androidx.compose.ui.unit.Density
-import java.awt.Component
-import java.awt.event.InputMethodEvent
-import java.text.AttributedString
-import kotlin.test.assertIs
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.awaitCancellation
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.test.runTest
-import org.junit.Assert.assertEquals
-import org.junit.Assume.assumeTrue
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class LegacyPlatformTextInputServiceAdapterTest {
-
-    @Test
-    fun replaceInputMethodText_basic() = runTest {
-        val processor = EditProcessor()
-        val adapter = DesktopLegacyPlatformTextInputServiceAdapter()
-        val inputService = TextInputService(adapter)
-        var currentRequest: PlatformTextInputMethodRequest? = null
-
-        adapter.registerModifier(
-            object : LegacyPlatformTextInputNode {
-                override val softwareKeyboardController: SoftwareKeyboardController?
-                    get() = null
-
-                override val layoutCoordinates: LayoutCoordinates?
-                    get() = null
-
-                override val legacyTextFieldState: LegacyTextFieldState?
-                    get() = null
-
-                override val textFieldSelectionManager: TextFieldSelectionManager?
-                    get() = null
-
-                override val viewConfiguration: ViewConfiguration
-                    get() = DefaultViewConfiguration(Density(1f))
-
-                override fun launchTextInputSession(
-                    block: suspend PlatformTextInputSession.() -> Nothing
-                ): Job {
-                    val session =
-                        object : PlatformTextInputSession {
-                            override suspend fun startInputMethod(
-                                request: PlatformTextInputMethodRequest
-                            ): Nothing {
-                                currentRequest = request
-                                try {
-                                    awaitCancellation()
-                                } finally {
-                                    currentRequest = null
-                                }
-                            }
-                        }
-
-                    return backgroundScope.launch(Dispatchers.Unconfined) { block(session) }
-                }
-            }
-        )
-
-        val session =
-            inputService.startInput(TextFieldValue(), ImeOptions.Default, processor::apply, {})
-
-        processor.reset(TextFieldValue("h"), session)
-
-        val familyEmoji = "\uD83D\uDC68\u200D\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66"
-
-        val request = assertIs<LegacyTextInputMethodRequest>(currentRequest)
-        request.replaceInputMethodText(
-            InputMethodEvent(
-                object : Component() {},
-                InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
-                AttributedString(familyEmoji).iterator,
-                11,
-                null,
-                null
-            )
-        )
-
-        val buffer = processor.toTextFieldValue()
-
-        assertEquals("${familyEmoji}h", buffer.text)
-        assertEquals(TextRange(11), buffer.selection)
-    }
-
-    @Test
-    fun longPressWorkaroundTest() = runTest {
-        assumeTrue(isMac)
-        val processor = EditProcessor()
-
-        val adapter = DesktopLegacyPlatformTextInputServiceAdapter()
-        val inputService = TextInputService(adapter)
-        var currentRequest: PlatformTextInputMethodRequest? = null
-
-        adapter.registerModifier(
-            object : LegacyPlatformTextInputNode {
-                override val softwareKeyboardController: SoftwareKeyboardController?
-                    get() = null
-
-                override val layoutCoordinates: LayoutCoordinates?
-                    get() = null
-
-                override val legacyTextFieldState: LegacyTextFieldState?
-                    get() = null
-
-                override val textFieldSelectionManager: TextFieldSelectionManager?
-                    get() = null
-
-                override val viewConfiguration: ViewConfiguration
-                    get() = DefaultViewConfiguration(Density(1f))
-
-                override fun launchTextInputSession(
-                    block: suspend PlatformTextInputSession.() -> Nothing
-                ): Job {
-                    val session =
-                        object : PlatformTextInputSession {
-                            override suspend fun startInputMethod(
-                                request: PlatformTextInputMethodRequest
-                            ): Nothing {
-                                currentRequest = request
-                                try {
-                                    awaitCancellation()
-                                } finally {
-                                    currentRequest = null
-                                }
-                            }
-                        }
-
-                    return backgroundScope.launch(Dispatchers.Unconfined) { block(session) }
-                }
-            }
-        )
-
-        val session =
-            inputService.startInput(TextFieldValue(), ImeOptions.Default, processor::apply, {})
-
-        val request = assertIs<LegacyTextInputMethodRequest>(currentRequest)
-        request.charKeyPressed = true
-        processor.reset(TextFieldValue("a", selection = TextRange(1)), session)
-        request.getSelectedText(null)
-        request.charKeyPressed = false
-
-        request.replaceInputMethodText(
-            InputMethodEvent(
-                object : Component() {},
-                InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
-                AttributedString("ä").iterator,
-                1,
-                null,
-                null
-            )
-        )
-
-        val buffer = processor.toTextFieldValue()
-
-        assertEquals("ä", buffer.text)
-        assertEquals(TextRange(1), buffer.selection)
-    }
-}
diff --git a/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/text/selection/DesktopTextFieldSelectionManagerTest.kt b/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/text/selection/DesktopTextFieldSelectionManagerTest.kt
deleted file mode 100644
index 63d9845..0000000
--- a/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/text/selection/DesktopTextFieldSelectionManagerTest.kt
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.text.selection
-
-import androidx.compose.foundation.text.InternalFoundationTextApi
-import androidx.compose.foundation.text.LegacyTextFieldState
-import androidx.compose.foundation.text.TextLayoutResultProxy
-import androidx.compose.ui.focus.FocusRequester
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.geometry.Rect
-import androidx.compose.ui.hapticfeedback.HapticFeedback
-import androidx.compose.ui.platform.ClipboardManager
-import androidx.compose.ui.platform.TextToolbar
-import androidx.compose.ui.text.AnnotatedString
-import androidx.compose.ui.text.TextLayoutInput
-import androidx.compose.ui.text.TextLayoutResult
-import androidx.compose.ui.text.TextRange
-import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.text.input.EditProcessor
-import androidx.compose.ui.text.input.OffsetMapping
-import androidx.compose.ui.text.input.TextFieldValue
-import androidx.compose.ui.text.style.TextOverflow
-import androidx.compose.ui.unit.Constraints
-import androidx.compose.ui.unit.Density
-import androidx.compose.ui.unit.LayoutDirection
-import com.google.common.truth.Truth.assertThat
-import org.junit.Before
-import org.junit.Ignore
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-import org.mockito.kotlin.any
-import org.mockito.kotlin.mock
-import org.mockito.kotlin.times
-import org.mockito.kotlin.verify
-import org.mockito.kotlin.whenever
-
-@RunWith(JUnit4::class)
-@Ignore("b/271123970 Fails in AOSP. Will be fixed after upstreaming Compose for Desktop")
-class DesktopTextFieldSelectionManagerTest {
-    private val text = "Hello World"
-    private val density = Density(density = 1f)
-    private val offsetMapping = OffsetMapping.Identity
-    private var value = TextFieldValue(text)
-    private val lambda: (TextFieldValue) -> Unit = { value = it }
-    private lateinit var state: LegacyTextFieldState
-
-    private val dragBeginPosition = Offset.Zero
-    private val dragDistance = Offset(300f, 15f)
-    private val beginOffset = 0
-    private val dragOffset = text.indexOf('r')
-    private val layoutResult: TextLayoutResult = mock()
-    private val layoutResultProxy: TextLayoutResultProxy = mock()
-    private lateinit var manager: TextFieldSelectionManager
-
-    private val clipboardManager = mock<ClipboardManager>()
-    private val textToolbar = mock<TextToolbar>()
-    private val hapticFeedback = mock<HapticFeedback>()
-    private val focusRequester = mock<FocusRequester>()
-    private val processor = mock<EditProcessor>()
-
-    @OptIn(InternalFoundationTextApi::class)
-    @Before
-    fun setup() {
-        manager = TextFieldSelectionManager()
-        manager.offsetMapping = offsetMapping
-        manager.onValueChange = lambda
-        manager.value = value
-        manager.clipboardManager = clipboardManager
-        manager.textToolbar = textToolbar
-        manager.hapticFeedBack = hapticFeedback
-        manager.focusRequester = focusRequester
-
-        whenever(layoutResult.layoutInput)
-            .thenReturn(
-                TextLayoutInput(
-                    text = AnnotatedString(text),
-                    style = TextStyle.Default,
-                    placeholders = mock(),
-                    maxLines = 2,
-                    softWrap = true,
-                    overflow = TextOverflow.Ellipsis,
-                    density = density,
-                    layoutDirection = LayoutDirection.Ltr,
-                    fontFamilyResolver = mock(),
-                    constraints = Constraints()
-                )
-            )
-
-        whenever(layoutResult.getBoundingBox(any())).thenReturn(Rect.Zero)
-        whenever(layoutResult.getOffsetForPosition(dragBeginPosition)).thenReturn(beginOffset)
-        whenever(layoutResult.getOffsetForPosition(dragBeginPosition + dragDistance))
-            .thenReturn(dragOffset)
-        whenever(layoutResultProxy.getOffsetForPosition(dragBeginPosition, false))
-            .thenReturn(beginOffset)
-        whenever(layoutResultProxy.getOffsetForPosition(dragBeginPosition + dragDistance, false))
-            .thenReturn(dragOffset)
-        whenever(layoutResultProxy.getOffsetForPosition(dragBeginPosition + dragDistance))
-            .thenReturn(dragOffset)
-
-        whenever(layoutResultProxy.value).thenReturn(layoutResult)
-
-        state =
-            LegacyTextFieldState(
-                textDelegate = mock(),
-                recomposeScope = mock(),
-                keyboardController = null
-            )
-        state.layoutResult = layoutResultProxy
-        state.processor.reset(value, null)
-        manager.state = state
-        whenever(state.textDelegate.density).thenReturn(density)
-    }
-
-    @Test
-    fun TextFieldSelectionManager_mouseSelectionObserver_onStart() {
-        manager.mouseSelectionObserver.onStart(dragBeginPosition, SelectionAdjustment.None)
-
-        assertThat(value.selection).isEqualTo(TextRange(0, 0))
-
-        manager.mouseSelectionObserver.onStart(
-            dragBeginPosition + dragDistance,
-            SelectionAdjustment.None
-        )
-        assertThat(value.selection).isEqualTo(TextRange(8, 8))
-    }
-
-    @Test
-    fun TextFieldSelectionManager_mouseSelectionObserver_onStart_withShift() {
-        manager.mouseSelectionObserver.onExtend(dragBeginPosition)
-
-        assertThat(value.selection).isEqualTo(TextRange(0, 0))
-
-        manager.mouseSelectionObserver.onExtend(dragBeginPosition + dragDistance)
-        assertThat(value.selection).isEqualTo(TextRange(0, 8))
-    }
-
-    @Test
-    fun TextFieldSelectionManager_mouseSelectionObserver_onDrag() {
-        val observer = manager.mouseSelectionObserver
-        observer.onStart(dragBeginPosition, SelectionAdjustment.None)
-        observer.onDrag(dragDistance, SelectionAdjustment.None)
-
-        assertThat(value.selection).isEqualTo(TextRange(0, 8))
-    }
-
-    @Test
-    fun TextFieldSelectionManager_mouseSelectionObserver_copy() {
-        val observer = manager.mouseSelectionObserver
-        observer.onStart(dragBeginPosition, SelectionAdjustment.None)
-        observer.onDrag(dragDistance, SelectionAdjustment.None)
-
-        manager.value = value
-        manager.copy(cancelSelection = false)
-
-        verify(clipboardManager, times(1)).setText(AnnotatedString("Hello Wo"))
-        assertThat(value.selection).isEqualTo(TextRange(0, 8))
-    }
-}
diff --git a/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/text/selection/StringHelpersTest.kt b/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/text/selection/StringHelpersTest.kt
deleted file mode 100644
index 3f52c3b..0000000
--- a/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/text/selection/StringHelpersTest.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.text.selection
-
-import androidx.compose.foundation.text.findFollowingBreak
-import androidx.compose.foundation.text.findPrecedingBreak
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class StringHelpersTest {
-    val complexString = "\uD83E\uDDD1\uD83C\uDFFF\u200D\uD83E\uDDB0"
-
-    @Test
-    fun StringHelpersTest_findFollowingBreak() {
-        val result = complexString.findFollowingBreak(0)
-        assertThat(result).isEqualTo(7)
-    }
-
-    @Test
-    fun StringHelpersTest_findPrecedingBreak() {
-        val result = complexString.findPrecedingBreak(7)
-        assertThat(result).isEqualTo(0)
-    }
-}
diff --git a/compose/foundation/foundation/src/desktopTest/resources/mockito-extensions/org.mockito.plugins.MockMaker b/compose/foundation/foundation/src/desktopTest/resources/mockito-extensions/org.mockito.plugins.MockMaker
deleted file mode 100644
index ca6ee9c..0000000
--- a/compose/foundation/foundation/src/desktopTest/resources/mockito-extensions/org.mockito.plugins.MockMaker
+++ /dev/null
@@ -1 +0,0 @@
-mock-maker-inline
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/BasicTooltip.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/BasicTooltip.jvmStubs.kt
new file mode 100644
index 0000000..66b1f41
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/BasicTooltip.jvmStubs.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.foundation
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.window.PopupPositionProvider
+
+@Composable
+actual fun BasicTooltipBox(
+    positionProvider: PopupPositionProvider,
+    tooltip: @Composable () -> Unit,
+    state: BasicTooltipState,
+    modifier: Modifier,
+    focusable: Boolean,
+    enableUserInput: Boolean,
+    content: @Composable () -> Unit
+): Unit = implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/Clickable.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/Clickable.jvmStubs.kt
new file mode 100644
index 0000000..552054f
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/Clickable.jvmStubs.kt
@@ -0,0 +1,31 @@
+/*
+ * 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.foundation
+
+import androidx.compose.ui.input.key.KeyEvent
+import androidx.compose.ui.node.DelegatableNode
+
+internal actual fun DelegatableNode.isComposeRootInScrollableContainer(): Boolean =
+    implementedInJetBrainsFork()
+
+internal actual val TapIndicationDelay: Long = implementedInJetBrainsFork()
+
+internal actual val KeyEvent.isPress: Boolean
+    get() = implementedInJetBrainsFork()
+
+internal actual val KeyEvent.isClick: Boolean
+    get() = implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/DarkTheme.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/DarkTheme.jvmStubs.kt
new file mode 100644
index 0000000..bb83308
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/DarkTheme.jvmStubs.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.foundation
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.ReadOnlyComposable
+
+@Composable
+@ReadOnlyComposable
+internal actual fun _isSystemInDarkTheme(): Boolean = implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/DesktopOverscroll.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/DesktopOverscroll.jvmStubs.kt
new file mode 100644
index 0000000..1f77b7d
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/DesktopOverscroll.jvmStubs.kt
@@ -0,0 +1,22 @@
+/*
+ * 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.foundation
+
+import androidx.compose.runtime.Composable
+
+@Composable
+internal actual fun rememberOverscrollEffect(): OverscrollEffect = implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/NotImplemented.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/NotImplemented.jvmStubs.kt
new file mode 100644
index 0000000..e6fddbc
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/NotImplemented.jvmStubs.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.foundation
+
+@Suppress("NOTHING_TO_INLINE")
+internal inline fun implementedInJetBrainsFork(): Nothing =
+    throw NotImplementedError(
+        """
+        Implemented only in JetBrains fork.
+        Please use `org.jetbrains.compose.foundation:foundation` package instead.
+        """
+            .trimIndent()
+    )
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/content/MediaType.desktop.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/content/MediaType.jvmStubs.kt
similarity index 100%
rename from compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/content/MediaType.desktop.kt
rename to compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/content/MediaType.jvmStubs.kt
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/content/TransferableContent.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/content/TransferableContent.jvmStubs.kt
new file mode 100644
index 0000000..0f012d2
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/content/TransferableContent.jvmStubs.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.foundation.content
+
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.implementedInJetBrainsFork
+import androidx.compose.ui.platform.ClipEntry
+import java.awt.datatransfer.Transferable
+
+@ExperimentalFoundationApi
+actual class PlatformTransferableContent internal constructor(val transferable: Transferable)
+
+@ExperimentalFoundationApi
+actual fun TransferableContent.hasMediaType(mediaType: MediaType): Boolean =
+    implementedInJetBrainsFork()
+
+internal actual fun ClipEntry.readPlainText(): String? = implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/content/internal/DragAndDropRequestPermission.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/content/internal/DragAndDropRequestPermission.jvmStubs.kt
new file mode 100644
index 0000000..72de510
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/content/internal/DragAndDropRequestPermission.jvmStubs.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.foundation.content.internal
+
+import androidx.compose.foundation.implementedInJetBrainsFork
+import androidx.compose.ui.draganddrop.DragAndDropEvent
+import androidx.compose.ui.node.DelegatableNode
+
+internal actual fun DelegatableNode.dragAndDropRequestPermission(event: DragAndDropEvent): Unit =
+    implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/content/internal/ReceiveContentDragAndDropNode.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/content/internal/ReceiveContentDragAndDropNode.jvmStubs.kt
new file mode 100644
index 0000000..9667098
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/content/internal/ReceiveContentDragAndDropNode.jvmStubs.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.foundation.content.internal
+
+import androidx.compose.foundation.implementedInJetBrainsFork
+import androidx.compose.ui.draganddrop.DragAndDropEvent
+import androidx.compose.ui.draganddrop.DragAndDropModifierNode
+
+internal actual fun ReceiveContentDragAndDropNode(
+    receiveContentConfiguration: ReceiveContentConfiguration,
+    dragAndDropRequestPermission: (DragAndDropEvent) -> Unit
+): DragAndDropModifierNode = implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/gestures/BringIntoViewSpec.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/gestures/BringIntoViewSpec.jvmStubs.kt
new file mode 100644
index 0000000..7fe1719
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/gestures/BringIntoViewSpec.jvmStubs.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.foundation.gestures
+
+import androidx.compose.foundation.implementedInJetBrainsFork
+import androidx.compose.runtime.ProvidableCompositionLocal
+
+@Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+actual val LocalBringIntoViewSpec: ProvidableCompositionLocal<BringIntoViewSpec> =
+    implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/gestures/DesktopScrollable.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/gestures/DesktopScrollable.jvmStubs.kt
new file mode 100644
index 0000000..cb480be
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/gestures/DesktopScrollable.jvmStubs.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.foundation.gestures
+
+import androidx.compose.foundation.implementedInJetBrainsFork
+import androidx.compose.ui.node.CompositionLocalConsumerModifierNode
+
+internal actual fun CompositionLocalConsumerModifierNode.platformScrollConfig(): ScrollConfig =
+    implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/lazy/layout/Lazy.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/lazy/layout/Lazy.jvmStubs.kt
new file mode 100644
index 0000000..d0d2c73
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/lazy/layout/Lazy.jvmStubs.kt
@@ -0,0 +1,21 @@
+/*
+ * 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.foundation.lazy.layout
+
+import androidx.compose.foundation.implementedInJetBrainsFork
+
+actual fun getDefaultLazyLayoutKey(index: Int): Any = implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/lazy/layout/PrefetchScheduler.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/lazy/layout/PrefetchScheduler.jvmStubs.kt
new file mode 100644
index 0000000..e6c77c1
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/lazy/layout/PrefetchScheduler.jvmStubs.kt
@@ -0,0 +1,25 @@
+/*
+ * 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.foundation.lazy.layout
+
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.implementedInJetBrainsFork
+import androidx.compose.runtime.Composable
+
+@ExperimentalFoundationApi
+@Composable
+actual fun rememberDefaultPrefetchScheduler(): PrefetchScheduler = implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/relocation/BringIntoViewResponder.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/relocation/BringIntoViewResponder.jvmStubs.kt
new file mode 100644
index 0000000..8d66a9f
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/relocation/BringIntoViewResponder.jvmStubs.kt
@@ -0,0 +1,24 @@
+/*
+ * 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.foundation.relocation
+
+import androidx.compose.foundation.implementedInJetBrainsFork
+import androidx.compose.ui.node.DelegatableNode
+
+/** Platform specific internal API to bring a rectangle into view. */
+internal actual fun DelegatableNode.defaultBringIntoViewParent(): BringIntoViewParent =
+    implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/ContextMenu.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/ContextMenu.jvmStubs.kt
new file mode 100644
index 0000000..9eb04eb
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/ContextMenu.jvmStubs.kt
@@ -0,0 +1,43 @@
+/*
+ * 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.foundation.text
+
+import androidx.compose.foundation.implementedInJetBrainsFork
+import androidx.compose.foundation.text.input.internal.selection.TextFieldSelectionState
+import androidx.compose.foundation.text.selection.SelectionManager
+import androidx.compose.foundation.text.selection.TextFieldSelectionManager
+import androidx.compose.runtime.Composable
+
+@Composable
+internal actual fun ContextMenuArea(
+    manager: TextFieldSelectionManager,
+    content: @Composable () -> Unit
+): Unit = implementedInJetBrainsFork()
+
+// todo implement
+@Composable
+internal actual inline fun ContextMenuArea(
+    selectionState: TextFieldSelectionState,
+    enabled: Boolean,
+    content: @Composable () -> Unit
+): Unit = implementedInJetBrainsFork()
+
+@Composable
+internal actual fun ContextMenuArea(
+    manager: SelectionManager,
+    content: @Composable () -> Unit
+): Unit = implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/DeadKeyCombiner.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/DeadKeyCombiner.jvmStubs.kt
new file mode 100644
index 0000000..90fe729
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/DeadKeyCombiner.jvmStubs.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.foundation.text
+
+import androidx.compose.foundation.implementedInJetBrainsFork
+import androidx.compose.ui.input.key.KeyEvent
+
+internal actual class DeadKeyCombiner {
+    actual fun consume(event: KeyEvent): Int? = implementedInJetBrainsFork()
+}
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/DesktopCursorHandle.desktop.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/DesktopCursorHandle.jvmStubs.kt
similarity index 100%
rename from compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/text/DesktopCursorHandle.desktop.kt
rename to compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/DesktopCursorHandle.jvmStubs.kt
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/KeyEventHelpers.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/KeyEventHelpers.jvmStubs.kt
new file mode 100644
index 0000000..726724e
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/KeyEventHelpers.jvmStubs.kt
@@ -0,0 +1,24 @@
+/*
+ * 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.foundation.text
+
+import androidx.compose.foundation.implementedInJetBrainsFork
+import androidx.compose.ui.input.key.KeyEvent
+
+internal actual fun KeyEvent.cancelsTextSelection(): Boolean = implementedInJetBrainsFork()
+
+internal actual fun showCharacterPalette(): Unit = implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/KeyMapping.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/KeyMapping.jvmStubs.kt
new file mode 100644
index 0000000..e6450f8
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/KeyMapping.jvmStubs.kt
@@ -0,0 +1,49 @@
+/*
+ * 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.foundation.text
+
+import androidx.compose.foundation.implementedInJetBrainsFork
+import androidx.compose.ui.input.key.Key
+
+internal actual val platformDefaultKeyMapping: KeyMapping = implementedInJetBrainsFork()
+
+internal actual object MappedKeys {
+    actual val A: Key = implementedInJetBrainsFork()
+    actual val C: Key = implementedInJetBrainsFork()
+    actual val H: Key = implementedInJetBrainsFork()
+    actual val V: Key = implementedInJetBrainsFork()
+    actual val X: Key = implementedInJetBrainsFork()
+    actual val Y: Key = implementedInJetBrainsFork()
+    actual val Z: Key = implementedInJetBrainsFork()
+    actual val Backslash: Key = implementedInJetBrainsFork()
+    actual val DirectionLeft: Key = implementedInJetBrainsFork()
+    actual val DirectionRight: Key = implementedInJetBrainsFork()
+    actual val DirectionUp: Key = implementedInJetBrainsFork()
+    actual val DirectionDown: Key = implementedInJetBrainsFork()
+    actual val PageUp: Key = implementedInJetBrainsFork()
+    actual val PageDown: Key = implementedInJetBrainsFork()
+    actual val MoveHome: Key = implementedInJetBrainsFork()
+    actual val MoveEnd: Key = implementedInJetBrainsFork()
+    actual val Insert: Key = implementedInJetBrainsFork()
+    actual val Enter: Key = implementedInJetBrainsFork()
+    actual val Backspace: Key = implementedInJetBrainsFork()
+    actual val Delete: Key = implementedInJetBrainsFork()
+    actual val Paste: Key = implementedInJetBrainsFork()
+    actual val Cut: Key = implementedInJetBrainsFork()
+    actual val Copy: Key = implementedInJetBrainsFork()
+    actual val Tab: Key = implementedInJetBrainsFork()
+}
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/StringHelpers.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/StringHelpers.jvmStubs.kt
new file mode 100644
index 0000000..18b1f9a
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/StringHelpers.jvmStubs.kt
@@ -0,0 +1,23 @@
+/*
+ * 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.foundation.text
+
+import androidx.compose.foundation.implementedInJetBrainsFork
+
+internal actual fun String.findPrecedingBreak(index: Int): Int = implementedInJetBrainsFork()
+
+internal actual fun String.findFollowingBreak(index: Int): Int = implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/TextFieldFocusModifier.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/TextFieldFocusModifier.jvmStubs.kt
new file mode 100644
index 0000000..8803750
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/TextFieldFocusModifier.jvmStubs.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.foundation.text
+
+import androidx.compose.foundation.implementedInJetBrainsFork
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.focus.FocusManager
+
+internal actual fun Modifier.interceptDPadAndMoveFocus(
+    state: LegacyTextFieldState,
+    focusManager: FocusManager
+): Modifier = implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/TextFieldKeyInput.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/TextFieldKeyInput.jvmStubs.kt
new file mode 100644
index 0000000..9702293
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/TextFieldKeyInput.jvmStubs.kt
@@ -0,0 +1,23 @@
+/*
+ * 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.foundation.text
+
+import androidx.compose.foundation.implementedInJetBrainsFork
+import androidx.compose.ui.input.key.KeyEvent
+
+actual val KeyEvent.isTypedEvent: Boolean
+    get() = implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/TextPointerIcon.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/TextPointerIcon.jvmStubs.kt
new file mode 100644
index 0000000..30f4d68
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/TextPointerIcon.jvmStubs.kt
@@ -0,0 +1,22 @@
+/*
+ * 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.foundation.text
+
+import androidx.compose.foundation.implementedInJetBrainsFork
+import androidx.compose.ui.input.pointer.PointerIcon
+
+internal actual val textPointerIcon: PointerIcon = implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/TouchMode.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/TouchMode.jvmStubs.kt
new file mode 100644
index 0000000..8f9ccec
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/TouchMode.jvmStubs.kt
@@ -0,0 +1,21 @@
+/*
+ * 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.foundation.text
+
+import androidx.compose.foundation.implementedInJetBrainsFork
+
+internal actual val isInTouchMode: Boolean = implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/handwriting/StylusHandwriting.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/handwriting/StylusHandwriting.jvmStubs.kt
new file mode 100644
index 0000000..e213288
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/handwriting/StylusHandwriting.jvmStubs.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.foundation.text.handwriting
+
+import androidx.compose.foundation.implementedInJetBrainsFork
+
+internal actual val isStylusHandwritingSupported: Boolean = implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/input/internal/DesktopTextInputSession.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/input/internal/DesktopTextInputSession.jvmStubs.kt
new file mode 100644
index 0000000..7ed3359
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/input/internal/DesktopTextInputSession.jvmStubs.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.foundation.text.input.internal
+
+import androidx.compose.foundation.content.internal.ReceiveContentConfiguration
+import androidx.compose.foundation.implementedInJetBrainsFork
+import androidx.compose.ui.platform.PlatformTextInputSession
+import androidx.compose.ui.platform.ViewConfiguration
+import androidx.compose.ui.text.input.ImeAction
+import androidx.compose.ui.text.input.ImeOptions
+import kotlinx.coroutines.flow.MutableSharedFlow
+
+internal actual suspend fun PlatformTextInputSession.platformSpecificTextInputSession(
+    state: TransformedTextFieldState,
+    layoutState: TextLayoutState,
+    imeOptions: ImeOptions,
+    receiveContentConfiguration: ReceiveContentConfiguration?,
+    onImeAction: ((ImeAction) -> Unit)?,
+    stylusHandwritingTrigger: MutableSharedFlow<Unit>?,
+    viewConfiguration: ViewConfiguration?
+): Nothing = implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/input/internal/LegacyPlatformTextInputServiceAdapter.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/input/internal/LegacyPlatformTextInputServiceAdapter.jvmStubs.kt
new file mode 100644
index 0000000..1c04d1b
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/input/internal/LegacyPlatformTextInputServiceAdapter.jvmStubs.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.foundation.text.input.internal
+
+import androidx.compose.foundation.implementedInJetBrainsFork
+
+internal actual fun createLegacyPlatformTextInputServiceAdapter():
+    LegacyPlatformTextInputServiceAdapter = implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/input/internal/TextFieldDragAndDropNode.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/input/internal/TextFieldDragAndDropNode.jvmStubs.kt
new file mode 100644
index 0000000..73d4929
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/input/internal/TextFieldDragAndDropNode.jvmStubs.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.foundation.text.input.internal
+
+import androidx.compose.foundation.content.MediaType
+import androidx.compose.foundation.implementedInJetBrainsFork
+import androidx.compose.ui.draganddrop.DragAndDropEvent
+import androidx.compose.ui.draganddrop.DragAndDropModifierNode
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.platform.ClipEntry
+import androidx.compose.ui.platform.ClipMetadata
+
+internal actual fun textFieldDragAndDropNode(
+    hintMediaTypes: () -> Set<MediaType>,
+    onDrop: (clipEntry: ClipEntry, clipMetadata: ClipMetadata) -> Boolean,
+    dragAndDropRequestPermission: (DragAndDropEvent) -> Unit,
+    onStarted: ((event: DragAndDropEvent) -> Unit)?,
+    onEntered: ((event: DragAndDropEvent) -> Unit)?,
+    onMoved: ((position: Offset) -> Unit)?,
+    onChanged: ((event: DragAndDropEvent) -> Unit)?,
+    onExited: ((event: DragAndDropEvent) -> Unit)?,
+    onEnded: ((event: DragAndDropEvent) -> Unit)?,
+): DragAndDropModifierNode = implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/input/internal/TextFieldKeyEventHandler.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/input/internal/TextFieldKeyEventHandler.jvmStubs.kt
new file mode 100644
index 0000000..b127947
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/input/internal/TextFieldKeyEventHandler.jvmStubs.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.foundation.text.input.internal
+
+import androidx.compose.foundation.implementedInJetBrainsFork
+import androidx.compose.ui.input.key.KeyEvent
+
+internal actual fun createTextFieldKeyEventHandler(): TextFieldKeyEventHandler =
+    implementedInJetBrainsFork()
+
+internal actual val KeyEvent.isFromSoftKeyboard: Boolean
+    get() = implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/input/internal/TextFieldLayoutStateCache.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/input/internal/TextFieldLayoutStateCache.jvmStubs.kt
new file mode 100644
index 0000000..7284a63
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/input/internal/TextFieldLayoutStateCache.jvmStubs.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.foundation.text.input.internal
+
+import androidx.compose.foundation.implementedInJetBrainsFork
+import androidx.compose.ui.text.intl.PlatformLocale
+import androidx.compose.ui.text.style.TextDirection
+
+internal actual fun resolveTextDirectionForKeyboardTypePhone(
+    locale: PlatformLocale
+): TextDirection = implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/input/internal/ToCharArray.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/input/internal/ToCharArray.jvmStubs.kt
new file mode 100644
index 0000000..d118d6b
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/input/internal/ToCharArray.jvmStubs.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.foundation.text.input.internal
+
+import androidx.compose.foundation.implementedInJetBrainsFork
+
+internal actual fun CharSequence.toCharArray(
+    destination: CharArray,
+    destinationOffset: Int,
+    startIndex: Int,
+    endIndex: Int
+): Unit = implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/input/internal/selection/DesktopTextFieldMagnifier.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/input/internal/selection/DesktopTextFieldMagnifier.jvmStubs.kt
new file mode 100644
index 0000000..37623cf
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/input/internal/selection/DesktopTextFieldMagnifier.jvmStubs.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.foundation.text.input.internal.selection
+
+import androidx.compose.foundation.implementedInJetBrainsFork
+import androidx.compose.foundation.text.input.internal.TextLayoutState
+import androidx.compose.foundation.text.input.internal.TransformedTextFieldState
+
+internal actual fun textFieldMagnifierNode(
+    textFieldState: TransformedTextFieldState,
+    textFieldSelectionState: TextFieldSelectionState,
+    textLayoutState: TextLayoutState,
+    visible: Boolean
+): TextFieldMagnifierNode = implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/selection/DesktopSelectionHandles.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/selection/DesktopSelectionHandles.jvmStubs.kt
new file mode 100644
index 0000000..ee80e2d
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/selection/DesktopSelectionHandles.jvmStubs.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.
+ */
+
+package androidx.compose.foundation.text.selection
+
+import androidx.compose.foundation.implementedInJetBrainsFork
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.text.style.ResolvedTextDirection
+import androidx.compose.ui.unit.DpSize
+
+@Composable
+internal actual fun SelectionHandle(
+    offsetProvider: OffsetProvider,
+    isStartHandle: Boolean,
+    direction: ResolvedTextDirection,
+    handlesCrossed: Boolean,
+    minTouchTargetSize: DpSize,
+    modifier: Modifier,
+): Unit = implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/selection/SelectionManager.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/selection/SelectionManager.jvmStubs.kt
new file mode 100644
index 0000000..870ecf8
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/selection/SelectionManager.jvmStubs.kt
@@ -0,0 +1,26 @@
+/*
+ * 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.foundation.text.selection
+
+import androidx.compose.foundation.implementedInJetBrainsFork
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.input.key.KeyEvent
+
+internal actual fun isCopyKeyEvent(keyEvent: KeyEvent): Boolean = implementedInJetBrainsFork()
+
+internal actual fun Modifier.selectionMagnifier(manager: SelectionManager): Modifier =
+    implementedInJetBrainsFork()
diff --git a/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/selection/TextFieldSelectionManager.jvmStubs.kt b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/selection/TextFieldSelectionManager.jvmStubs.kt
new file mode 100644
index 0000000..0c0ad6e
--- /dev/null
+++ b/compose/foundation/foundation/src/jvmStubsMain/kotlin/androidx/compose/foundation/text/selection/TextFieldSelectionManager.jvmStubs.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.foundation.text.selection
+
+import androidx.compose.foundation.implementedInJetBrainsFork
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.input.pointer.PointerEvent
+
+internal actual val PointerEvent.isShiftPressed: Boolean
+    get() = implementedInJetBrainsFork()
+
+internal actual fun Modifier.textFieldMagnifier(manager: TextFieldSelectionManager): Modifier =
+    implementedInJetBrainsFork()
diff --git a/compose/integration-tests/material-catalog/build.gradle b/compose/integration-tests/material-catalog/build.gradle
index 97c2ce3..973f875 100644
--- a/compose/integration-tests/material-catalog/build.gradle
+++ b/compose/integration-tests/material-catalog/build.gradle
@@ -34,8 +34,8 @@
 android {
     defaultConfig {
         applicationId "androidx.compose.material.catalog"
-        versionCode 2300
-        versionName "2.3.0"
+        versionCode 2400
+        versionName "2.4.0"
     }
     buildTypes {
         release {
diff --git a/compose/lint/common/src/main/java/androidx/compose/lint/PsiUtils.kt b/compose/lint/common/src/main/java/androidx/compose/lint/PsiUtils.kt
index e6ee457..f4509b2 100644
--- a/compose/lint/common/src/main/java/androidx/compose/lint/PsiUtils.kt
+++ b/compose/lint/common/src/main/java/androidx/compose/lint/PsiUtils.kt
@@ -17,14 +17,14 @@
 package androidx.compose.lint
 
 import com.intellij.psi.PsiClass
-import com.intellij.psi.PsiJavaFile
+import com.intellij.psi.PsiClassOwner
 import com.intellij.psi.PsiMethod
 import com.intellij.psi.PsiType
 import com.intellij.psi.util.InheritanceUtil
 
 /** Returns whether [this] has [packageName] as its package name. */
 fun PsiMethod.isInPackageName(packageName: PackageName): Boolean {
-    val actual = (containingFile as? PsiJavaFile)?.packageName
+    val actual = (containingFile as? PsiClassOwner)?.packageName
     return packageName.javaPackageName == actual
 }
 
diff --git a/compose/material/material-ripple/build.gradle b/compose/material/material-ripple/build.gradle
index cf608eb..7189ea2 100644
--- a/compose/material/material-ripple/build.gradle
+++ b/compose/material/material-ripple/build.gradle
@@ -32,7 +32,7 @@
 
 androidXMultiplatform {
     android()
-    desktop()
+    jvmStubs()
 
     defaultPlatform(PlatformIdentifier.ANDROID)
 
@@ -60,33 +60,21 @@
             }
         }
 
-        skikoMain {
-            dependsOn(commonMain)
-            dependencies {
-            }
-        }
-
         androidMain {
             dependsOn(jvmMain)
             dependencies {
             }
         }
 
-        desktopMain {
-            dependsOn(skikoMain)
+        jvmStubsMain {
             dependsOn(jvmMain)
             dependencies {
-            }
-        }
-
-        jvmTest {
-            dependsOn(commonTest)
-            dependencies {
+                implementation(libs.kotlinStdlib)
             }
         }
 
         androidInstrumentedTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(project(":compose:test-utils"))
                 implementation(project(":compose:foundation:foundation"))
@@ -98,7 +86,7 @@
         }
 
         androidUnitTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(libs.testRules)
                 implementation(libs.testRunner)
@@ -106,12 +94,6 @@
                 implementation(libs.truth)
             }
         }
-
-        desktopTest {
-            dependsOn(jvmTest)
-            dependencies {
-            }
-        }
     }
 }
 
diff --git a/compose/material/material-ripple/src/desktopMain/kotlin/androidx/compose/material/ripple/Ripple.desktop.kt b/compose/material/material-ripple/src/desktopMain/kotlin/androidx/compose/material/ripple/Ripple.desktop.kt
deleted file mode 100644
index 9f8b307..0000000
--- a/compose/material/material-ripple/src/desktopMain/kotlin/androidx/compose/material/ripple/Ripple.desktop.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material.ripple
-
-import androidx.compose.foundation.interaction.InteractionSource
-import androidx.compose.ui.graphics.ColorProducer
-import androidx.compose.ui.node.DelegatableNode
-import androidx.compose.ui.unit.Dp
-
-/** Desktop ripple implementation using the Compose-rendered [CommonRippleNode] implementation. */
-internal actual fun createPlatformRippleNode(
-    interactionSource: InteractionSource,
-    bounded: Boolean,
-    radius: Dp,
-    color: ColorProducer,
-    rippleAlpha: () -> RippleAlpha
-): DelegatableNode {
-    return CommonRippleNode(interactionSource, bounded, radius, color, rippleAlpha)
-}
-
-/** Desktop ripple implementation using the Compose-rendered [CommonRipple] implementation. */
-@Suppress("DEPRECATION")
-@Deprecated("Replaced by the new RippleNode implementation")
-internal actual typealias PlatformRipple = CommonRipple
diff --git a/compose/material/material-ripple/src/jvmStubsMain/kotlin/androidx/compose/material/ripple/NotImplemented.jvmStubs.kt b/compose/material/material-ripple/src/jvmStubsMain/kotlin/androidx/compose/material/ripple/NotImplemented.jvmStubs.kt
new file mode 100644
index 0000000..a5cf43e
--- /dev/null
+++ b/compose/material/material-ripple/src/jvmStubsMain/kotlin/androidx/compose/material/ripple/NotImplemented.jvmStubs.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material.ripple
+
+@Suppress("NOTHING_TO_INLINE")
+internal inline fun implementedInJetBrainsFork(): Nothing =
+    throw NotImplementedError(
+        """
+        Implemented only in JetBrains fork.
+        Please use `org.jetbrains.compose.material:material` package instead.
+        """
+            .trimIndent()
+    )
diff --git a/compose/material/material-ripple/src/jvmStubsMain/kotlin/androidx/compose/material/ripple/Ripple.jvmStubs.kt b/compose/material/material-ripple/src/jvmStubsMain/kotlin/androidx/compose/material/ripple/Ripple.jvmStubs.kt
new file mode 100644
index 0000000..7de618a
--- /dev/null
+++ b/compose/material/material-ripple/src/jvmStubsMain/kotlin/androidx/compose/material/ripple/Ripple.jvmStubs.kt
@@ -0,0 +1,34 @@
+/*
+ * 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.material.ripple
+
+import androidx.compose.foundation.interaction.InteractionSource
+import androidx.compose.ui.graphics.ColorProducer
+import androidx.compose.ui.node.DelegatableNode
+import androidx.compose.ui.unit.Dp
+
+internal actual fun createPlatformRippleNode(
+    interactionSource: InteractionSource,
+    bounded: Boolean,
+    radius: Dp,
+    color: ColorProducer,
+    rippleAlpha: () -> RippleAlpha
+): DelegatableNode = implementedInJetBrainsFork()
+
+@Suppress("DEPRECATION")
+@Deprecated("Replaced by the new RippleNode implementation")
+internal actual typealias PlatformRipple = CommonRipple
diff --git a/compose/material/material/build.gradle b/compose/material/material/build.gradle
index 3415437..3b446ea 100644
--- a/compose/material/material/build.gradle
+++ b/compose/material/material/build.gradle
@@ -32,7 +32,7 @@
 
 androidXMultiplatform {
     android()
-    desktop()
+    jvmStubs()
 
     defaultPlatform(PlatformIdentifier.ANDROID)
 
@@ -66,12 +66,6 @@
             }
         }
 
-        skikoMain {
-            dependsOn(commonMain)
-            dependencies {
-            }
-        }
-
         androidMain {
             dependsOn(jvmMain)
             dependencies {
@@ -85,22 +79,15 @@
             }
         }
 
-        desktopMain {
-            dependsOn(skikoMain)
+        jvmStubsMain {
             dependsOn(jvmMain)
             dependencies {
                 implementation(libs.kotlinStdlib)
             }
         }
 
-        jvmTest {
-            dependsOn(commonTest)
-            dependencies {
-            }
-        }
-
         androidInstrumentedTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(project(":compose:material:material:material-samples"))
                 implementation(project(":compose:test-utils"))
@@ -120,7 +107,7 @@
         }
 
         androidUnitTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(libs.testRules)
                 implementation(libs.testRunner)
@@ -128,16 +115,6 @@
                 implementation(libs.truth)
             }
         }
-
-        desktopTest {
-            dependsOn(jvmTest)
-            dependencies {
-                implementation(project(":compose:ui:ui-test-junit4"))
-                implementation(libs.truth)
-                implementation(libs.junit)
-                implementation(libs.skikoCurrentOs)
-            }
-        }
     }
 }
 
diff --git a/compose/material/material/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/library/model/Examples.kt b/compose/material/material/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/library/model/Examples.kt
index 319d188..0bfc7bc 100644
--- a/compose/material/material/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/library/model/Examples.kt
+++ b/compose/material/material/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/library/model/Examples.kt
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-@file:Suppress("COMPOSABLE_FUNCTION_REFERENCE")
-
 package androidx.compose.material.catalog.library.model
 
 import androidx.compose.foundation.layout.Box
@@ -112,7 +110,7 @@
 val AppBarsBottomExamples =
     listOf(
         Example(
-            name = ::SimpleBottomAppBar.name,
+            name = "SimpleBottomAppBar",
             description = AppBarsBottomExampleDescription,
             sourceUrl = AppBarsBottomExampleSourceUrl,
         ) {
@@ -125,7 +123,7 @@
 val AppBarsTopExamples =
     listOf(
         Example(
-            name = ::SimpleTopAppBar.name,
+            name = "SimpleTopAppBar",
             description = AppBarsTopExampleDescription,
             sourceUrl = AppBarsTopExampleSourceUrl
         ) {
@@ -138,7 +136,7 @@
 val BackdropExamples =
     listOf(
         Example(
-            name = ::BackdropScaffoldSample.name,
+            name = "BackdropScaffoldSample",
             description = BackdropExampleDescription,
             sourceUrl = BackdropExampleSourceUrl
         ) {
@@ -151,7 +149,7 @@
 val BadgeExamples =
     listOf(
         Example(
-            name = ::BottomNavigationItemWithBadge.name,
+            name = "BottomNavigationItemWithBadge",
             description = BadgeExampleDescription,
             sourceUrl = BadgeExampleSourceUrl
         ) {
@@ -164,14 +162,14 @@
 val BottomNavigationExamples =
     listOf(
         Example(
-            name = ::BottomNavigationSample.name,
+            name = "BottomNavigationSample",
             description = BottomNavigationExampleDescription,
             sourceUrl = BottomNavigationExampleSourceUrl
         ) {
             BottomNavigationSample()
         },
         Example(
-            name = ::BottomNavigationWithOnlySelectedLabelsSample.name,
+            name = "BottomNavigationWithOnlySelectedLabelsSample",
             description = BottomNavigationExampleDescription,
             sourceUrl = BottomNavigationExampleSourceUrl
         ) {
@@ -184,28 +182,28 @@
 val ButtonsExamples =
     listOf(
         Example(
-            name = ::ButtonSample.name,
+            name = "ButtonSample",
             description = ButtonsExampleDescription,
             sourceUrl = ButtonsExampleSourceUrl
         ) {
             ButtonSample()
         },
         Example(
-            name = ::OutlinedButtonSample.name,
+            name = "OutlinedButtonSample",
             description = ButtonsExampleDescription,
             sourceUrl = ButtonsExampleSourceUrl
         ) {
             OutlinedButtonSample()
         },
         Example(
-            name = ::TextButtonSample.name,
+            name = "TextButtonSample",
             description = ButtonsExampleDescription,
             sourceUrl = ButtonsExampleSourceUrl
         ) {
             TextButtonSample()
         },
         Example(
-            name = ::ButtonWithIconSample.name,
+            name = "ButtonWithIconSample",
             description = ButtonsExampleDescription,
             sourceUrl = ButtonsExampleSourceUrl
         ) {
@@ -219,28 +217,28 @@
 val ButtonsFloatingActionButtonExamples =
     listOf(
         Example(
-            name = ::SimpleFab.name,
+            name = "SimpleFab",
             description = ButtonsFloatingActionButtonExampleDescription,
             sourceUrl = ButtonsFloatingActionButtonExampleSourceUrl
         ) {
             SimpleFab()
         },
         Example(
-            name = ::SimpleExtendedFabNoIcon.name,
+            name = "SimpleExtendedFabNoIcon",
             description = ButtonsFloatingActionButtonExampleDescription,
             sourceUrl = ButtonsFloatingActionButtonExampleSourceUrl
         ) {
             SimpleExtendedFabNoIcon()
         },
         Example(
-            name = ::SimpleExtendedFabWithIcon.name,
+            name = "SimpleExtendedFabWithIcon",
             description = ButtonsFloatingActionButtonExampleDescription,
             sourceUrl = ButtonsFloatingActionButtonExampleSourceUrl
         ) {
             SimpleExtendedFabWithIcon()
         },
         Example(
-            name = ::FluidExtendedFab.name,
+            name = "FluidExtendedFab",
             description = ButtonsFloatingActionButtonExampleDescription,
             sourceUrl = ButtonsFloatingActionButtonExampleSourceUrl
         ) {
@@ -253,14 +251,14 @@
 val CardsExamples =
     listOf(
         Example(
-            name = ::CardSample.name,
+            name = "CardSample",
             description = CardsExampleDescription,
             sourceUrl = CardsExampleSourceUrl
         ) {
             CardSample()
         },
         Example(
-            name = ::ClickableCardSample.name,
+            name = "ClickableCardSample",
             description = CardsExampleDescription,
             sourceUrl = CardsExampleSourceUrl
         ) {
@@ -273,14 +271,14 @@
 val CheckboxesExamples =
     listOf(
         Example(
-            name = ::CheckboxSample.name,
+            name = "CheckboxSample",
             description = CheckboxesExampleDescription,
             sourceUrl = CheckboxesExampleSourceUrl
         ) {
             CheckboxSample()
         },
         Example(
-            name = ::TriStateCheckboxSample.name,
+            name = "TriStateCheckboxSample",
             description = CheckboxesExampleDescription,
             sourceUrl = CheckboxesExampleSourceUrl
         ) {
@@ -293,28 +291,28 @@
 val ChipsExamples =
     listOf(
         Example(
-            name = ::ChipSample.name,
+            name = "ChipSample",
             description = ChipsExampleDescription,
             sourceUrl = ChipsExampleSourceUrl
         ) {
             ChipSample()
         },
         Example(
-            name = ::OutlinedChipWithIconSample.name,
+            name = "OutlinedChipWithIconSample",
             description = ChipsExampleDescription,
             sourceUrl = ChipsExampleSourceUrl
         ) {
             OutlinedChipWithIconSample()
         },
         Example(
-            name = ::ChipGroupSingleLineSample.name,
+            name = "ChipGroupSingleLineSample",
             description = ChipsExampleDescription,
             sourceUrl = ChipsExampleSourceUrl
         ) {
             ChipGroupSingleLineSample()
         },
         Example(
-            name = ::ChipGroupReflowSample.name,
+            name = "ChipGroupReflowSample",
             description = ChipsExampleDescription,
             sourceUrl = ChipsExampleSourceUrl
         ) {
@@ -327,14 +325,14 @@
 val DialogsExamples =
     listOf(
         Example(
-            name = ::AlertDialogSample.name,
+            name = "AlertDialogSample",
             description = DialogsExampleDescription,
             sourceUrl = DialogsExampleSourceUrl
         ) {
             AlertDialogSample()
         },
         Example(
-            name = ::CustomAlertDialogSample.name,
+            name = "CustomAlertDialogSample",
             description = DialogsExampleDescription,
             sourceUrl = DialogsExampleSourceUrl
         ) {
@@ -350,49 +348,49 @@
 val ListsExamples =
     listOf(
         Example(
-            name = ::ClickableListItems.name,
+            name = "ClickableListItems",
             description = ListsExampleDescription,
             sourceUrl = ListsExampleSourceUrl
         ) {
             ClickableListItems()
         },
         Example(
-            name = ::OneLineListItems.name,
+            name = "OneLineListItems",
             description = ListsExampleDescription,
             sourceUrl = ListsExampleSourceUrl
         ) {
             OneLineListItems()
         },
         Example(
-            name = ::TwoLineListItems.name,
+            name = "TwoLineListItems",
             description = ListsExampleDescription,
             sourceUrl = ListsExampleSourceUrl
         ) {
             TwoLineListItems()
         },
         Example(
-            name = ::ThreeLineListItems.name,
+            name = "ThreeLineListItems",
             description = ListsExampleDescription,
             sourceUrl = ListsExampleSourceUrl
         ) {
             ThreeLineListItems()
         },
         Example(
-            name = ::OneLineRtlLtrListItems.name,
+            name = "OneLineRtlLtrListItems",
             description = ListsExampleDescription,
             sourceUrl = ListsExampleSourceUrl
         ) {
             OneLineRtlLtrListItems()
         },
         Example(
-            name = ::TwoLineRtlLtrListItems.name,
+            name = "TwoLineRtlLtrListItems",
             description = ListsExampleDescription,
             sourceUrl = ListsExampleSourceUrl
         ) {
             TwoLineRtlLtrListItems()
         },
         Example(
-            name = ::ThreeLineRtlLtrListItems.name,
+            name = "ThreeLineRtlLtrListItems",
             description = ListsExampleDescription,
             sourceUrl = ListsExampleSourceUrl
         ) {
@@ -405,21 +403,21 @@
 val MenusExamples =
     listOf(
         Example(
-            name = ::MenuSample.name,
+            name = "MenuSample",
             description = MenusExampleDescription,
             sourceUrl = MenusExampleSourceUrl
         ) {
             MenuSample()
         },
         Example(
-            name = ::MenuWithScrollStateSample.name,
+            name = "MenuWithScrollStateSample",
             description = MenusExampleDescription,
             sourceUrl = MenusExampleSourceUrl
         ) {
             MenuWithScrollStateSample()
         },
         Example(
-            name = ::ExposedDropdownMenuSample.name,
+            name = "ExposedDropdownMenuSample",
             description = MenusExampleDescription,
             sourceUrl = MenusExampleSourceUrl
         ) {
@@ -432,14 +430,14 @@
 val NavigationDrawerExamples =
     listOf(
         Example(
-            name = ::ModalDrawerSample.name,
+            name = "ModalDrawerSample",
             description = NavigationDrawerExampleDescription,
             sourceUrl = NavigationDrawerExampleSourceUrl
         ) {
             ModalDrawerSample()
         },
         Example(
-            name = ::BottomDrawerSample.name,
+            name = "BottomDrawerSample",
             description = NavigationDrawerExampleDescription,
             sourceUrl = NavigationDrawerExampleSourceUrl
         ) {
@@ -453,14 +451,14 @@
 val ProgressIndicatorsExamples =
     listOf(
         Example(
-            name = ::LinearProgressIndicatorSample.name,
+            name = "LinearProgressIndicatorSample",
             description = ProgressIndicatorsExampleDescription,
             sourceUrl = ProgressIndicatorsExampleSourceUrl
         ) {
             LinearProgressIndicatorSample()
         },
         Example(
-            name = ::CircularProgressIndicatorSample.name,
+            name = "CircularProgressIndicatorSample",
             description = ProgressIndicatorsExampleDescription,
             sourceUrl = ProgressIndicatorsExampleSourceUrl
         ) {
@@ -473,14 +471,14 @@
 val RadioButtonsExamples =
     listOf(
         Example(
-            name = ::RadioButtonSample.name,
+            name = "RadioButtonSample",
             description = RadioButtonsExampleDescription,
             sourceUrl = RadioButtonsExampleSourceUrl
         ) {
             RadioButtonSample()
         },
         Example(
-            name = ::RadioGroupSample.name,
+            name = "RadioGroupSample",
             description = RadioButtonsExampleDescription,
             sourceUrl = RadioButtonsExampleSourceUrl
         ) {
@@ -496,14 +494,14 @@
 val SheetsBottomExamples =
     listOf(
         Example(
-            name = ::BottomSheetScaffoldSample.name,
+            name = "BottomSheetScaffoldSample",
             description = SheetsBottomExampleDescription,
             sourceUrl = SheetsBottomStandardExampleSourceUrl
         ) {
             BottomSheetScaffoldSample()
         },
         Example(
-            name = ::ModalBottomSheetSample.name,
+            name = "ModalBottomSheetSample",
             description = SheetsBottomExampleDescription,
             sourceUrl = SheetsBottomModalExampleSourceUrl
         ) {
@@ -516,28 +514,28 @@
 val SlidersExamples =
     listOf(
         Example(
-            name = ::SliderSample.name,
+            name = "SliderSample",
             description = SlidersExampleDescription,
             sourceUrl = SlidersExampleSourceUrl
         ) {
             SliderSample()
         },
         Example(
-            name = ::StepsSliderSample.name,
+            name = "StepsSliderSample",
             description = SlidersExampleDescription,
             sourceUrl = SlidersExampleSourceUrl
         ) {
             StepsSliderSample()
         },
         Example(
-            name = ::RangeSliderSample.name,
+            name = "RangeSliderSample",
             description = SlidersExampleDescription,
             sourceUrl = SlidersExampleSourceUrl
         ) {
             RangeSliderSample()
         },
         Example(
-            name = ::StepRangeSliderSample.name,
+            name = "StepRangeSliderSample",
             description = SlidersExampleDescription,
             sourceUrl = SlidersExampleSourceUrl
         ) {
@@ -550,21 +548,21 @@
 val SnackbarsExamples =
     listOf(
         Example(
-            name = ::ScaffoldWithSimpleSnackbar.name,
+            name = "ScaffoldWithSimpleSnackbar",
             description = SnackbarsExampleDescription,
             sourceUrl = SnackbarsExampleSourceUrl
         ) {
             ScaffoldWithSimpleSnackbar()
         },
         Example(
-            name = ::ScaffoldWithCustomSnackbar.name,
+            name = "ScaffoldWithCustomSnackbar",
             description = SnackbarsExampleDescription,
             sourceUrl = SnackbarsExampleSourceUrl
         ) {
             ScaffoldWithCustomSnackbar()
         },
         Example(
-            name = ::ScaffoldWithCoroutinesSnackbar.name,
+            name = "ScaffoldWithCoroutinesSnackbar",
             description = SnackbarsExampleDescription,
             sourceUrl = SnackbarsExampleSourceUrl
         ) {
@@ -577,7 +575,7 @@
 val SwitchesExamples =
     listOf(
         Example(
-            name = ::SwitchSample.name,
+            name = "SwitchSample",
             description = SwitchesExampleDescription,
             sourceUrl = SwitchesExampleSourceUrl
         ) {
@@ -590,63 +588,63 @@
 val TabsExamples =
     listOf(
         Example(
-            name = ::TextTabs.name,
+            name = "TextTabs",
             description = TabsExampleDescription,
             sourceUrl = TabsExampleSourceUrl
         ) {
             TextTabs()
         },
         Example(
-            name = ::IconTabs.name,
+            name = "IconTabs",
             description = TabsExampleDescription,
             sourceUrl = TabsExampleSourceUrl
         ) {
             IconTabs()
         },
         Example(
-            name = ::TextAndIconTabs.name,
+            name = "TextAndIconTabs",
             description = TabsExampleDescription,
             sourceUrl = TabsExampleSourceUrl
         ) {
             TextAndIconTabs()
         },
         Example(
-            name = ::LeadingIconTabs.name,
+            name = "LeadingIconTabs",
             description = TabsExampleDescription,
             sourceUrl = TabsExampleSourceUrl
         ) {
             LeadingIconTabs()
         },
         Example(
-            name = ::ScrollingTextTabs.name,
+            name = "ScrollingTextTabs",
             description = TabsExampleDescription,
             sourceUrl = TabsExampleSourceUrl
         ) {
             ScrollingTextTabs()
         },
         Example(
-            name = ::FancyTabs.name,
+            name = "FancyTabs",
             description = TabsExampleDescription,
             sourceUrl = TabsExampleSourceUrl
         ) {
             FancyTabs()
         },
         Example(
-            name = ::FancyIndicatorTabs.name,
+            name = "FancyIndicatorTabs",
             description = TabsExampleDescription,
             sourceUrl = TabsExampleSourceUrl
         ) {
             FancyIndicatorTabs()
         },
         Example(
-            name = ::FancyIndicatorContainerTabs.name,
+            name = "FancyIndicatorContainerTabs",
             description = TabsExampleDescription,
             sourceUrl = TabsExampleSourceUrl
         ) {
             FancyIndicatorContainerTabs()
         },
         Example(
-            name = ::ScrollingFancyIndicatorContainerTabs.name,
+            name = "ScrollingFancyIndicatorContainerTabs",
             description = TabsExampleDescription,
             sourceUrl = TabsExampleSourceUrl
         ) {
@@ -659,77 +657,77 @@
 val TextFieldsExamples =
     listOf(
             Example(
-                name = ::SimpleTextFieldSample.name,
+                name = "SimpleTextFieldSample",
                 description = TextFieldsExampleDescription,
                 sourceUrl = TextFieldsExampleSourceUrl
             ) {
                 SimpleTextFieldSample()
             },
             Example(
-                name = ::TextFieldSample.name,
+                name = "TextFieldSample",
                 description = TextFieldsExampleDescription,
                 sourceUrl = TextFieldsExampleSourceUrl
             ) {
                 TextFieldSample()
             },
             Example(
-                name = ::SimpleOutlinedTextFieldSample.name,
+                name = "SimpleOutlinedTextFieldSample",
                 description = TextFieldsExampleDescription,
                 sourceUrl = TextFieldsExampleSourceUrl
             ) {
                 SimpleOutlinedTextFieldSample()
             },
             Example(
-                name = ::OutlinedTextFieldSample.name,
+                name = "OutlinedTextFieldSample",
                 description = TextFieldsExampleDescription,
                 sourceUrl = TextFieldsExampleSourceUrl
             ) {
                 OutlinedTextFieldSample()
             },
             Example(
-                name = ::TextFieldWithIcons.name,
+                name = "TextFieldWithIcons",
                 description = TextFieldsExampleDescription,
                 sourceUrl = TextFieldsExampleSourceUrl
             ) {
                 TextFieldWithIcons()
             },
             Example(
-                name = ::TextFieldWithPlaceholder.name,
+                name = "TextFieldWithPlaceholder",
                 description = TextFieldsExampleDescription,
                 sourceUrl = TextFieldsExampleSourceUrl
             ) {
                 TextFieldWithPlaceholder()
             },
             Example(
-                name = ::TextFieldWithErrorState.name,
+                name = "TextFieldWithErrorState",
                 description = TextFieldsExampleDescription,
                 sourceUrl = TextFieldsExampleSourceUrl
             ) {
                 TextFieldWithErrorState()
             },
             Example(
-                name = ::TextFieldWithHelperMessage.name,
+                name = "TextFieldWithHelperMessage",
                 description = TextFieldsExampleDescription,
                 sourceUrl = TextFieldsExampleSourceUrl
             ) {
                 TextFieldWithHelperMessage()
             },
             Example(
-                name = ::PasswordTextField.name,
+                name = "PasswordTextField",
                 description = TextFieldsExampleDescription,
                 sourceUrl = TextFieldsExampleSourceUrl
             ) {
                 PasswordTextField()
             },
             Example(
-                name = ::TextFieldWithHideKeyboardOnImeAction.name,
+                name = "TextFieldWithHideKeyboardOnImeAction",
                 description = TextFieldsExampleDescription,
                 sourceUrl = TextFieldsExampleSourceUrl
             ) {
                 TextFieldWithHideKeyboardOnImeAction()
             },
             Example(
-                name = ::TextArea.name,
+                name = "TextArea",
                 description = TextFieldsExampleDescription,
                 sourceUrl = TextFieldsExampleSourceUrl
             ) {
@@ -750,28 +748,28 @@
 val NavigationRailExamples =
     listOf(
         Example(
-            name = ::NavigationRailSample.name,
+            name = "NavigationRailSample",
             description = NavigationRailExampleDescription,
             sourceUrl = NavigationRailExampleSourceUrl
         ) {
             NavigationRailSample()
         },
         Example(
-            name = ::NavigationRailWithOnlySelectedLabelsSample.name,
+            name = "NavigationRailWithOnlySelectedLabelsSample",
             description = NavigationRailExampleDescription,
             sourceUrl = NavigationRailExampleSourceUrl
         ) {
             NavigationRailWithOnlySelectedLabelsSample()
         },
         Example(
-            name = ::CompactNavigationRailSample.name,
+            name = "CompactNavigationRailSample",
             description = NavigationRailExampleDescription,
             sourceUrl = NavigationRailExampleSourceUrl
         ) {
             CompactNavigationRailSample()
         },
         Example(
-            name = ::NavigationRailBottomAlignSample.name,
+            name = "NavigationRailBottomAlignSample",
             description = NavigationRailExampleDescription,
             sourceUrl = NavigationRailExampleSourceUrl
         ) {
diff --git a/compose/material/material/src/androidInstrumentedTest/kotlin/androidx/compose/material/RippleTest.kt b/compose/material/material/src/androidInstrumentedTest/kotlin/androidx/compose/material/RippleTest.kt
index 7c05cfb..35bd0ea 100644
--- a/compose/material/material/src/androidInstrumentedTest/kotlin/androidx/compose/material/RippleTest.kt
+++ b/compose/material/material/src/androidInstrumentedTest/kotlin/androidx/compose/material/RippleTest.kt
@@ -1092,6 +1092,88 @@
     }
 
     /**
+     * Regression test for b/348379457 : going from enabled -> disabled -> enabled should show a
+     * valid ripple, and going to disabled after that should not crash.
+     */
+    @Test
+    fun rippleConfigurationToggleBetweenEnabledAndDisabled() {
+        val interactionSource = MutableInteractionSource()
+
+        val contentColor = Color.Black
+
+        var rippleConfiguration: RippleConfiguration? by mutableStateOf(RippleConfiguration())
+        val dragStart1 = DragInteraction.Start()
+        val dragStop1 = DragInteraction.Stop(dragStart1)
+        val dragStart2 = DragInteraction.Start()
+        val dragStop2 = DragInteraction.Stop(dragStart2)
+        val dragStart3 = DragInteraction.Start()
+
+        var scope: CoroutineScope? = null
+
+        rule.setContent {
+            scope = rememberCoroutineScope()
+            MaterialTheme {
+                Surface(contentColor = contentColor) {
+                    CompositionLocalProvider(
+                        LocalRippleConfiguration provides rippleConfiguration
+                    ) {
+                        Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
+                            RippleBoxWithBackground(interactionSource, ripple(), bounded = true)
+                        }
+                    }
+                }
+            }
+        }
+
+        rule.runOnIdle { scope!!.launch { interactionSource.emit(dragStart1) } }
+        rule.waitForIdle()
+
+        with(rule.onNodeWithTag(Tag)) {
+            val centerPixel =
+                captureToImage().asAndroidBitmap().run { getPixel(width / 2, height / 2) }
+
+            val expectedColor = calculateResultingRippleColor(contentColor, rippleOpacity = 0.08f)
+
+            Truth.assertThat(Color(centerPixel)).isEqualTo(expectedColor)
+        }
+
+        rule.runOnIdle { scope!!.launch { interactionSource.emit(dragStop1) } }
+        // Disable the ripple
+        rule.runOnIdle { rippleConfiguration = null }
+
+        rule.runOnIdle { scope!!.launch { interactionSource.emit(dragStart2) } }
+
+        with(rule.onNodeWithTag(Tag)) {
+            val centerPixel =
+                captureToImage().asAndroidBitmap().run { getPixel(width / 2, height / 2) }
+
+            // There should not be a ripple
+            Truth.assertThat(Color(centerPixel)).isEqualTo(RippleBoxBackgroundColor)
+        }
+
+        rule.runOnIdle { scope!!.launch { interactionSource.emit(dragStop2) } }
+        // Enable the ripple again
+        rule.runOnIdle { rippleConfiguration = RippleConfiguration() }
+
+        // The ripple should show again
+        rule.runOnIdle { scope!!.launch { interactionSource.emit(dragStart3) } }
+
+        with(rule.onNodeWithTag(Tag)) {
+            val centerPixel =
+                captureToImage().asAndroidBitmap().run { getPixel(width / 2, height / 2) }
+
+            val expectedColor = calculateResultingRippleColor(contentColor, rippleOpacity = 0.08f)
+
+            Truth.assertThat(Color(centerPixel)).isEqualTo(expectedColor)
+        }
+
+        // Disable the ripple again
+        rule.runOnIdle { rippleConfiguration = null }
+        // Should not crash
+        rule.waitForIdle()
+    }
+
+    /**
      * Asserts that the resultant color of the ripple on screen matches [expectedCenterPixelColor].
      *
      * @param interactionSource the [MutableInteractionSource] driving the ripple
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Ripple.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Ripple.kt
index 69c2169..0ed73bc 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Ripple.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Ripple.kt
@@ -342,6 +342,7 @@
 
     private fun removeRipple() {
         rippleNode?.let { undelegate(it) }
+        rippleNode = null
     }
 }
 
diff --git a/compose/material/material/src/desktopMain/kotlin/androidx/compose/material/DefaultPlatformTextStyle.desktop.kt b/compose/material/material/src/desktopMain/kotlin/androidx/compose/material/DefaultPlatformTextStyle.desktop.kt
deleted file mode 100644
index 873b9e0..0000000
--- a/compose/material/material/src/desktopMain/kotlin/androidx/compose/material/DefaultPlatformTextStyle.desktop.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material
-
-import androidx.compose.ui.text.PlatformTextStyle
-
-internal actual fun defaultPlatformTextStyle(): PlatformTextStyle? = null
diff --git a/compose/material/material/src/desktopMain/kotlin/androidx/compose/material/DesktopMenu.desktop.kt b/compose/material/material/src/desktopMain/kotlin/androidx/compose/material/DesktopMenu.desktop.kt
deleted file mode 100644
index 8e566b9..0000000
--- a/compose/material/material/src/desktopMain/kotlin/androidx/compose/material/DesktopMenu.desktop.kt
+++ /dev/null
@@ -1,454 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material
-
-import androidx.compose.animation.core.MutableTransitionState
-import androidx.compose.foundation.ScrollState
-import androidx.compose.foundation.interaction.MutableInteractionSource
-import androidx.compose.foundation.layout.ColumnScope
-import androidx.compose.foundation.layout.PaddingValues
-import androidx.compose.foundation.layout.RowScope
-import androidx.compose.foundation.rememberScrollState
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.Immutable
-import androidx.compose.runtime.MutableState
-import androidx.compose.runtime.Stable
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.focus.FocusManager
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.graphics.TransformOrigin
-import androidx.compose.ui.input.InputModeManager
-import androidx.compose.ui.platform.LocalFocusManager
-import androidx.compose.ui.platform.LocalInputModeManager
-import androidx.compose.ui.unit.DpOffset
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.window.Popup
-import androidx.compose.ui.window.PopupPositionProvider
-import androidx.compose.ui.window.PopupProperties
-import androidx.compose.ui.window.rememberCursorPositionProvider
-import androidx.compose.ui.window.rememberPopupPositionProviderAtPosition
-
-/**
- * A Material Design [dropdown menu](https://material.io/components/menus#dropdown-menu).
- *
- * A [DropdownMenu] behaves similarly to a [Popup], and will use the position of the parent layout
- * to position itself on screen. Commonly a [DropdownMenu] will be placed in a [Box] with a sibling
- * that will be used as the 'anchor'. Note that a [DropdownMenu] by itself will not take up any
- * space in a layout, as the menu is displayed in a separate window, on top of other content.
- *
- * The [content] of a [DropdownMenu] will typically be [DropdownMenuItem]s, as well as custom
- * content. Using [DropdownMenuItem]s will result in a menu that matches the Material specification
- * for menus. Also note that the [content] is placed inside a scrollable [Column], so using a
- * [LazyColumn] as the root layout inside [content] is unsupported.
- *
- * [onDismissRequest] will be called when the menu should close - for example when there is a tap
- * outside the menu, or when the back key is pressed.
- *
- * [DropdownMenu] changes its positioning depending on the available space, always trying to be
- * fully visible. It will try to expand horizontally, depending on layout direction, to the end of
- * its parent, then to the start of its parent, and then screen end-aligned. Vertically, it will try
- * to expand to the bottom of its parent, then from the top of its parent, and then screen
- * top-aligned. An [offset] can be provided to adjust the positioning of the menu for cases when the
- * layout bounds of its parent do not coincide with its visual bounds. Note the offset will be
- * applied in the direction in which the menu will decide to expand.
- *
- * Example usage:
- *
- * @sample androidx.compose.material.samples.MenuSample
- * @param expanded Whether the menu is currently open and visible to the user
- * @param onDismissRequest Called when the user requests to dismiss the menu, such as by tapping
- *   outside the menu's bounds
- * @param focusable Whether the dropdown can capture focus
- * @param modifier Modifier for the menu
- * @param offset [DpOffset] to be added to the position of the menu
- * @param content content lambda
- */
-@Deprecated(
-    level = DeprecationLevel.HIDDEN,
-    replaceWith =
-        ReplaceWith(
-            expression =
-                "DropdownMenu(expanded,onDismissRequest, focusable, modifier, offset, " +
-                    "rememberScrollState(), content)",
-            "androidx.compose.foundation.rememberScrollState"
-        ),
-    message = "Replaced by a DropdownMenu function with a ScrollState parameter"
-)
-@Composable
-fun DropdownMenu(
-    expanded: Boolean,
-    onDismissRequest: () -> Unit,
-    focusable: Boolean = true,
-    modifier: Modifier = Modifier,
-    offset: DpOffset = DpOffset(0.dp, 0.dp),
-    content: @Composable ColumnScope.() -> Unit
-) =
-    DropdownMenu(
-        expanded = expanded,
-        onDismissRequest = onDismissRequest,
-        modifier = modifier,
-        offset = offset,
-        scrollState = rememberScrollState(),
-        properties = PopupProperties(focusable = focusable),
-        content = content
-    )
-
-/**
- * A Material Design [dropdown menu](https://material.io/components/menus#dropdown-menu).
- *
- * A [DropdownMenu] behaves similarly to a [Popup], and will use the position of the parent layout
- * to position itself on screen. Commonly a [DropdownMenu] will be placed in a [Box] with a sibling
- * that will be used as the 'anchor'. Note that a [DropdownMenu] by itself will not take up any
- * space in a layout, as the menu is displayed in a separate window, on top of other content.
- *
- * The [content] of a [DropdownMenu] will typically be [DropdownMenuItem]s, as well as custom
- * content. Using [DropdownMenuItem]s will result in a menu that matches the Material specification
- * for menus. Also note that the [content] is placed inside a scrollable [Column], so using a
- * [LazyColumn] as the root layout inside [content] is unsupported.
- *
- * [onDismissRequest] will be called when the menu should close - for example when there is a tap
- * outside the menu, or when the back key is pressed.
- *
- * [DropdownMenu] changes its positioning depending on the available space, always trying to be
- * fully visible. It will try to expand horizontally, depending on layout direction, to the end of
- * its parent, then to the start of its parent, and then screen end-aligned. Vertically, it will try
- * to expand to the bottom of its parent, then from the top of its parent, and then screen
- * top-aligned. An [offset] can be provided to adjust the positioning of the menu for cases when the
- * layout bounds of its parent do not coincide with its visual bounds. Note the offset will be
- * applied in the direction in which the menu will decide to expand.
- *
- * Example usage:
- *
- * @sample androidx.compose.material.samples.MenuSample
- *
- * Example usage with a [ScrollState] to control the menu items scroll position:
- *
- * @sample androidx.compose.material.samples.MenuWithScrollStateSample
- * @param expanded Whether the menu is currently open and visible to the user
- * @param onDismissRequest Called when the user requests to dismiss the menu, such as by tapping
- *   outside the menu's bounds
- * @param focusable Whether the dropdown can capture focus
- * @param modifier [Modifier] to be applied to the menu's content
- * @param offset [DpOffset] to be added to the position of the menu
- * @param scrollState a [ScrollState] to used by the menu's content for items vertical scrolling
- * @param content the content of this dropdown menu, typically a [DropdownMenuItem]
- */
-@Deprecated(
-    "Replaced by DropdownMenu with properties parameter",
-    ReplaceWith(
-        "DropdownMenu(expanded, onDismissRequest, modifier, offset, scrollState," +
-            "androidx.compose.ui.window.PopupProperties(focusable = focusable), " +
-            "content)"
-    ),
-    level = DeprecationLevel.HIDDEN
-)
-@Composable
-fun DropdownMenu(
-    expanded: Boolean,
-    onDismissRequest: () -> Unit,
-    focusable: Boolean = true,
-    modifier: Modifier = Modifier,
-    offset: DpOffset = DpOffset(0.dp, 0.dp),
-    scrollState: ScrollState = rememberScrollState(),
-    content: @Composable ColumnScope.() -> Unit
-): Unit =
-    DropdownMenu(
-        expanded = expanded,
-        onDismissRequest = onDismissRequest,
-        modifier = modifier,
-        offset = offset,
-        scrollState = scrollState,
-        properties = PopupProperties(focusable = focusable),
-        content = content
-    )
-
-// Workaround for `Overload resolution ambiguity` between old and new overload.
-@Deprecated("Maintained for binary compatibility", level = DeprecationLevel.HIDDEN)
-@Composable
-fun DropdownMenu(
-    expanded: Boolean,
-    onDismissRequest: () -> Unit,
-    modifier: Modifier = Modifier,
-    offset: DpOffset = DpOffset(0.dp, 0.dp),
-    scrollState: ScrollState = rememberScrollState(),
-    content: @Composable ColumnScope.() -> Unit
-): Unit =
-    DropdownMenu(
-        expanded = expanded,
-        onDismissRequest = onDismissRequest,
-        modifier = modifier,
-        offset = offset,
-        scrollState = scrollState,
-        properties = PopupProperties(focusable = true),
-        content = content
-    )
-
-/**
- * A variant of a dropdown menu that accepts a [DropdownMenuState] to allow precise positioning.
- *
- * Typically, it should be combined with [Modifier.contextMenuOpenDetector] via state-hoisting.
- *
- * @param state The open/closed state of the menu.
- * @param onDismissRequest Called when the user requests to dismiss the menu, such as by tapping
- *   outside the menu's bounds
- * @param content the content of this dropdown menu, typically a [DropdownMenuItem]
- */
-@Deprecated(
-    level = DeprecationLevel.HIDDEN,
-    replaceWith =
-        ReplaceWith(
-            expression =
-                "DropdownMenu(state, onDismissRequest, focusable, modifier, offset, " +
-                    "rememberScrollState(), content)",
-            "androidx.compose.foundation.rememberScrollState"
-        ),
-    message = "Replaced by a DropdownMenu function with a ScrollState parameter"
-)
-@Composable
-fun DropdownMenu(
-    state: DropdownMenuState,
-    onDismissRequest: () -> Unit = { state.status = DropdownMenuState.Status.Closed },
-    focusable: Boolean = true,
-    modifier: Modifier = Modifier,
-    content: @Composable ColumnScope.() -> Unit
-) {
-    DropdownMenu(state, onDismissRequest, focusable, modifier, rememberScrollState(), content)
-}
-
-/**
- * A variant of a dropdown menu that accepts a [DropdownMenuState] to allow precise positioning.
- *
- * Typically, it should be combined with [Modifier.contextMenuOpenDetector] via state-hoisting.
- *
- * Example usage with a [ScrollState] to control the menu items scroll position:
- *
- * @sample androidx.compose.material.samples.MenuWithScrollStateSample
- * @param state The open/closed state of the menu
- * @param onDismissRequest Called when the user requests to dismiss the menu, such as by tapping
- *   outside the menu's bounds
- * @param focusable Whether the dropdown can capture focus
- * @param modifier [Modifier] to be applied to the menu's content
- * @param scrollState a [ScrollState] to used by the menu's content for items vertical scrolling
- * @param content the content of this dropdown menu, typically a [DropdownMenuItem]
- */
-@Composable
-fun DropdownMenu(
-    state: DropdownMenuState,
-    onDismissRequest: () -> Unit = { state.status = DropdownMenuState.Status.Closed },
-    focusable: Boolean = true,
-    modifier: Modifier = Modifier,
-    scrollState: ScrollState = rememberScrollState(),
-    content: @Composable ColumnScope.() -> Unit
-) {
-    val status = state.status
-    var position: Offset? by remember { mutableStateOf(null) }
-    val expandedStates = remember { MutableTransitionState(false) }
-    expandedStates.targetState = status is DropdownMenuState.Status.Open
-
-    // Whenever we are asked to open the popup, remember the position
-    if (status is DropdownMenuState.Status.Open) {
-        position = status.position
-    }
-
-    if (expandedStates.currentState || expandedStates.targetState) {
-        OpenDropdownMenu(
-            expandedStates = expandedStates,
-            popupPositionProvider = rememberPopupPositionProviderAtPosition(position!!),
-            scrollState = scrollState,
-            onDismissRequest = onDismissRequest,
-            focusable = focusable,
-            modifier = modifier,
-            content = content
-        )
-    }
-}
-
-/** The implementation of a [DropdownMenu] in its open state. */
-@Composable
-private fun OpenDropdownMenu(
-    expandedStates: MutableTransitionState<Boolean>,
-    popupPositionProvider: PopupPositionProvider,
-    transformOriginState: MutableState<TransformOrigin> = remember {
-        mutableStateOf(TransformOrigin.Center)
-    },
-    scrollState: ScrollState,
-    onDismissRequest: () -> Unit,
-    focusable: Boolean = true,
-    modifier: Modifier = Modifier,
-    content: @Composable ColumnScope.() -> Unit
-) {
-    var focusManager: FocusManager? by remember { mutableStateOf(null) }
-    var inputModeManager: InputModeManager? by remember { mutableStateOf(null) }
-    Popup(
-        onDismissRequest = onDismissRequest,
-        popupPositionProvider = popupPositionProvider,
-        properties = PopupProperties(focusable = focusable),
-        onKeyEvent = { handlePopupOnKeyEvent(it, focusManager!!, inputModeManager!!) },
-    ) {
-        focusManager = LocalFocusManager.current
-        inputModeManager = LocalInputModeManager.current
-
-        DropdownMenuContent(
-            expandedStates = expandedStates,
-            transformOriginState = transformOriginState,
-            scrollState = scrollState,
-            modifier = modifier,
-            content = content
-        )
-    }
-}
-
-@Composable
-actual fun DropdownMenuItem(
-    onClick: () -> Unit,
-    modifier: Modifier,
-    enabled: Boolean,
-    contentPadding: PaddingValues,
-    interactionSource: MutableInteractionSource?,
-    content: @Composable RowScope.() -> Unit
-): Unit =
-    DropdownMenuItemContent(
-        onClick,
-        modifier,
-        enabled,
-        contentPadding,
-        interactionSource,
-        content = content
-    )
-
-/**
- * A [CursorDropdownMenu] behaves similarly to [Popup] and will use the current position of the
- * mouse cursor to position itself on screen.
- *
- * The [content] of a [CursorDropdownMenu] will typically be [DropdownMenuItem]s, as well as custom
- * content. Using [DropdownMenuItem]s will result in a menu that matches the Material specification
- * for menus.
- *
- * @param expanded Whether the menu is currently open and visible to the user
- * @param onDismissRequest Called when the user requests to dismiss the menu, such as by tapping
- *   outside the menu's bounds
- * @param focusable Sets the ability for the menu to capture focus
- * @param modifier The modifier for this layout.
- * @param content The content lambda.
- */
-@Deprecated(
-    level = DeprecationLevel.HIDDEN,
-    replaceWith =
-        ReplaceWith(
-            expression =
-                "CursorDropdownMenu(expanded, onDismissRequest, focusable, modifier, " +
-                    "rememberScrollState(), content)",
-            "androidx.compose.foundation.rememberScrollState"
-        ),
-    message = "Replaced by a CursorDropdownMenu function with a ScrollState parameter"
-)
-@Composable
-fun CursorDropdownMenu(
-    expanded: Boolean,
-    onDismissRequest: () -> Unit,
-    focusable: Boolean = true,
-    modifier: Modifier = Modifier,
-    content: @Composable ColumnScope.() -> Unit
-) =
-    CursorDropdownMenu(
-        expanded = expanded,
-        onDismissRequest = onDismissRequest,
-        focusable = focusable,
-        modifier = modifier,
-        scrollState = rememberScrollState(),
-        content = content
-    )
-
-/**
- * A [CursorDropdownMenu] behaves similarly to [Popup] and will use the current position of the
- * mouse cursor to position itself on screen.
- *
- * The [content] of a [CursorDropdownMenu] will typically be [DropdownMenuItem]s, as well as custom
- * content. Using [DropdownMenuItem]s will result in a menu that matches the Material specification
- * for menus.
- *
- * @param expanded Whether the menu is currently open and visible to the user
- * @param onDismissRequest Called when the user requests to dismiss the menu, such as by tapping
- *   outside the menu's bounds
- * @param focusable Whether the dropdown can capture focus
- * @param modifier [Modifier] to be applied to the menu's content
- * @param scrollState a [ScrollState] to used by the menu's content for items vertical scrolling
- * @param content the content of this dropdown menu, typically a [DropdownMenuItem]
- */
-@Composable
-fun CursorDropdownMenu(
-    expanded: Boolean,
-    onDismissRequest: () -> Unit,
-    focusable: Boolean = true,
-    modifier: Modifier = Modifier,
-    scrollState: ScrollState = rememberScrollState(),
-    content: @Composable ColumnScope.() -> Unit
-) {
-    val expandedStates = remember { MutableTransitionState(false) }
-    expandedStates.targetState = expanded
-
-    if (expandedStates.currentState || expandedStates.targetState) {
-        OpenDropdownMenu(
-            expandedStates = expandedStates,
-            popupPositionProvider = rememberCursorPositionProvider(),
-            scrollState = scrollState,
-            onDismissRequest = onDismissRequest,
-            focusable = focusable,
-            modifier = modifier,
-            content = content
-        )
-    }
-}
-
-/** Represents the open/closed state of a dropdown menu. */
-@Stable
-class DropdownMenuState(initialStatus: Status = Status.Closed) {
-
-    /** The current status of the menu. */
-    var status: Status by mutableStateOf(initialStatus)
-
-    @Immutable
-    sealed class Status {
-
-        class Open(val position: Offset) : Status() {
-
-            override fun equals(other: Any?): Boolean {
-                if (this === other) return true
-
-                if (other !is Open) return false
-
-                if (position != other.position) return false
-
-                return true
-            }
-
-            override fun hashCode(): Int {
-                return position.hashCode()
-            }
-
-            override fun toString(): String {
-                return "Open(position=$position)"
-            }
-        }
-
-        object Closed : Status()
-    }
-}
diff --git a/compose/material/material/src/desktopMain/kotlin/androidx/compose/material/MaterialTheme.desktop.kt b/compose/material/material/src/desktopMain/kotlin/androidx/compose/material/MaterialTheme.desktop.kt
deleted file mode 100644
index b4d36c6..0000000
--- a/compose/material/material/src/desktopMain/kotlin/androidx/compose/material/MaterialTheme.desktop.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material
-
-import androidx.compose.foundation.LocalScrollbarStyle
-import androidx.compose.foundation.defaultScrollbarStyle
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.CompositionLocalProvider
-
-@Composable
-internal actual fun PlatformMaterialTheme(content: @Composable () -> Unit) {
-    CompositionLocalProvider(
-        LocalScrollbarStyle provides
-            defaultScrollbarStyle()
-                .copy(
-                    shape = MaterialTheme.shapes.small,
-                    unhoverColor = MaterialTheme.colors.onSurface.copy(alpha = 0.12f),
-                    hoverColor = MaterialTheme.colors.onSurface.copy(alpha = 0.50f)
-                ),
-        content = content
-    )
-}
diff --git a/compose/material/material/src/desktopMain/kotlin/androidx/compose/material/Strings.desktop.kt b/compose/material/material/src/desktopMain/kotlin/androidx/compose/material/Strings.desktop.kt
deleted file mode 100644
index b1f629d..0000000
--- a/compose/material/material/src/desktopMain/kotlin/androidx/compose/material/Strings.desktop.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material
-
-import androidx.compose.runtime.Composable
-
-@Composable
-internal actual fun getString(string: Strings): String {
-    return when (string) {
-        Strings.NavigationMenu -> "Navigation menu"
-        Strings.CloseDrawer -> "Close navigation menu"
-        Strings.CloseSheet -> "Close sheet"
-        Strings.DefaultErrorMessage -> "Invalid input"
-        else -> ""
-    }
-}
diff --git a/compose/material/material/src/desktopMain/kotlin/androidx/compose/material/SystemBarsDefaultInsets.desktop.kt b/compose/material/material/src/desktopMain/kotlin/androidx/compose/material/SystemBarsDefaultInsets.desktop.kt
deleted file mode 100644
index 3ca24d7..0000000
--- a/compose/material/material/src/desktopMain/kotlin/androidx/compose/material/SystemBarsDefaultInsets.desktop.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material
-
-import androidx.compose.foundation.layout.WindowInsets
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.unit.dp
-
-internal actual val WindowInsets.Companion.systemBarsForVisualComponents: WindowInsets
-    @Composable get() = WindowInsets(0.dp, 0.dp, 0.dp, 0.dp)
diff --git a/compose/material/material/src/desktopTest/kotlin/androidx/compose/material/DesktopAlertDialogTest.kt b/compose/material/material/src/desktopTest/kotlin/androidx/compose/material/DesktopAlertDialogTest.kt
deleted file mode 100644
index 4a7d166..0000000
--- a/compose/material/material/src/desktopTest/kotlin/androidx/compose/material/DesktopAlertDialogTest.kt
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material
-
-import androidx.compose.foundation.layout.size
-import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.layout.onGloballyPositioned
-import androidx.compose.ui.layout.positionInRoot
-import androidx.compose.ui.platform.LocalDensity
-import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.compose.ui.unit.Density
-import androidx.compose.ui.unit.IntSize
-import androidx.compose.ui.unit.dp
-import com.google.common.truth.Truth.assertThat
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class DesktopAlertDialogTest {
-
-    @get:Rule val rule = createComposeRule()
-
-    @Test
-    fun alignedToCenter_inPureWindow() {
-        var rootSize = IntSize(1024, 768) // default value
-        var dialogSize = IntSize(150, 150)
-        var location = Offset.Zero
-        rule.setContent {
-            CompositionLocalProvider(LocalDensity provides Density(1f, 1f)) {
-                @OptIn(ExperimentalMaterialApi::class)
-                AlertDialog(
-                    onDismissRequest = {},
-                    title = { Text("AlerDialog") },
-                    text = { Text("Apply?") },
-                    confirmButton = { Button(onClick = {}) { Text("Apply") } },
-                    modifier =
-                        Modifier.size(dialogSize.width.dp, dialogSize.height.dp)
-                            .onGloballyPositioned { location = it.positionInRoot() }
-                )
-            }
-        }
-        rule.runOnIdle {
-            assertThat(location).isEqualTo(calculateCenterPosition(rootSize, dialogSize))
-        }
-    }
-
-    private fun calculateCenterPosition(rootSize: IntSize, childSize: IntSize): Offset {
-        val x = (rootSize.width - childSize.width) / 2f
-        val y = (rootSize.height - childSize.height) / 2f
-        return Offset(x, y)
-    }
-}
diff --git a/compose/material/material/src/desktopTest/kotlin/androidx/compose/material/DesktopMenuTest.kt b/compose/material/material/src/desktopTest/kotlin/androidx/compose/material/DesktopMenuTest.kt
deleted file mode 100644
index 0dcc06a..0000000
--- a/compose/material/material/src/desktopTest/kotlin/androidx/compose/material/DesktopMenuTest.kt
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material
-
-import androidx.compose.ui.unit.Density
-import androidx.compose.ui.unit.DpOffset
-import androidx.compose.ui.unit.IntOffset
-import androidx.compose.ui.unit.IntRect
-import androidx.compose.ui.unit.IntSize
-import androidx.compose.ui.unit.LayoutDirection
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class DesktopMenuTest {
-    private val windowSize = IntSize(200, 200)
-
-    // Standard case: enough room to position below the anchor and align left
-    @Test
-    fun menu_positioning_alignLeft_belowAnchor() {
-        val anchorBounds = IntRect(offset = IntOffset(10, 50), size = IntSize(50, 20))
-        val popupSize = IntSize(70, 70)
-
-        val position =
-            DropdownMenuPositionProvider(DpOffset.Zero, Density(1f))
-                .calculatePosition(anchorBounds, windowSize, LayoutDirection.Ltr, popupSize)
-
-        assertThat(position).isEqualTo(anchorBounds.bottomLeft)
-    }
-
-    // Standard RTL case: enough room to position below the anchor and align right
-    @Test
-    fun menu_positioning_rtl_alignRight_belowAnchor() {
-        val anchorBounds = IntRect(offset = IntOffset(30, 50), size = IntSize(50, 20))
-        val popupSize = IntSize(70, 70)
-
-        val position =
-            DropdownMenuPositionProvider(DpOffset.Zero, Density(1f))
-                .calculatePosition(anchorBounds, windowSize, LayoutDirection.Rtl, popupSize)
-
-        assertThat(position)
-            .isEqualTo(IntOffset(x = anchorBounds.right - popupSize.width, y = anchorBounds.bottom))
-    }
-
-    // Not enough room to position the popup below the anchor, but enough room above
-    @Test
-    fun menu_positioning_alignLeft_aboveAnchor() {
-        val anchorBounds = IntRect(offset = IntOffset(10, 150), size = IntSize(50, 30))
-        val popupSize = IntSize(70, 30)
-
-        val position =
-            DropdownMenuPositionProvider(DpOffset.Zero, Density(1f))
-                .calculatePosition(anchorBounds, windowSize, LayoutDirection.Ltr, popupSize)
-
-        assertThat(position)
-            .isEqualTo(IntOffset(x = anchorBounds.left, y = anchorBounds.top - popupSize.height))
-    }
-
-    // Anchor left is at negative coordinates, so align popup to the left of the window
-    @Test
-    fun menu_positioning_windowLeft_belowAnchor() {
-        val anchorBounds = IntRect(offset = IntOffset(-10, 50), size = IntSize(50, 20))
-        val popupSize = IntSize(70, 50)
-
-        val position =
-            DropdownMenuPositionProvider(DpOffset.Zero, Density(1f))
-                .calculatePosition(
-                    anchorBounds = anchorBounds,
-                    windowSize,
-                    LayoutDirection.Ltr,
-                    popupSize
-                )
-
-        assertThat(position).isEqualTo(IntOffset(0, anchorBounds.bottom))
-    }
-}
diff --git a/compose/material/material/src/jvmStubsMain/kotlin/androidx/compose/material/AlertDialog.jvmStubs.kt b/compose/material/material/src/jvmStubsMain/kotlin/androidx/compose/material/AlertDialog.jvmStubs.kt
new file mode 100644
index 0000000..a6ca27f
--- /dev/null
+++ b/compose/material/material/src/jvmStubsMain/kotlin/androidx/compose/material/AlertDialog.jvmStubs.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.window.DialogProperties
+
+@Composable
+actual fun AlertDialog(
+    onDismissRequest: () -> Unit,
+    confirmButton: @Composable () -> Unit,
+    modifier: Modifier,
+    dismissButton: @Composable (() -> Unit)?,
+    title: @Composable (() -> Unit)?,
+    text: @Composable (() -> Unit)?,
+    shape: Shape,
+    backgroundColor: Color,
+    contentColor: Color,
+    properties: DialogProperties
+): Unit = implementedInJetBrainsFork()
+
+@Composable
+actual fun AlertDialog(
+    onDismissRequest: () -> Unit,
+    buttons: @Composable () -> Unit,
+    modifier: Modifier,
+    title: (@Composable () -> Unit)?,
+    text: @Composable (() -> Unit)?,
+    shape: Shape,
+    backgroundColor: Color,
+    contentColor: Color,
+    properties: DialogProperties
+): Unit = implementedInJetBrainsFork()
diff --git a/compose/material/material/src/jvmStubsMain/kotlin/androidx/compose/material/DefaultPlatformTextStyle.jvmStubs.kt b/compose/material/material/src/jvmStubsMain/kotlin/androidx/compose/material/DefaultPlatformTextStyle.jvmStubs.kt
new file mode 100644
index 0000000..7c38652
--- /dev/null
+++ b/compose/material/material/src/jvmStubsMain/kotlin/androidx/compose/material/DefaultPlatformTextStyle.jvmStubs.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material
+
+import androidx.compose.ui.text.PlatformTextStyle
+
+internal actual fun defaultPlatformTextStyle(): PlatformTextStyle? = implementedInJetBrainsFork()
diff --git a/compose/material/material/src/jvmStubsMain/kotlin/androidx/compose/material/DesktopMenu.jvmStubs.kt b/compose/material/material/src/jvmStubsMain/kotlin/androidx/compose/material/DesktopMenu.jvmStubs.kt
new file mode 100644
index 0000000..2e0c188
--- /dev/null
+++ b/compose/material/material/src/jvmStubsMain/kotlin/androidx/compose/material/DesktopMenu.jvmStubs.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material
+
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.RowScope
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+
+@Composable
+actual fun DropdownMenuItem(
+    onClick: () -> Unit,
+    modifier: Modifier,
+    enabled: Boolean,
+    contentPadding: PaddingValues,
+    interactionSource: MutableInteractionSource?,
+    content: @Composable RowScope.() -> Unit
+): Unit = implementedInJetBrainsFork()
diff --git a/compose/material/material/src/jvmStubsMain/kotlin/androidx/compose/material/MaterialTheme.jvmStubs.kt b/compose/material/material/src/jvmStubsMain/kotlin/androidx/compose/material/MaterialTheme.jvmStubs.kt
new file mode 100644
index 0000000..6658f4f
--- /dev/null
+++ b/compose/material/material/src/jvmStubsMain/kotlin/androidx/compose/material/MaterialTheme.jvmStubs.kt
@@ -0,0 +1,23 @@
+/*
+ * 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.material
+
+import androidx.compose.runtime.Composable
+
+@Composable
+internal actual fun PlatformMaterialTheme(content: @Composable () -> Unit): Unit =
+    implementedInJetBrainsFork()
diff --git a/compose/material/material/src/jvmStubsMain/kotlin/androidx/compose/material/Menu.jvmStubs.kt b/compose/material/material/src/jvmStubsMain/kotlin/androidx/compose/material/Menu.jvmStubs.kt
new file mode 100644
index 0000000..4164d13
--- /dev/null
+++ b/compose/material/material/src/jvmStubsMain/kotlin/androidx/compose/material/Menu.jvmStubs.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material
+
+import androidx.compose.foundation.ScrollState
+import androidx.compose.foundation.layout.ColumnScope
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.DpOffset
+import androidx.compose.ui.window.PopupProperties
+
+@Composable
+actual fun DropdownMenu(
+    expanded: Boolean,
+    onDismissRequest: () -> Unit,
+    modifier: Modifier,
+    offset: DpOffset,
+    scrollState: ScrollState,
+    properties: PopupProperties,
+    content: @Composable ColumnScope.() -> Unit
+): Unit = implementedInJetBrainsFork()
+
+internal actual val DefaultMenuProperties: PopupProperties = implementedInJetBrainsFork()
diff --git a/compose/material/material/src/jvmStubsMain/kotlin/androidx/compose/material/NotImplemented.jvmStubs.kt b/compose/material/material/src/jvmStubsMain/kotlin/androidx/compose/material/NotImplemented.jvmStubs.kt
new file mode 100644
index 0000000..99338c7
--- /dev/null
+++ b/compose/material/material/src/jvmStubsMain/kotlin/androidx/compose/material/NotImplemented.jvmStubs.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material
+
+@Suppress("NOTHING_TO_INLINE")
+internal inline fun implementedInJetBrainsFork(): Nothing =
+    throw NotImplementedError(
+        """
+        Implemented only in JetBrains fork.
+        Please use `org.jetbrains.compose.material:material` package instead.
+        """
+            .trimIndent()
+    )
diff --git a/compose/material/material/src/jvmStubsMain/kotlin/androidx/compose/material/Strings.jvmStubs.kt b/compose/material/material/src/jvmStubsMain/kotlin/androidx/compose/material/Strings.jvmStubs.kt
new file mode 100644
index 0000000..f4f1b03
--- /dev/null
+++ b/compose/material/material/src/jvmStubsMain/kotlin/androidx/compose/material/Strings.jvmStubs.kt
@@ -0,0 +1,21 @@
+/*
+ * 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.material
+
+import androidx.compose.runtime.Composable
+
+@Composable internal actual fun getString(string: Strings): String = implementedInJetBrainsFork()
diff --git a/compose/material/material/src/jvmStubsMain/kotlin/androidx/compose/material/SystemBarsDefaultInsets.jvmStubs.kt b/compose/material/material/src/jvmStubsMain/kotlin/androidx/compose/material/SystemBarsDefaultInsets.jvmStubs.kt
new file mode 100644
index 0000000..c1cf866
--- /dev/null
+++ b/compose/material/material/src/jvmStubsMain/kotlin/androidx/compose/material/SystemBarsDefaultInsets.jvmStubs.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material
+
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.runtime.Composable
+
+internal actual val WindowInsets.Companion.systemBarsForVisualComponents: WindowInsets
+    @Composable get() = implementedInJetBrainsFork()
diff --git a/compose/material/material/src/skikoMain/kotlin/androidx/compose/material/AlertDialog.skiko.kt b/compose/material/material/src/skikoMain/kotlin/androidx/compose/material/AlertDialog.skiko.kt
deleted file mode 100644
index d5533bc..0000000
--- a/compose/material/material/src/skikoMain/kotlin/androidx/compose/material/AlertDialog.skiko.kt
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material
-
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.Shape
-import androidx.compose.ui.window.DialogProperties
-
-// Keep expect/actual for maintain binary compatibility.
-// `@file:JvmName` doesn't work here because Android and Desktop were published with different names
-// Please note that binary compatibility for Desktop is tracked only in JetBrains fork
-
-@Composable
-actual fun AlertDialog(
-    onDismissRequest: () -> Unit,
-    confirmButton: @Composable () -> Unit,
-    modifier: Modifier,
-    dismissButton: @Composable (() -> Unit)?,
-    title: @Composable (() -> Unit)?,
-    text: @Composable (() -> Unit)?,
-    shape: Shape,
-    backgroundColor: Color,
-    contentColor: Color,
-    properties: DialogProperties
-): Unit =
-    AlertDialogImpl(
-        onDismissRequest = onDismissRequest,
-        confirmButton = confirmButton,
-        modifier = modifier,
-        dismissButton = dismissButton,
-        title = title,
-        text = text,
-        shape = shape,
-        backgroundColor = backgroundColor,
-        contentColor = contentColor,
-        properties = properties
-    )
-
-@Composable
-actual fun AlertDialog(
-    onDismissRequest: () -> Unit,
-    buttons: @Composable () -> Unit,
-    modifier: Modifier,
-    title: (@Composable () -> Unit)?,
-    text: @Composable (() -> Unit)?,
-    shape: Shape,
-    backgroundColor: Color,
-    contentColor: Color,
-    properties: DialogProperties
-): Unit =
-    AlertDialogImpl(
-        onDismissRequest = onDismissRequest,
-        buttons = buttons,
-        modifier = modifier,
-        title = title,
-        text = text,
-        shape = shape,
-        backgroundColor = backgroundColor,
-        contentColor = contentColor,
-        properties = properties
-    )
diff --git a/compose/material/material/src/skikoMain/kotlin/androidx/compose/material/Menu.skiko.kt b/compose/material/material/src/skikoMain/kotlin/androidx/compose/material/Menu.skiko.kt
deleted file mode 100644
index 4649223..0000000
--- a/compose/material/material/src/skikoMain/kotlin/androidx/compose/material/Menu.skiko.kt
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material
-
-import androidx.compose.animation.core.MutableTransitionState
-import androidx.compose.foundation.ScrollState
-import androidx.compose.foundation.layout.ColumnScope
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.focus.FocusDirection
-import androidx.compose.ui.focus.FocusManager
-import androidx.compose.ui.graphics.TransformOrigin
-import androidx.compose.ui.input.InputMode
-import androidx.compose.ui.input.InputModeManager
-import androidx.compose.ui.input.key.Key
-import androidx.compose.ui.input.key.KeyEvent
-import androidx.compose.ui.input.key.KeyEventType
-import androidx.compose.ui.input.key.key
-import androidx.compose.ui.input.key.type
-import androidx.compose.ui.platform.LocalDensity
-import androidx.compose.ui.platform.LocalFocusManager
-import androidx.compose.ui.platform.LocalInputModeManager
-import androidx.compose.ui.unit.DpOffset
-import androidx.compose.ui.window.Popup
-import androidx.compose.ui.window.PopupProperties
-
-@Composable
-actual fun DropdownMenu(
-    expanded: Boolean,
-    onDismissRequest: () -> Unit,
-    modifier: Modifier,
-    offset: DpOffset,
-    scrollState: ScrollState,
-    properties: PopupProperties,
-    content: @Composable ColumnScope.() -> Unit
-) {
-    val expandedStates = remember { MutableTransitionState(false) }
-    expandedStates.targetState = expanded
-
-    if (expandedStates.currentState || expandedStates.targetState) {
-        val transformOriginState = remember { mutableStateOf(TransformOrigin.Center) }
-        val density = LocalDensity.current
-        val popupPositionProvider =
-            DropdownMenuPositionProvider(offset, density) { parentBounds, menuBounds ->
-                transformOriginState.value = calculateTransformOrigin(parentBounds, menuBounds)
-            }
-
-        var focusManager: FocusManager? by mutableStateOf(null)
-        var inputModeManager: InputModeManager? by mutableStateOf(null)
-        Popup(
-            onDismissRequest = onDismissRequest,
-            popupPositionProvider = popupPositionProvider,
-            properties = properties,
-            onKeyEvent = { handlePopupOnKeyEvent(it, focusManager, inputModeManager) },
-        ) {
-            focusManager = LocalFocusManager.current
-            inputModeManager = LocalInputModeManager.current
-            DropdownMenuContent(
-                expandedStates = expandedStates,
-                transformOriginState = transformOriginState,
-                scrollState = scrollState,
-                modifier = modifier,
-                content = content
-            )
-        }
-    }
-}
-
-internal actual val DefaultMenuProperties =
-    PopupProperties(
-        focusable = true
-        // TODO: Add a flag to not block clicks outside while being focusable
-    )
-
-internal fun handlePopupOnKeyEvent(
-    keyEvent: KeyEvent,
-    focusManager: FocusManager?,
-    inputModeManager: InputModeManager?
-): Boolean =
-    if (keyEvent.type == KeyEventType.KeyDown) {
-        when (keyEvent.key) {
-            Key.DirectionDown -> {
-                inputModeManager?.requestInputMode(InputMode.Keyboard)
-                focusManager?.moveFocus(FocusDirection.Next)
-                true
-            }
-            Key.DirectionUp -> {
-                inputModeManager?.requestInputMode(InputMode.Keyboard)
-                focusManager?.moveFocus(FocusDirection.Previous)
-                true
-            }
-            else -> false
-        }
-    } else {
-        false
-    }
diff --git a/compose/material3/adaptive/adaptive-layout/api/1.0.0-beta04.txt b/compose/material3/adaptive/adaptive-layout/api/1.0.0-beta04.txt
new file mode 100644
index 0000000..87f05eb
--- /dev/null
+++ b/compose/material3/adaptive/adaptive-layout/api/1.0.0-beta04.txt
@@ -0,0 +1,170 @@
+// Signature format: 4.0
+package androidx.compose.material3.adaptive.layout {
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Stable public sealed interface AdaptStrategy {
+    method public String adapt();
+    field public static final androidx.compose.material3.adaptive.layout.AdaptStrategy.Companion Companion;
+  }
+
+  public static final class AdaptStrategy.Companion {
+    method public androidx.compose.material3.adaptive.layout.AdaptStrategy getHide();
+    property public final androidx.compose.material3.adaptive.layout.AdaptStrategy Hide;
+  }
+
+  public sealed interface AnimatedPaneScope extends androidx.compose.animation.AnimatedVisibilityScope {
+  }
+
+  @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class HingePolicy {
+    field public static final androidx.compose.material3.adaptive.layout.HingePolicy.Companion Companion;
+  }
+
+  public static final class HingePolicy.Companion {
+    method public int getAlwaysAvoid();
+    method public int getAvoidOccluding();
+    method public int getAvoidSeparating();
+    method public int getNeverAvoid();
+    property public final int AlwaysAvoid;
+    property public final int AvoidOccluding;
+    property public final int AvoidSeparating;
+    property public final int NeverAvoid;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class ListDetailPaneScaffoldDefaults {
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies(optional androidx.compose.material3.adaptive.layout.AdaptStrategy detailPaneAdaptStrategy, optional androidx.compose.material3.adaptive.layout.AdaptStrategy listPaneAdaptStrategy, optional androidx.compose.material3.adaptive.layout.AdaptStrategy extraPaneAdaptStrategy);
+    field public static final androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldDefaults INSTANCE;
+  }
+
+  public final class ListDetailPaneScaffoldKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void ListDetailPaneScaffold(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective directive, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit> listPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit> detailPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit>? extraPane);
+  }
+
+  public final class ListDetailPaneScaffoldRole {
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getDetail();
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getExtra();
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getList();
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Detail;
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Extra;
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole List;
+    field public static final androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole INSTANCE;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @kotlin.jvm.JvmInline public final value class PaneAdaptedValue {
+    field public static final androidx.compose.material3.adaptive.layout.PaneAdaptedValue.Companion Companion;
+  }
+
+  public static final class PaneAdaptedValue.Companion {
+    method public String getExpanded();
+    method public String getHidden();
+    property public final String Expanded;
+    property public final String Hidden;
+  }
+
+  public final class PaneKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void AnimatedPane(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope, optional androidx.compose.ui.Modifier modifier, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.AnimatedPaneScope,kotlin.Unit> content);
+  }
+
+  @androidx.compose.runtime.Immutable public final class PaneScaffoldDirective {
+    ctor public PaneScaffoldDirective(int maxHorizontalPartitions, float horizontalPartitionSpacerSize, int maxVerticalPartitions, float verticalPartitionSpacerSize, float defaultPanePreferredWidth, java.util.List<androidx.compose.ui.geometry.Rect> excludedBounds);
+    method public androidx.compose.material3.adaptive.layout.PaneScaffoldDirective copy(optional int maxHorizontalPartitions, optional float horizontalPartitionSpacerSize, optional int maxVerticalPartitions, optional float verticalPartitionSpacerSize, optional float defaultPanePreferredWidth, optional java.util.List<androidx.compose.ui.geometry.Rect> excludedBounds);
+    method public float getDefaultPanePreferredWidth();
+    method public java.util.List<androidx.compose.ui.geometry.Rect> getExcludedBounds();
+    method public float getHorizontalPartitionSpacerSize();
+    method public int getMaxHorizontalPartitions();
+    method public int getMaxVerticalPartitions();
+    method public float getVerticalPartitionSpacerSize();
+    property public final float defaultPanePreferredWidth;
+    property public final java.util.List<androidx.compose.ui.geometry.Rect> excludedBounds;
+    property public final float horizontalPartitionSpacerSize;
+    property public final int maxHorizontalPartitions;
+    property public final int maxVerticalPartitions;
+    property public final float verticalPartitionSpacerSize;
+    field public static final androidx.compose.material3.adaptive.layout.PaneScaffoldDirective.Companion Companion;
+  }
+
+  public static final class PaneScaffoldDirective.Companion {
+    method public androidx.compose.material3.adaptive.layout.PaneScaffoldDirective getDefault();
+    property public final androidx.compose.material3.adaptive.layout.PaneScaffoldDirective Default;
+  }
+
+  public final class PaneScaffoldDirectiveKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.layout.PaneScaffoldDirective calculatePaneScaffoldDirective(androidx.compose.material3.adaptive.WindowAdaptiveInfo windowAdaptiveInfo, optional int verticalHingePolicy);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.layout.PaneScaffoldDirective calculatePaneScaffoldDirectiveWithTwoPanesOnMediumWidth(androidx.compose.material3.adaptive.WindowAdaptiveInfo windowAdaptiveInfo, optional int verticalHingePolicy);
+  }
+
+  public sealed interface PaneScaffoldScope {
+    method public androidx.compose.ui.Modifier preferredWidth(androidx.compose.ui.Modifier, float width);
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class SupportingPaneScaffoldDefaults {
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies(optional androidx.compose.material3.adaptive.layout.AdaptStrategy mainPaneAdaptStrategy, optional androidx.compose.material3.adaptive.layout.AdaptStrategy supportingPaneAdaptStrategy, optional androidx.compose.material3.adaptive.layout.AdaptStrategy extraPaneAdaptStrategy);
+    field public static final androidx.compose.material3.adaptive.layout.SupportingPaneScaffoldDefaults INSTANCE;
+  }
+
+  public final class SupportingPaneScaffoldKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void SupportingPaneScaffold(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective directive, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit> mainPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit> supportingPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit>? extraPane);
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class SupportingPaneScaffoldRole {
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getExtra();
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getMain();
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getSupporting();
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Extra;
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Main;
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Supporting;
+    field public static final androidx.compose.material3.adaptive.layout.SupportingPaneScaffoldRole INSTANCE;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class ThreePaneScaffoldAdaptStrategies {
+    ctor public ThreePaneScaffoldAdaptStrategies(androidx.compose.material3.adaptive.layout.AdaptStrategy primaryPaneAdaptStrategy, androidx.compose.material3.adaptive.layout.AdaptStrategy secondaryPaneAdaptStrategy, androidx.compose.material3.adaptive.layout.AdaptStrategy tertiaryPaneAdaptStrategy);
+    method public operator androidx.compose.material3.adaptive.layout.AdaptStrategy get(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole role);
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class ThreePaneScaffoldDestinationItem<T> {
+    ctor public ThreePaneScaffoldDestinationItem(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole pane, optional T? content);
+    method public T? getContent();
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getPane();
+    property public final T? content;
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole pane;
+  }
+
+  public enum ThreePaneScaffoldRole {
+    enum_constant public static final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Primary;
+    enum_constant public static final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Secondary;
+    enum_constant public static final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Tertiary;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public sealed interface ThreePaneScaffoldScope extends androidx.compose.material3.adaptive.layout.PaneScaffoldScope androidx.compose.ui.layout.LookaheadScope {
+    method public androidx.compose.animation.EnterTransition getEnterTransition();
+    method public androidx.compose.animation.ExitTransition getExitTransition();
+    method public androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> getPositionAnimationSpec();
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getRole();
+    method public androidx.compose.animation.core.Transition<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue> getScaffoldStateTransition();
+    method public float getScaffoldStateTransitionFraction();
+    method public androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntSize> getSizeAnimationSpec();
+    property public abstract androidx.compose.animation.EnterTransition enterTransition;
+    property public abstract androidx.compose.animation.ExitTransition exitTransition;
+    property public abstract androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> positionAnimationSpec;
+    property public abstract androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole role;
+    property public abstract androidx.compose.animation.core.Transition<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue> scaffoldStateTransition;
+    property public abstract float scaffoldStateTransitionFraction;
+    property public abstract androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntSize> sizeAnimationSpec;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Immutable public final class ThreePaneScaffoldValue {
+    ctor public ThreePaneScaffoldValue(String primary, String secondary, String tertiary);
+    method public operator String get(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole role);
+    method public String getPrimary();
+    method public String getSecondary();
+    method public String getTertiary();
+    property public final String primary;
+    property public final String secondary;
+    property public final String tertiary;
+  }
+
+  public final class ThreePaneScaffoldValueKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue calculateThreePaneScaffoldValue(int maxHorizontalPartitions, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<? extends java.lang.Object?>? currentDestination);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue calculateThreePaneScaffoldValue(int maxHorizontalPartitions, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies, java.util.List<? extends androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<? extends java.lang.Object?>> destinationHistory);
+  }
+
+}
+
diff --git a/compose/material3/adaptive/adaptive-layout/api/res-1.0.0-beta04.txt b/compose/material3/adaptive/adaptive-layout/api/res-1.0.0-beta04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compose/material3/adaptive/adaptive-layout/api/res-1.0.0-beta04.txt
diff --git a/compose/material3/adaptive/adaptive-layout/api/restricted_1.0.0-beta04.txt b/compose/material3/adaptive/adaptive-layout/api/restricted_1.0.0-beta04.txt
new file mode 100644
index 0000000..87f05eb
--- /dev/null
+++ b/compose/material3/adaptive/adaptive-layout/api/restricted_1.0.0-beta04.txt
@@ -0,0 +1,170 @@
+// Signature format: 4.0
+package androidx.compose.material3.adaptive.layout {
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Stable public sealed interface AdaptStrategy {
+    method public String adapt();
+    field public static final androidx.compose.material3.adaptive.layout.AdaptStrategy.Companion Companion;
+  }
+
+  public static final class AdaptStrategy.Companion {
+    method public androidx.compose.material3.adaptive.layout.AdaptStrategy getHide();
+    property public final androidx.compose.material3.adaptive.layout.AdaptStrategy Hide;
+  }
+
+  public sealed interface AnimatedPaneScope extends androidx.compose.animation.AnimatedVisibilityScope {
+  }
+
+  @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class HingePolicy {
+    field public static final androidx.compose.material3.adaptive.layout.HingePolicy.Companion Companion;
+  }
+
+  public static final class HingePolicy.Companion {
+    method public int getAlwaysAvoid();
+    method public int getAvoidOccluding();
+    method public int getAvoidSeparating();
+    method public int getNeverAvoid();
+    property public final int AlwaysAvoid;
+    property public final int AvoidOccluding;
+    property public final int AvoidSeparating;
+    property public final int NeverAvoid;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class ListDetailPaneScaffoldDefaults {
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies(optional androidx.compose.material3.adaptive.layout.AdaptStrategy detailPaneAdaptStrategy, optional androidx.compose.material3.adaptive.layout.AdaptStrategy listPaneAdaptStrategy, optional androidx.compose.material3.adaptive.layout.AdaptStrategy extraPaneAdaptStrategy);
+    field public static final androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldDefaults INSTANCE;
+  }
+
+  public final class ListDetailPaneScaffoldKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void ListDetailPaneScaffold(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective directive, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit> listPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit> detailPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit>? extraPane);
+  }
+
+  public final class ListDetailPaneScaffoldRole {
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getDetail();
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getExtra();
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getList();
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Detail;
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Extra;
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole List;
+    field public static final androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole INSTANCE;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @kotlin.jvm.JvmInline public final value class PaneAdaptedValue {
+    field public static final androidx.compose.material3.adaptive.layout.PaneAdaptedValue.Companion Companion;
+  }
+
+  public static final class PaneAdaptedValue.Companion {
+    method public String getExpanded();
+    method public String getHidden();
+    property public final String Expanded;
+    property public final String Hidden;
+  }
+
+  public final class PaneKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void AnimatedPane(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope, optional androidx.compose.ui.Modifier modifier, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.AnimatedPaneScope,kotlin.Unit> content);
+  }
+
+  @androidx.compose.runtime.Immutable public final class PaneScaffoldDirective {
+    ctor public PaneScaffoldDirective(int maxHorizontalPartitions, float horizontalPartitionSpacerSize, int maxVerticalPartitions, float verticalPartitionSpacerSize, float defaultPanePreferredWidth, java.util.List<androidx.compose.ui.geometry.Rect> excludedBounds);
+    method public androidx.compose.material3.adaptive.layout.PaneScaffoldDirective copy(optional int maxHorizontalPartitions, optional float horizontalPartitionSpacerSize, optional int maxVerticalPartitions, optional float verticalPartitionSpacerSize, optional float defaultPanePreferredWidth, optional java.util.List<androidx.compose.ui.geometry.Rect> excludedBounds);
+    method public float getDefaultPanePreferredWidth();
+    method public java.util.List<androidx.compose.ui.geometry.Rect> getExcludedBounds();
+    method public float getHorizontalPartitionSpacerSize();
+    method public int getMaxHorizontalPartitions();
+    method public int getMaxVerticalPartitions();
+    method public float getVerticalPartitionSpacerSize();
+    property public final float defaultPanePreferredWidth;
+    property public final java.util.List<androidx.compose.ui.geometry.Rect> excludedBounds;
+    property public final float horizontalPartitionSpacerSize;
+    property public final int maxHorizontalPartitions;
+    property public final int maxVerticalPartitions;
+    property public final float verticalPartitionSpacerSize;
+    field public static final androidx.compose.material3.adaptive.layout.PaneScaffoldDirective.Companion Companion;
+  }
+
+  public static final class PaneScaffoldDirective.Companion {
+    method public androidx.compose.material3.adaptive.layout.PaneScaffoldDirective getDefault();
+    property public final androidx.compose.material3.adaptive.layout.PaneScaffoldDirective Default;
+  }
+
+  public final class PaneScaffoldDirectiveKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.layout.PaneScaffoldDirective calculatePaneScaffoldDirective(androidx.compose.material3.adaptive.WindowAdaptiveInfo windowAdaptiveInfo, optional int verticalHingePolicy);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.layout.PaneScaffoldDirective calculatePaneScaffoldDirectiveWithTwoPanesOnMediumWidth(androidx.compose.material3.adaptive.WindowAdaptiveInfo windowAdaptiveInfo, optional int verticalHingePolicy);
+  }
+
+  public sealed interface PaneScaffoldScope {
+    method public androidx.compose.ui.Modifier preferredWidth(androidx.compose.ui.Modifier, float width);
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class SupportingPaneScaffoldDefaults {
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies(optional androidx.compose.material3.adaptive.layout.AdaptStrategy mainPaneAdaptStrategy, optional androidx.compose.material3.adaptive.layout.AdaptStrategy supportingPaneAdaptStrategy, optional androidx.compose.material3.adaptive.layout.AdaptStrategy extraPaneAdaptStrategy);
+    field public static final androidx.compose.material3.adaptive.layout.SupportingPaneScaffoldDefaults INSTANCE;
+  }
+
+  public final class SupportingPaneScaffoldKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void SupportingPaneScaffold(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective directive, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit> mainPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit> supportingPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit>? extraPane);
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class SupportingPaneScaffoldRole {
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getExtra();
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getMain();
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getSupporting();
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Extra;
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Main;
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Supporting;
+    field public static final androidx.compose.material3.adaptive.layout.SupportingPaneScaffoldRole INSTANCE;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class ThreePaneScaffoldAdaptStrategies {
+    ctor public ThreePaneScaffoldAdaptStrategies(androidx.compose.material3.adaptive.layout.AdaptStrategy primaryPaneAdaptStrategy, androidx.compose.material3.adaptive.layout.AdaptStrategy secondaryPaneAdaptStrategy, androidx.compose.material3.adaptive.layout.AdaptStrategy tertiaryPaneAdaptStrategy);
+    method public operator androidx.compose.material3.adaptive.layout.AdaptStrategy get(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole role);
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class ThreePaneScaffoldDestinationItem<T> {
+    ctor public ThreePaneScaffoldDestinationItem(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole pane, optional T? content);
+    method public T? getContent();
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getPane();
+    property public final T? content;
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole pane;
+  }
+
+  public enum ThreePaneScaffoldRole {
+    enum_constant public static final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Primary;
+    enum_constant public static final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Secondary;
+    enum_constant public static final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Tertiary;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public sealed interface ThreePaneScaffoldScope extends androidx.compose.material3.adaptive.layout.PaneScaffoldScope androidx.compose.ui.layout.LookaheadScope {
+    method public androidx.compose.animation.EnterTransition getEnterTransition();
+    method public androidx.compose.animation.ExitTransition getExitTransition();
+    method public androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> getPositionAnimationSpec();
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getRole();
+    method public androidx.compose.animation.core.Transition<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue> getScaffoldStateTransition();
+    method public float getScaffoldStateTransitionFraction();
+    method public androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntSize> getSizeAnimationSpec();
+    property public abstract androidx.compose.animation.EnterTransition enterTransition;
+    property public abstract androidx.compose.animation.ExitTransition exitTransition;
+    property public abstract androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset> positionAnimationSpec;
+    property public abstract androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole role;
+    property public abstract androidx.compose.animation.core.Transition<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue> scaffoldStateTransition;
+    property public abstract float scaffoldStateTransitionFraction;
+    property public abstract androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntSize> sizeAnimationSpec;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Immutable public final class ThreePaneScaffoldValue {
+    ctor public ThreePaneScaffoldValue(String primary, String secondary, String tertiary);
+    method public operator String get(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole role);
+    method public String getPrimary();
+    method public String getSecondary();
+    method public String getTertiary();
+    property public final String primary;
+    property public final String secondary;
+    property public final String tertiary;
+  }
+
+  public final class ThreePaneScaffoldValueKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue calculateThreePaneScaffoldValue(int maxHorizontalPartitions, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<? extends java.lang.Object?>? currentDestination);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue calculateThreePaneScaffoldValue(int maxHorizontalPartitions, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies, java.util.List<? extends androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<? extends java.lang.Object?>> destinationHistory);
+  }
+
+}
+
diff --git a/compose/material3/adaptive/adaptive-layout/build.gradle b/compose/material3/adaptive/adaptive-layout/build.gradle
index ffcb419..987896ee 100644
--- a/compose/material3/adaptive/adaptive-layout/build.gradle
+++ b/compose/material3/adaptive/adaptive-layout/build.gradle
@@ -33,23 +33,23 @@
 
 androidXMultiplatform {
     android()
-    desktop()
+    jvmStubs()
 
     defaultPlatform(PlatformIdentifier.ANDROID)
 
     sourceSets {
         commonMain {
             dependencies {
-                implementation(libs.kotlinStdlibCommon)
+                implementation(libs.kotlinStdlib)
                 api(project(":compose:material3:adaptive:adaptive"))
-                api("androidx.compose.animation:animation-core:1.7.0-beta02")
-                api("androidx.compose.ui:ui:1.7.0-beta02")
-                implementation("androidx.compose.animation:animation:1.7.0-beta02")
+                api("androidx.compose.animation:animation-core:1.7.0-beta04")
+                api("androidx.compose.ui:ui:1.7.0-beta04")
+                implementation("androidx.compose.animation:animation:1.7.0-beta04")
                 implementation("androidx.compose.foundation:foundation:1.6.5")
                 implementation("androidx.compose.foundation:foundation-layout:1.6.5")
                 implementation("androidx.compose.ui:ui-geometry:1.6.5")
                 implementation("androidx.compose.ui:ui-util:1.6.5")
-                implementation("androidx.window:window-core:1.3.0-beta02")
+                implementation("androidx.window:window-core:1.3.0-rc01")
             }
         }
 
@@ -61,7 +61,6 @@
         jvmMain {
             dependsOn(commonMain)
             dependencies {
-                implementation(libs.kotlinStdlib)
             }
         }
 
@@ -73,24 +72,14 @@
             }
         }
 
-        desktopMain {
+        jvmStubsMain {
             dependsOn(jvmMain)
             dependencies {
             }
         }
 
-        jvmTest {
-            dependsOn(commonTest)
-            dependencies {
-            }
-        }
-
-        desktopTest {
-            dependsOn(jvmTest)
-        }
-
         androidInstrumentedTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(project(":compose:material3:material3"))
                 implementation(project(":compose:test-utils"))
@@ -102,7 +91,7 @@
         }
 
         androidUnitTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(libs.junit)
                 implementation(libs.testRunner)
diff --git a/compose/material3/adaptive/adaptive-layout/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/layout/PaneMotionTest.kt b/compose/material3/adaptive/adaptive-layout/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/layout/PaneMotionTest.kt
index 1c455bf..35d588d 100644
--- a/compose/material3/adaptive/adaptive-layout/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/layout/PaneMotionTest.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/layout/PaneMotionTest.kt
@@ -40,13 +40,9 @@
 import androidx.compose.material3.adaptive.layout.PaneAdaptedValue.Companion.Expanded
 import androidx.compose.material3.adaptive.layout.PaneAdaptedValue.Companion.Hidden
 import androidx.compose.ui.Alignment
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.geometry.Rect
-import androidx.compose.ui.layout.AlignmentLine
-import androidx.compose.ui.layout.LayoutCoordinates
-import androidx.compose.ui.layout.Placeable
 import androidx.compose.ui.unit.IntOffset
 import androidx.compose.ui.unit.IntSize
+import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -93,12 +89,104 @@
     ) {
         // Can't compare equality directly because of lambda. Check string representation instead
         assertWithMessage("Enter transition of $this: ")
-            .that(mockPaneMotionScope.enterTransition.toString())
+            .that(mockPaneScaffoldMotionScope.enterTransition.toString())
             .isEqualTo(expectedEnterTransition.toString())
         assertWithMessage("Exit transition of $this: ")
-            .that(mockPaneMotionScope.exitTransition.toString())
+            .that(mockPaneScaffoldMotionScope.exitTransition.toString())
             .isEqualTo(expectedExitTransition.toString())
     }
+
+    @Test
+    fun slideInFromLeftOffset_noEnterFromLeftPane_equalsZero() {
+        mockPaneScaffoldMotionScope.paneMotions =
+            listOf(EnterFromRight, EnterFromRight, EnterFromRight)
+        assertThat(mockPaneScaffoldMotionScope.slideInFromLeftOffset).isEqualTo(0)
+    }
+
+    @Test
+    fun slideInFromLeftOffset_withEnterFromLeftPane_useTheRightestEdge() {
+        mockPaneScaffoldMotionScope.paneMotions =
+            listOf(EnterFromLeft, EnterFromLeft, EnterFromRight)
+        assertThat(mockPaneScaffoldMotionScope.slideInFromLeftOffset)
+            .isEqualTo(
+                -mockPaneScaffoldMotionScope.targetPanePositions[1].x -
+                    mockPaneScaffoldMotionScope.targetPaneSizes[1].width
+            )
+    }
+
+    @Test
+    fun slideInFromLeftOffset_withEnterFromLeftDelayedPane_useTheRightestEdge() {
+        mockPaneScaffoldMotionScope.paneMotions =
+            listOf(EnterFromLeft, EnterFromLeftDelayed, EnterFromRight)
+        assertThat(mockPaneScaffoldMotionScope.slideInFromLeftOffset)
+            .isEqualTo(
+                -mockPaneScaffoldMotionScope.targetPanePositions[1].x -
+                    mockPaneScaffoldMotionScope.targetPaneSizes[1].width
+            )
+    }
+
+    @Test
+    fun slideInFromRightOffset_noEnterFromRightPane_equalsZero() {
+        mockPaneScaffoldMotionScope.paneMotions =
+            listOf(EnterFromLeft, EnterFromLeft, EnterFromLeft)
+        assertThat(mockPaneScaffoldMotionScope.slideInFromRightOffset).isEqualTo(0)
+    }
+
+    @Test
+    fun slideInFromRightOffset_withEnterFromRightPane_useTheLeftestEdge() {
+        mockPaneScaffoldMotionScope.paneMotions =
+            listOf(EnterFromLeft, EnterFromRight, EnterFromRight)
+        assertThat(mockPaneScaffoldMotionScope.slideInFromRightOffset)
+            .isEqualTo(
+                mockPaneScaffoldMotionScope.scaffoldSize.width -
+                    mockPaneScaffoldMotionScope.targetPanePositions[1].x
+            )
+    }
+
+    @Test
+    fun slideInFromRightOffset_withEnterFromRightDelayedPane_useTheLeftestEdge() {
+        mockPaneScaffoldMotionScope.paneMotions =
+            listOf(EnterFromLeft, EnterFromRightDelayed, EnterFromRight)
+        assertThat(mockPaneScaffoldMotionScope.slideInFromRightOffset)
+            .isEqualTo(
+                mockPaneScaffoldMotionScope.scaffoldSize.width -
+                    mockPaneScaffoldMotionScope.targetPanePositions[1].x
+            )
+    }
+
+    @Test
+    fun slideOutToLeftOffset_noExitToLeftPane_equalsZero() {
+        mockPaneScaffoldMotionScope.paneMotions =
+            listOf(EnterFromRight, EnterFromRight, EnterFromRight)
+        assertThat(mockPaneScaffoldMotionScope.slideOutToLeftOffset).isEqualTo(0)
+    }
+
+    @Test
+    fun slideOutToLeftOffset_withExitToLeftPane_useTheRightestEdge() {
+        mockPaneScaffoldMotionScope.paneMotions = listOf(ExitToLeft, ExitToLeft, ExitToRight)
+        assertThat(mockPaneScaffoldMotionScope.slideOutToLeftOffset)
+            .isEqualTo(
+                -mockPaneScaffoldMotionScope.currentPanePositions[1].x -
+                    mockPaneScaffoldMotionScope.currentPaneSizes[1].width
+            )
+    }
+
+    @Test
+    fun slideOutToRightOffset_noExitToRightPane_equalsZero() {
+        mockPaneScaffoldMotionScope.paneMotions =
+            listOf(EnterFromRight, EnterFromRight, EnterFromRight)
+        assertThat(mockPaneScaffoldMotionScope.slideOutToRightOffset).isEqualTo(0)
+    }
+
+    @Test
+    fun slideOutToRightOffset_withExitToRightPane_useTheLeftestEdge() {
+        mockPaneScaffoldMotionScope.paneMotions = listOf(ExitToLeft, ExitToRight, ExitToRight)
+        assertThat(mockPaneScaffoldMotionScope.slideOutToRightOffset)
+            .isEqualTo(
+                mockPaneScaffoldMotionScope.scaffoldSize.width -
+                    mockPaneScaffoldMotionScope.currentPanePositions[1].x
+            )
+    }
 }
 
 @OptIn(ExperimentalMaterial3AdaptiveApi::class)
@@ -126,174 +214,156 @@
 
 @OptIn(ExperimentalMaterial3AdaptiveApi::class)
 private val ExpectedThreePaneMotions =
-    arrayOf(
+    listOf(
         // From H, H, H
-        arrayOf(
-            arrayOf(NoMotion, NoMotion, NoMotion), // To H, H, H
-            arrayOf(EnterFromRight, NoMotion, NoMotion), // To V, H, H
-            arrayOf(NoMotion, EnterFromRight, NoMotion), // To H, V, H
-            arrayOf(NoMotion, NoMotion, EnterFromRight), // To H, H, V
-            arrayOf(EnterFromRight, EnterFromRight, NoMotion), // To V, V, H
-            arrayOf(EnterFromRight, NoMotion, EnterFromRight), // To V, H, V
-            arrayOf(NoMotion, EnterFromRight, EnterFromRight), // To H, V, V
-            arrayOf(EnterFromRight, EnterFromRight, EnterFromRight), // To V, V, V
+        listOf(
+            listOf(NoMotion, NoMotion, NoMotion), // To H, H, H
+            listOf(EnterFromRight, NoMotion, NoMotion), // To V, H, H
+            listOf(NoMotion, EnterFromRight, NoMotion), // To H, V, H
+            listOf(NoMotion, NoMotion, EnterFromRight), // To H, H, V
+            listOf(EnterFromRight, EnterFromRight, NoMotion), // To V, V, H
+            listOf(EnterFromRight, NoMotion, EnterFromRight), // To V, H, V
+            listOf(NoMotion, EnterFromRight, EnterFromRight), // To H, V, V
+            listOf(EnterFromRight, EnterFromRight, EnterFromRight), // To V, V, V
         ),
         // From V, H, H
-        arrayOf(
-            arrayOf(ExitToRight, NoMotion, NoMotion), // To H, H, H
-            arrayOf(AnimateBounds, NoMotion, NoMotion), // To V, H, H
-            arrayOf(ExitToLeft, EnterFromRight, NoMotion), // To H, V, H
-            arrayOf(ExitToLeft, NoMotion, EnterFromRight), // To H, H, V
-            arrayOf(AnimateBounds, EnterFromRight, NoMotion), // To V, V, H
-            arrayOf(AnimateBounds, NoMotion, EnterFromRight), // To V, H, V
-            arrayOf(ExitToLeft, EnterFromRight, EnterFromRight), // To H, V, V
-            arrayOf(AnimateBounds, EnterFromRight, EnterFromRight), // To V, V, V
+        listOf(
+            listOf(ExitToRight, NoMotion, NoMotion), // To H, H, H
+            listOf(AnimateBounds, NoMotion, NoMotion), // To V, H, H
+            listOf(ExitToLeft, EnterFromRight, NoMotion), // To H, V, H
+            listOf(ExitToLeft, NoMotion, EnterFromRight), // To H, H, V
+            listOf(AnimateBounds, EnterFromRight, NoMotion), // To V, V, H
+            listOf(AnimateBounds, NoMotion, EnterFromRight), // To V, H, V
+            listOf(ExitToLeft, EnterFromRight, EnterFromRight), // To H, V, V
+            listOf(AnimateBounds, EnterFromRight, EnterFromRight), // To V, V, V
         ),
         // From H, V, H
-        arrayOf(
-            arrayOf(NoMotion, ExitToRight, NoMotion), // To H, H, H
-            arrayOf(EnterFromLeft, ExitToRight, NoMotion), // To V, H, H
-            arrayOf(NoMotion, AnimateBounds, NoMotion), // To H, V, H
-            arrayOf(NoMotion, ExitToLeft, EnterFromRight), // To H, H, V
-            arrayOf(EnterFromLeft, AnimateBounds, NoMotion), // To V, V, H
-            arrayOf(EnterFromLeft, ExitToRight, EnterFromRightDelayed), // To V, H, V
-            arrayOf(NoMotion, AnimateBounds, EnterFromRight), // To H, V, V
-            arrayOf(EnterFromLeft, AnimateBounds, EnterFromRight), // To V, V, V
+        listOf(
+            listOf(NoMotion, ExitToRight, NoMotion), // To H, H, H
+            listOf(EnterFromLeft, ExitToRight, NoMotion), // To V, H, H
+            listOf(NoMotion, AnimateBounds, NoMotion), // To H, V, H
+            listOf(NoMotion, ExitToLeft, EnterFromRight), // To H, H, V
+            listOf(EnterFromLeft, AnimateBounds, NoMotion), // To V, V, H
+            listOf(EnterFromLeft, ExitToRight, EnterFromRightDelayed), // To V, H, V
+            listOf(NoMotion, AnimateBounds, EnterFromRight), // To H, V, V
+            listOf(EnterFromLeft, AnimateBounds, EnterFromRight), // To V, V, V
         ),
         // From H, H, V
-        arrayOf(
-            arrayOf(NoMotion, NoMotion, ExitToRight), // To H, H, H
-            arrayOf(EnterFromLeft, NoMotion, ExitToRight), // To V, H, H
-            arrayOf(NoMotion, EnterFromLeft, ExitToRight), // To H, V, H
-            arrayOf(NoMotion, NoMotion, AnimateBounds), // To H, H, V
-            arrayOf(EnterFromLeft, EnterFromLeft, ExitToRight), // To V, V, H
-            arrayOf(EnterFromLeft, NoMotion, AnimateBounds), // To V, H, V
-            arrayOf(NoMotion, EnterFromLeft, AnimateBounds), // To H, V, V
-            arrayOf(EnterFromLeft, EnterFromLeft, AnimateBounds), // To V, V, V
+        listOf(
+            listOf(NoMotion, NoMotion, ExitToRight), // To H, H, H
+            listOf(EnterFromLeft, NoMotion, ExitToRight), // To V, H, H
+            listOf(NoMotion, EnterFromLeft, ExitToRight), // To H, V, H
+            listOf(NoMotion, NoMotion, AnimateBounds), // To H, H, V
+            listOf(EnterFromLeft, EnterFromLeft, ExitToRight), // To V, V, H
+            listOf(EnterFromLeft, NoMotion, AnimateBounds), // To V, H, V
+            listOf(NoMotion, EnterFromLeft, AnimateBounds), // To H, V, V
+            listOf(EnterFromLeft, EnterFromLeft, AnimateBounds), // To V, V, V
         ),
         // From V, V, H
-        arrayOf(
-            arrayOf(ExitToRight, ExitToRight, NoMotion), // To H, H, H
-            arrayOf(AnimateBounds, ExitToRight, NoMotion), // To V, H, H
-            arrayOf(ExitToLeft, AnimateBounds, NoMotion), // To H, V, H
-            arrayOf(ExitToLeft, ExitToLeft, EnterFromRight), // To H, H, V
-            arrayOf(AnimateBounds, AnimateBounds, NoMotion), // To V, V, H
-            arrayOf(AnimateBounds, ExitToRight, EnterFromRightDelayed), // To V, H, V
-            arrayOf(ExitToLeft, AnimateBounds, EnterFromRight), // To H, V, V
-            arrayOf(AnimateBounds, AnimateBounds, EnterFromRight), // To V, V, V
+        listOf(
+            listOf(ExitToRight, ExitToRight, NoMotion), // To H, H, H
+            listOf(AnimateBounds, ExitToRight, NoMotion), // To V, H, H
+            listOf(ExitToLeft, AnimateBounds, NoMotion), // To H, V, H
+            listOf(ExitToLeft, ExitToLeft, EnterFromRight), // To H, H, V
+            listOf(AnimateBounds, AnimateBounds, NoMotion), // To V, V, H
+            listOf(AnimateBounds, ExitToRight, EnterFromRightDelayed), // To V, H, V
+            listOf(ExitToLeft, AnimateBounds, EnterFromRight), // To H, V, V
+            listOf(AnimateBounds, AnimateBounds, EnterFromRight), // To V, V, V
         ),
         // From V, H, V
-        arrayOf(
-            arrayOf(ExitToRight, NoMotion, ExitToRight), // To H, H, H
-            arrayOf(AnimateBounds, NoMotion, ExitToRight), // To V, H, H
-            arrayOf(ExitToLeft, EnterFromRightDelayed, ExitToRight), // To H, V, H
-            arrayOf(ExitToLeft, NoMotion, AnimateBounds), // To H, H, V
-            arrayOf(AnimateBounds, EnterFromRightDelayed, ExitToRight), // To V, V, H
-            arrayOf(AnimateBounds, NoMotion, AnimateBounds), // To V, H, V
-            arrayOf(ExitToLeft, EnterFromLeftDelayed, AnimateBounds), // To H, V, V
-            arrayOf(AnimateBounds, EnterWithExpand, AnimateBounds), // To V, V, V
+        listOf(
+            listOf(ExitToRight, NoMotion, ExitToRight), // To H, H, H
+            listOf(AnimateBounds, NoMotion, ExitToRight), // To V, H, H
+            listOf(ExitToLeft, EnterFromRightDelayed, ExitToRight), // To H, V, H
+            listOf(ExitToLeft, NoMotion, AnimateBounds), // To H, H, V
+            listOf(AnimateBounds, EnterFromRightDelayed, ExitToRight), // To V, V, H
+            listOf(AnimateBounds, NoMotion, AnimateBounds), // To V, H, V
+            listOf(ExitToLeft, EnterFromLeftDelayed, AnimateBounds), // To H, V, V
+            listOf(AnimateBounds, EnterWithExpand, AnimateBounds), // To V, V, V
         ),
         // From H, V, V
-        arrayOf(
-            arrayOf(NoMotion, ExitToRight, ExitToRight), // To H, H, H
-            arrayOf(EnterFromLeft, ExitToRight, ExitToRight), // To V, H, H
-            arrayOf(NoMotion, AnimateBounds, ExitToRight), // To H, V, H
-            arrayOf(NoMotion, ExitToLeft, AnimateBounds), // To H, H, V
-            arrayOf(EnterFromLeft, AnimateBounds, ExitToRight), // To V, V, H
-            arrayOf(EnterFromLeftDelayed, ExitToLeft, AnimateBounds), // To V, H, V
-            arrayOf(NoMotion, AnimateBounds, AnimateBounds), // To H, V, V
-            arrayOf(EnterFromLeft, AnimateBounds, AnimateBounds), // To V, V, V
+        listOf(
+            listOf(NoMotion, ExitToRight, ExitToRight), // To H, H, H
+            listOf(EnterFromLeft, ExitToRight, ExitToRight), // To V, H, H
+            listOf(NoMotion, AnimateBounds, ExitToRight), // To H, V, H
+            listOf(NoMotion, ExitToLeft, AnimateBounds), // To H, H, V
+            listOf(EnterFromLeft, AnimateBounds, ExitToRight), // To V, V, H
+            listOf(EnterFromLeftDelayed, ExitToLeft, AnimateBounds), // To V, H, V
+            listOf(NoMotion, AnimateBounds, AnimateBounds), // To H, V, V
+            listOf(EnterFromLeft, AnimateBounds, AnimateBounds), // To V, V, V
         ),
         // From V, V, V
-        arrayOf(
-            arrayOf(ExitToRight, ExitToRight, ExitToRight), // To H, H, H
-            arrayOf(AnimateBounds, ExitToRight, ExitToRight), // To V, H, H
-            arrayOf(ExitToLeft, AnimateBounds, ExitToRight), // To H, V, H
-            arrayOf(ExitToLeft, ExitToLeft, AnimateBounds), // To H, H, V
-            arrayOf(AnimateBounds, AnimateBounds, ExitToRight), // To V, V, H
-            arrayOf(AnimateBounds, ExitWithShrink, AnimateBounds), // To V, H, V
-            arrayOf(ExitToLeft, AnimateBounds, AnimateBounds), // To H, V, V
-            arrayOf(AnimateBounds, AnimateBounds, AnimateBounds), // To V, V, V
+        listOf(
+            listOf(ExitToRight, ExitToRight, ExitToRight), // To H, H, H
+            listOf(AnimateBounds, ExitToRight, ExitToRight), // To V, H, H
+            listOf(ExitToLeft, AnimateBounds, ExitToRight), // To H, V, H
+            listOf(ExitToLeft, ExitToLeft, AnimateBounds), // To H, H, V
+            listOf(AnimateBounds, AnimateBounds, ExitToRight), // To V, V, H
+            listOf(AnimateBounds, ExitWithShrink, AnimateBounds), // To V, H, V
+            listOf(ExitToLeft, AnimateBounds, AnimateBounds), // To H, V, V
+            listOf(AnimateBounds, AnimateBounds, AnimateBounds), // To V, V, V
         ),
     )
 
+@Suppress("PrimitiveInCollection") // No way to get underlying Long of IntSize or IntOffset
 @OptIn(ExperimentalMaterial3AdaptiveApi::class)
-private val mockPaneMotionScope =
-    object : PaneMotionScope {
+private val mockPaneScaffoldMotionScope =
+    object : PaneScaffoldMotionScope {
         override val positionAnimationSpec: FiniteAnimationSpec<IntOffset> = tween()
         override val sizeAnimationSpec: FiniteAnimationSpec<IntSize> = spring()
         override val delayedPositionAnimationSpec: FiniteAnimationSpec<IntOffset> = snap()
-        override val slideInFromLeftOffset: Int = 1
-        override val slideInFromRightOffset: Int = 2
-        override val slideOutToLeftOffset: Int = 3
-        override val slideOutToRightOffset: Int = 4
-        override val motionProgress: () -> Float = { 0.5F }
-        override val Placeable.PlacementScope.lookaheadScopeCoordinates: LayoutCoordinates
-            get() = mockLayoutCoordinates
-
-        override fun LayoutCoordinates.toLookaheadCoordinates(): LayoutCoordinates =
-            mockLayoutCoordinates
-
-        val mockLayoutCoordinates =
-            object : LayoutCoordinates {
-                override val isAttached: Boolean = false
-                override val parentCoordinates: LayoutCoordinates? = null
-                override val parentLayoutCoordinates: LayoutCoordinates? = null
-                override val providedAlignmentLines: Set<AlignmentLine> = emptySet()
-                override val size: IntSize = IntSize.Zero
-
-                override fun get(alignmentLine: AlignmentLine): Int = 0
-
-                override fun localBoundingBoxOf(
-                    sourceCoordinates: LayoutCoordinates,
-                    clipBounds: Boolean
-                ): Rect = Rect.Zero
-
-                override fun localPositionOf(
-                    sourceCoordinates: LayoutCoordinates,
-                    relativeToSource: Offset
-                ): Offset = Offset.Zero
-
-                override fun localToRoot(relativeToLocal: Offset): Offset = Offset.Zero
-
-                override fun localToWindow(relativeToLocal: Offset): Offset = Offset.Zero
-
-                override fun windowToLocal(relativeToWindow: Offset): Offset = Offset.Zero
-            }
+        override val scaffoldSize: IntSize = IntSize(1000, 1000)
+        override var currentPaneSizes: List<IntSize> =
+            listOf(IntSize(1, 2), IntSize(3, 4), IntSize(5, 6))
+        override var currentPanePositions: List<IntOffset> =
+            listOf(IntOffset(3, 4), IntOffset(5, 6), IntOffset(7, 8))
+        override var targetPaneSizes: List<IntSize> =
+            listOf(IntSize(3, 4), IntSize(5, 6), IntSize(7, 8))
+        override var targetPanePositions: List<IntOffset> =
+            listOf(IntOffset(5, 6), IntOffset(7, 8), IntOffset(9, 0))
+        override var paneMotions: List<PaneMotion> =
+            listOf(ExitToLeft, EnterFromRight, EnterFromRight)
+        override val motionProgress = 0.5F
     }
 
+@OptIn(ExperimentalMaterial3AdaptiveApi::class)
 private val mockEnterFromLeftTransition =
-    slideInHorizontally(mockPaneMotionScope.positionAnimationSpec) {
-        mockPaneMotionScope.slideInFromLeftOffset
+    slideInHorizontally(mockPaneScaffoldMotionScope.positionAnimationSpec) {
+        mockPaneScaffoldMotionScope.slideInFromLeftOffset
     }
 
+@OptIn(ExperimentalMaterial3AdaptiveApi::class)
 private val mockEnterFromRightTransition =
-    slideInHorizontally(mockPaneMotionScope.positionAnimationSpec) {
-        mockPaneMotionScope.slideInFromRightOffset
+    slideInHorizontally(mockPaneScaffoldMotionScope.positionAnimationSpec) {
+        mockPaneScaffoldMotionScope.slideInFromRightOffset
     }
 
+@OptIn(ExperimentalMaterial3AdaptiveApi::class)
 private val mockEnterFromLeftDelayedTransition =
-    slideInHorizontally(mockPaneMotionScope.delayedPositionAnimationSpec) {
-        mockPaneMotionScope.slideInFromLeftOffset
+    slideInHorizontally(mockPaneScaffoldMotionScope.delayedPositionAnimationSpec) {
+        mockPaneScaffoldMotionScope.slideInFromLeftOffset
     }
 
+@OptIn(ExperimentalMaterial3AdaptiveApi::class)
 private val mockEnterFromRightDelayedTransition =
-    slideInHorizontally(mockPaneMotionScope.delayedPositionAnimationSpec) {
-        mockPaneMotionScope.slideInFromLeftOffset
+    slideInHorizontally(mockPaneScaffoldMotionScope.delayedPositionAnimationSpec) {
+        mockPaneScaffoldMotionScope.slideInFromLeftOffset
     }
 
+@OptIn(ExperimentalMaterial3AdaptiveApi::class)
 private val mockExitToLeftTransition =
-    slideOutHorizontally(mockPaneMotionScope.positionAnimationSpec) {
-        mockPaneMotionScope.slideOutToLeftOffset
+    slideOutHorizontally(mockPaneScaffoldMotionScope.positionAnimationSpec) {
+        mockPaneScaffoldMotionScope.slideOutToLeftOffset
     }
 
+@OptIn(ExperimentalMaterial3AdaptiveApi::class)
 private val mockExitToRightTransition =
-    slideOutHorizontally(mockPaneMotionScope.positionAnimationSpec) {
-        mockPaneMotionScope.slideOutToRightOffset
+    slideOutHorizontally(mockPaneScaffoldMotionScope.positionAnimationSpec) {
+        mockPaneScaffoldMotionScope.slideOutToRightOffset
     }
 
 private val mockEnterWithExpandTransition =
-    expandHorizontally(mockPaneMotionScope.sizeAnimationSpec, Alignment.CenterHorizontally)
+    expandHorizontally(mockPaneScaffoldMotionScope.sizeAnimationSpec, Alignment.CenterHorizontally)
 
 private val mockExitWithShrinkTransition =
-    shrinkHorizontally(mockPaneMotionScope.sizeAnimationSpec, Alignment.CenterHorizontally)
+    shrinkHorizontally(mockPaneScaffoldMotionScope.sizeAnimationSpec, Alignment.CenterHorizontally)
diff --git a/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneMotion.kt b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneMotion.kt
index e151d69..597862e 100644
--- a/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneMotion.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneMotion.kt
@@ -26,30 +26,85 @@
 import androidx.compose.animation.slideOutHorizontally
 import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
 import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.layout.LookaheadScope
 import androidx.compose.ui.unit.IntOffset
 import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.util.fastForEachIndexed
 import kotlin.math.max
 import kotlin.math.min
 
+@Suppress("PrimitiveInCollection") // No way to get underlying Long of IntSize or IntOffset
 @ExperimentalMaterial3AdaptiveApi
-internal interface PaneMotionScope : LookaheadScope {
+internal interface PaneScaffoldMotionScope {
     val positionAnimationSpec: FiniteAnimationSpec<IntOffset>
     val sizeAnimationSpec: FiniteAnimationSpec<IntSize>
     val delayedPositionAnimationSpec: FiniteAnimationSpec<IntOffset>
-    val slideInFromLeftOffset: Int
-    val slideInFromRightOffset: Int
-    val slideOutToLeftOffset: Int
-    val slideOutToRightOffset: Int
-    val motionProgress: () -> Float
+    val scaffoldSize: IntSize
+    val currentPaneSizes: List<IntSize>
+    val currentPanePositions: List<IntOffset>
+    val targetPaneSizes: List<IntSize>
+    val targetPanePositions: List<IntOffset>
+    val paneMotions: List<PaneMotion>
+    val motionProgress: Float
 }
 
+@OptIn(ExperimentalMaterial3AdaptiveApi::class)
+internal val PaneScaffoldMotionScope.slideInFromLeftOffset: Int
+    get() {
+        // Find the right edge offset of the rightmost pane that enters from its left
+        for (i in paneMotions.lastIndex downTo 0) {
+            if (
+                paneMotions[i] == DefaultPaneMotion.EnterFromLeft ||
+                    paneMotions[i] == DefaultPaneMotion.EnterFromLeftDelayed
+            ) {
+                return -targetPanePositions[i].x - targetPaneSizes[i].width
+            }
+        }
+        return 0
+    }
+
+@OptIn(ExperimentalMaterial3AdaptiveApi::class)
+internal val PaneScaffoldMotionScope.slideInFromRightOffset: Int
+    get() {
+        // Find the left edge offset of the leftmost pane that enters from its right
+        paneMotions.fastForEachIndexed { i, paneMotion ->
+            if (
+                paneMotion == DefaultPaneMotion.EnterFromRight ||
+                    paneMotion == DefaultPaneMotion.EnterFromRightDelayed
+            ) {
+                return scaffoldSize.width - targetPanePositions[i].x
+            }
+        }
+        return 0
+    }
+
+@OptIn(ExperimentalMaterial3AdaptiveApi::class)
+internal val PaneScaffoldMotionScope.slideOutToLeftOffset: Int
+    get() {
+        // Find the right edge offset of the rightmost pane that exits to its left
+        for (i in paneMotions.lastIndex downTo 0) {
+            if (paneMotions[i] == DefaultPaneMotion.ExitToLeft) {
+                return -currentPanePositions[i].x - currentPaneSizes[i].width
+            }
+        }
+        return 0
+    }
+
+@OptIn(ExperimentalMaterial3AdaptiveApi::class)
+internal val PaneScaffoldMotionScope.slideOutToRightOffset: Int
+    get() {
+        // Find the left edge offset of the leftmost pane that exits to its right
+        paneMotions.fastForEachIndexed { i, paneMotion ->
+            if (paneMotion == DefaultPaneMotion.ExitToRight) {
+                return scaffoldSize.width - currentPanePositions[i].x
+            }
+        }
+        return 0
+    }
+
 @ExperimentalMaterial3AdaptiveApi
 internal interface PaneMotion {
-    val PaneMotionScope.enterTransition: EnterTransition
-    val PaneMotionScope.exitTransition: ExitTransition
-    val PaneMotionScope.animateBoundsModifier: Modifier
+    val PaneScaffoldMotionScope.enterTransition: EnterTransition
+    val PaneScaffoldMotionScope.exitTransition: ExitTransition
 }
 
 @ExperimentalMaterial3AdaptiveApi
@@ -68,7 +123,7 @@
         val ExitWithShrink = DefaultPaneMotion(9)
     }
 
-    override val PaneMotionScope.enterTransition: EnterTransition
+    override val PaneScaffoldMotionScope.enterTransition: EnterTransition
         get() =
             when (this@DefaultPaneMotion) {
                 EnterFromLeft ->
@@ -85,7 +140,7 @@
                 else -> EnterTransition.None
             }
 
-    override val PaneMotionScope.exitTransition: ExitTransition
+    override val PaneScaffoldMotionScope.exitTransition: ExitTransition
         get() =
             when (this@DefaultPaneMotion) {
                 ExitToLeft -> slideOutHorizontally(positionAnimationSpec) { slideOutToLeftOffset }
@@ -96,16 +151,6 @@
                 else -> ExitTransition.None
             }
 
-    override val PaneMotionScope.animateBoundsModifier: Modifier
-        get() =
-            Modifier.animateBounds(
-                motionProgress,
-                sizeAnimationSpec,
-                positionAnimationSpec,
-                this,
-                this@DefaultPaneMotion == AnimateBounds
-            )
-
     override fun toString(): String =
         when (this) {
             NoMotion -> "NoMotion"
@@ -128,10 +173,10 @@
     previousScaffoldValue: PaneScaffoldValue<T>,
     currentScaffoldValue: PaneScaffoldValue<T>,
     paneOrder: PaneScaffoldHorizontalOrder<T>
-): Array<PaneMotion> {
+): List<PaneMotion> {
     val numOfPanes = paneOrder.size
     val paneStatus = Array(numOfPanes) { PaneMotionStatus.Hidden }
-    val paneMotions = Array<PaneMotion>(numOfPanes) { DefaultPaneMotion.NoMotion }
+    val paneMotions = MutableList<PaneMotion>(numOfPanes) { DefaultPaneMotion.NoMotion }
     var firstShownPaneIndex = numOfPanes
     var firstEnteringPaneIndex = numOfPanes
     var lastShownPaneIndex = -1
diff --git a/compose/material3/adaptive/adaptive-layout/src/desktopMain/kotlin/androidx/compose/material3/adaptive/layout/PaneExpansionDragHandle.desktop.kt b/compose/material3/adaptive/adaptive-layout/src/desktopMain/kotlin/androidx/compose/material3/adaptive/layout/PaneExpansionDragHandle.desktop.kt
deleted file mode 100644
index d4a754b..0000000
--- a/compose/material3/adaptive/adaptive-layout/src/desktopMain/kotlin/androidx/compose/material3/adaptive/layout/PaneExpansionDragHandle.desktop.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material3.adaptive.layout
-
-import androidx.compose.ui.Modifier
-
-internal actual fun Modifier.systemGestureExclusion(): Modifier = this
diff --git a/compose/material3/adaptive/adaptive-layout/src/jvmStubsMain/kotlin/androidx/compose/material3/adaptive/layout/NotImplemented.jvmStubs.kt b/compose/material3/adaptive/adaptive-layout/src/jvmStubsMain/kotlin/androidx/compose/material3/adaptive/layout/NotImplemented.jvmStubs.kt
new file mode 100644
index 0000000..a2e9a00
--- /dev/null
+++ b/compose/material3/adaptive/adaptive-layout/src/jvmStubsMain/kotlin/androidx/compose/material3/adaptive/layout/NotImplemented.jvmStubs.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3.adaptive.layout
+
+@Suppress("NOTHING_TO_INLINE")
+internal inline fun implementedInJetBrainsFork(): Nothing =
+    throw NotImplementedError(
+        """
+        Implemented only in JetBrains fork.
+        Please use `org.jetbrains.compose.material3.adaptive:adaptive-layout` package instead.
+        """
+            .trimIndent()
+    )
diff --git a/compose/material3/adaptive/adaptive-layout/src/jvmStubsMain/kotlin/androidx/compose/material3/adaptive/layout/PaneExpansionDragHandle.jvmStubs.kt b/compose/material3/adaptive/adaptive-layout/src/jvmStubsMain/kotlin/androidx/compose/material3/adaptive/layout/PaneExpansionDragHandle.jvmStubs.kt
new file mode 100644
index 0000000..f8a917f
--- /dev/null
+++ b/compose/material3/adaptive/adaptive-layout/src/jvmStubsMain/kotlin/androidx/compose/material3/adaptive/layout/PaneExpansionDragHandle.jvmStubs.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3.adaptive.layout
+
+import androidx.compose.ui.Modifier
+
+internal actual fun Modifier.systemGestureExclusion(): Modifier = implementedInJetBrainsFork()
diff --git a/compose/material3/adaptive/adaptive-navigation/api/1.0.0-beta04.txt b/compose/material3/adaptive/adaptive-navigation/api/1.0.0-beta04.txt
new file mode 100644
index 0000000..3388cc4
--- /dev/null
+++ b/compose/material3/adaptive/adaptive-navigation/api/1.0.0-beta04.txt
@@ -0,0 +1,47 @@
+// Signature format: 4.0
+package androidx.compose.material3.adaptive.navigation {
+
+  public final class AndroidThreePaneScaffold_androidKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void NavigableListDetailPaneScaffold(androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator<java.lang.Object> navigator, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit> listPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit> detailPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit>? extraPane, optional String defaultBackBehavior);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void NavigableSupportingPaneScaffold(androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator<java.lang.Object> navigator, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit> mainPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit> supportingPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit>? extraPane, optional String defaultBackBehavior);
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @kotlin.jvm.JvmInline public final value class BackNavigationBehavior {
+    field public static final androidx.compose.material3.adaptive.navigation.BackNavigationBehavior.Companion Companion;
+  }
+
+  public static final class BackNavigationBehavior.Companion {
+    method public String getPopLatest();
+    method public String getPopUntilContentChange();
+    method public String getPopUntilCurrentDestinationChange();
+    method public String getPopUntilScaffoldValueChange();
+    property public final String PopLatest;
+    property public final String PopUntilContentChange;
+    property public final String PopUntilCurrentDestinationChange;
+    property public final String PopUntilScaffoldValueChange;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Stable public interface ThreePaneScaffoldNavigator<T> {
+    method public boolean canNavigateBack(optional String backNavigationBehavior);
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<T>? getCurrentDestination();
+    method public androidx.compose.material3.adaptive.layout.PaneScaffoldDirective getScaffoldDirective();
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue getScaffoldValue();
+    method public boolean isDestinationHistoryAware();
+    method public boolean navigateBack(optional String backNavigationBehavior);
+    method public void navigateTo(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole pane, optional T? content);
+    method public void setDestinationHistoryAware(boolean);
+    property public abstract androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<T>? currentDestination;
+    property public abstract boolean isDestinationHistoryAware;
+    property public abstract androidx.compose.material3.adaptive.layout.PaneScaffoldDirective scaffoldDirective;
+    property public abstract androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue scaffoldValue;
+  }
+
+  public final class ThreePaneScaffoldNavigatorKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator rememberListDetailPaneScaffoldNavigator(optional androidx.compose.material3.adaptive.layout.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies, optional boolean isDestinationHistoryAware);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static <T> androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator<T> rememberListDetailPaneScaffoldNavigator(optional androidx.compose.material3.adaptive.layout.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies, optional boolean isDestinationHistoryAware, optional java.util.List<? extends androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<? extends T>> initialDestinationHistory);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator rememberSupportingPaneScaffoldNavigator(optional androidx.compose.material3.adaptive.layout.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies, optional boolean isDestinationHistoryAware);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static <T> androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator<T> rememberSupportingPaneScaffoldNavigator(optional androidx.compose.material3.adaptive.layout.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies, optional boolean isDestinationHistoryAware, optional java.util.List<? extends androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<? extends T>> initialDestinationHistory);
+  }
+
+}
+
diff --git a/compose/material3/adaptive/adaptive-navigation/api/res-1.0.0-beta04.txt b/compose/material3/adaptive/adaptive-navigation/api/res-1.0.0-beta04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compose/material3/adaptive/adaptive-navigation/api/res-1.0.0-beta04.txt
diff --git a/compose/material3/adaptive/adaptive-navigation/api/restricted_1.0.0-beta04.txt b/compose/material3/adaptive/adaptive-navigation/api/restricted_1.0.0-beta04.txt
new file mode 100644
index 0000000..3388cc4
--- /dev/null
+++ b/compose/material3/adaptive/adaptive-navigation/api/restricted_1.0.0-beta04.txt
@@ -0,0 +1,47 @@
+// Signature format: 4.0
+package androidx.compose.material3.adaptive.navigation {
+
+  public final class AndroidThreePaneScaffold_androidKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void NavigableListDetailPaneScaffold(androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator<java.lang.Object> navigator, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit> listPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit> detailPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit>? extraPane, optional String defaultBackBehavior);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void NavigableSupportingPaneScaffold(androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator<java.lang.Object> navigator, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit> mainPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit> supportingPane, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit>? extraPane, optional String defaultBackBehavior);
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @kotlin.jvm.JvmInline public final value class BackNavigationBehavior {
+    field public static final androidx.compose.material3.adaptive.navigation.BackNavigationBehavior.Companion Companion;
+  }
+
+  public static final class BackNavigationBehavior.Companion {
+    method public String getPopLatest();
+    method public String getPopUntilContentChange();
+    method public String getPopUntilCurrentDestinationChange();
+    method public String getPopUntilScaffoldValueChange();
+    property public final String PopLatest;
+    property public final String PopUntilContentChange;
+    property public final String PopUntilCurrentDestinationChange;
+    property public final String PopUntilScaffoldValueChange;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Stable public interface ThreePaneScaffoldNavigator<T> {
+    method public boolean canNavigateBack(optional String backNavigationBehavior);
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<T>? getCurrentDestination();
+    method public androidx.compose.material3.adaptive.layout.PaneScaffoldDirective getScaffoldDirective();
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue getScaffoldValue();
+    method public boolean isDestinationHistoryAware();
+    method public boolean navigateBack(optional String backNavigationBehavior);
+    method public void navigateTo(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole pane, optional T? content);
+    method public void setDestinationHistoryAware(boolean);
+    property public abstract androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<T>? currentDestination;
+    property public abstract boolean isDestinationHistoryAware;
+    property public abstract androidx.compose.material3.adaptive.layout.PaneScaffoldDirective scaffoldDirective;
+    property public abstract androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue scaffoldValue;
+  }
+
+  public final class ThreePaneScaffoldNavigatorKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator rememberListDetailPaneScaffoldNavigator(optional androidx.compose.material3.adaptive.layout.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies, optional boolean isDestinationHistoryAware);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static <T> androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator<T> rememberListDetailPaneScaffoldNavigator(optional androidx.compose.material3.adaptive.layout.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies, optional boolean isDestinationHistoryAware, optional java.util.List<? extends androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<? extends T>> initialDestinationHistory);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator rememberSupportingPaneScaffoldNavigator(optional androidx.compose.material3.adaptive.layout.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies, optional boolean isDestinationHistoryAware);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static <T> androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator<T> rememberSupportingPaneScaffoldNavigator(optional androidx.compose.material3.adaptive.layout.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies, optional boolean isDestinationHistoryAware, optional java.util.List<? extends androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<? extends T>> initialDestinationHistory);
+  }
+
+}
+
diff --git a/compose/material3/adaptive/adaptive-navigation/build.gradle b/compose/material3/adaptive/adaptive-navigation/build.gradle
index e7f9947..e6f2983 100644
--- a/compose/material3/adaptive/adaptive-navigation/build.gradle
+++ b/compose/material3/adaptive/adaptive-navigation/build.gradle
@@ -33,14 +33,14 @@
 
 androidXMultiplatform {
     android()
-    desktop()
+    jvmStubs()
 
     defaultPlatform(PlatformIdentifier.ANDROID)
 
     sourceSets {
         commonMain {
             dependencies {
-                implementation(libs.kotlinStdlibCommon)
+                implementation(libs.kotlinStdlib)
                 api(project(":compose:material3:adaptive:adaptive-layout"))
                 implementation("androidx.compose.foundation:foundation:1.6.5")
                 implementation("androidx.compose.ui:ui-util:1.6.5")
@@ -55,7 +55,6 @@
         jvmMain {
             dependsOn(commonMain)
             dependencies {
-                implementation(libs.kotlinStdlib)
             }
         }
 
@@ -68,24 +67,14 @@
             }
         }
 
-        desktopMain {
+        jvmStubsMain {
             dependsOn(jvmMain)
             dependencies {
             }
         }
 
-        jvmTest {
-            dependsOn(commonTest)
-            dependencies {
-            }
-        }
-
-        desktopTest {
-            dependsOn(jvmTest)
-        }
-
         androidInstrumentedTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(project(":compose:material3:material3"))
                 implementation(project(":compose:test-utils"))
@@ -97,7 +86,7 @@
         }
 
         androidUnitTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(libs.junit)
                 implementation(libs.testRunner)
diff --git a/compose/material3/adaptive/adaptive/api/1.0.0-beta04.txt b/compose/material3/adaptive/adaptive/api/1.0.0-beta04.txt
new file mode 100644
index 0000000..4532ffe
--- /dev/null
+++ b/compose/material3/adaptive/adaptive/api/1.0.0-beta04.txt
@@ -0,0 +1,57 @@
+// Signature format: 4.0
+package androidx.compose.material3.adaptive {
+
+  public final class AndroidPosture_androidKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.Posture calculatePosture(java.util.List<? extends androidx.window.layout.FoldingFeature> foldingFeatures);
+  }
+
+  public final class AndroidWindowAdaptiveInfo_androidKt {
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<java.util.List<androidx.window.layout.FoldingFeature>> collectFoldingFeaturesAsState();
+    method @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.WindowAdaptiveInfo currentWindowAdaptiveInfo();
+    method @androidx.compose.runtime.Composable public static long currentWindowSize();
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn(message="This material3 adaptive API is experimental and is likely to change or to be" + "removed in the future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalMaterial3AdaptiveApi {
+  }
+
+  @androidx.compose.runtime.Immutable public final class HingeInfo {
+    ctor public HingeInfo(androidx.compose.ui.geometry.Rect bounds, boolean isFlat, boolean isVertical, boolean isSeparating, boolean isOccluding);
+    method public androidx.compose.ui.geometry.Rect getBounds();
+    method public boolean isFlat();
+    method public boolean isOccluding();
+    method public boolean isSeparating();
+    method public boolean isVertical();
+    property public final androidx.compose.ui.geometry.Rect bounds;
+    property public final boolean isFlat;
+    property public final boolean isOccluding;
+    property public final boolean isSeparating;
+    property public final boolean isVertical;
+  }
+
+  @androidx.compose.runtime.Immutable public final class Posture {
+    ctor public Posture(optional boolean isTabletop, optional java.util.List<androidx.compose.material3.adaptive.HingeInfo> hingeList);
+    method public java.util.List<androidx.compose.material3.adaptive.HingeInfo> getHingeList();
+    method public boolean isTabletop();
+    property public final java.util.List<androidx.compose.material3.adaptive.HingeInfo> hingeList;
+    property public final boolean isTabletop;
+  }
+
+  public final class PostureKt {
+    method public static java.util.List<androidx.compose.ui.geometry.Rect> getAllHorizontalHingeBounds(androidx.compose.material3.adaptive.Posture);
+    method public static java.util.List<androidx.compose.ui.geometry.Rect> getAllVerticalHingeBounds(androidx.compose.material3.adaptive.Posture);
+    method public static java.util.List<androidx.compose.ui.geometry.Rect> getOccludingHorizontalHingeBounds(androidx.compose.material3.adaptive.Posture);
+    method public static java.util.List<androidx.compose.ui.geometry.Rect> getOccludingVerticalHingeBounds(androidx.compose.material3.adaptive.Posture);
+    method public static java.util.List<androidx.compose.ui.geometry.Rect> getSeparatingHorizontalHingeBounds(androidx.compose.material3.adaptive.Posture);
+    method public static java.util.List<androidx.compose.ui.geometry.Rect> getSeparatingVerticalHingeBounds(androidx.compose.material3.adaptive.Posture);
+  }
+
+  @androidx.compose.runtime.Immutable public final class WindowAdaptiveInfo {
+    ctor public WindowAdaptiveInfo(androidx.window.core.layout.WindowSizeClass windowSizeClass, androidx.compose.material3.adaptive.Posture windowPosture);
+    method public androidx.compose.material3.adaptive.Posture getWindowPosture();
+    method public androidx.window.core.layout.WindowSizeClass getWindowSizeClass();
+    property public final androidx.compose.material3.adaptive.Posture windowPosture;
+    property public final androidx.window.core.layout.WindowSizeClass windowSizeClass;
+  }
+
+}
+
diff --git a/compose/material3/adaptive/adaptive/api/res-1.0.0-beta04.txt b/compose/material3/adaptive/adaptive/api/res-1.0.0-beta04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compose/material3/adaptive/adaptive/api/res-1.0.0-beta04.txt
diff --git a/compose/material3/adaptive/adaptive/api/restricted_1.0.0-beta04.txt b/compose/material3/adaptive/adaptive/api/restricted_1.0.0-beta04.txt
new file mode 100644
index 0000000..4532ffe
--- /dev/null
+++ b/compose/material3/adaptive/adaptive/api/restricted_1.0.0-beta04.txt
@@ -0,0 +1,57 @@
+// Signature format: 4.0
+package androidx.compose.material3.adaptive {
+
+  public final class AndroidPosture_androidKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.Posture calculatePosture(java.util.List<? extends androidx.window.layout.FoldingFeature> foldingFeatures);
+  }
+
+  public final class AndroidWindowAdaptiveInfo_androidKt {
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<java.util.List<androidx.window.layout.FoldingFeature>> collectFoldingFeaturesAsState();
+    method @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.WindowAdaptiveInfo currentWindowAdaptiveInfo();
+    method @androidx.compose.runtime.Composable public static long currentWindowSize();
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn(message="This material3 adaptive API is experimental and is likely to change or to be" + "removed in the future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalMaterial3AdaptiveApi {
+  }
+
+  @androidx.compose.runtime.Immutable public final class HingeInfo {
+    ctor public HingeInfo(androidx.compose.ui.geometry.Rect bounds, boolean isFlat, boolean isVertical, boolean isSeparating, boolean isOccluding);
+    method public androidx.compose.ui.geometry.Rect getBounds();
+    method public boolean isFlat();
+    method public boolean isOccluding();
+    method public boolean isSeparating();
+    method public boolean isVertical();
+    property public final androidx.compose.ui.geometry.Rect bounds;
+    property public final boolean isFlat;
+    property public final boolean isOccluding;
+    property public final boolean isSeparating;
+    property public final boolean isVertical;
+  }
+
+  @androidx.compose.runtime.Immutable public final class Posture {
+    ctor public Posture(optional boolean isTabletop, optional java.util.List<androidx.compose.material3.adaptive.HingeInfo> hingeList);
+    method public java.util.List<androidx.compose.material3.adaptive.HingeInfo> getHingeList();
+    method public boolean isTabletop();
+    property public final java.util.List<androidx.compose.material3.adaptive.HingeInfo> hingeList;
+    property public final boolean isTabletop;
+  }
+
+  public final class PostureKt {
+    method public static java.util.List<androidx.compose.ui.geometry.Rect> getAllHorizontalHingeBounds(androidx.compose.material3.adaptive.Posture);
+    method public static java.util.List<androidx.compose.ui.geometry.Rect> getAllVerticalHingeBounds(androidx.compose.material3.adaptive.Posture);
+    method public static java.util.List<androidx.compose.ui.geometry.Rect> getOccludingHorizontalHingeBounds(androidx.compose.material3.adaptive.Posture);
+    method public static java.util.List<androidx.compose.ui.geometry.Rect> getOccludingVerticalHingeBounds(androidx.compose.material3.adaptive.Posture);
+    method public static java.util.List<androidx.compose.ui.geometry.Rect> getSeparatingHorizontalHingeBounds(androidx.compose.material3.adaptive.Posture);
+    method public static java.util.List<androidx.compose.ui.geometry.Rect> getSeparatingVerticalHingeBounds(androidx.compose.material3.adaptive.Posture);
+  }
+
+  @androidx.compose.runtime.Immutable public final class WindowAdaptiveInfo {
+    ctor public WindowAdaptiveInfo(androidx.window.core.layout.WindowSizeClass windowSizeClass, androidx.compose.material3.adaptive.Posture windowPosture);
+    method public androidx.compose.material3.adaptive.Posture getWindowPosture();
+    method public androidx.window.core.layout.WindowSizeClass getWindowSizeClass();
+    property public final androidx.compose.material3.adaptive.Posture windowPosture;
+    property public final androidx.window.core.layout.WindowSizeClass windowSizeClass;
+  }
+
+}
+
diff --git a/compose/material3/adaptive/adaptive/build.gradle b/compose/material3/adaptive/adaptive/build.gradle
index b2ff51c..2e28d64 100644
--- a/compose/material3/adaptive/adaptive/build.gradle
+++ b/compose/material3/adaptive/adaptive/build.gradle
@@ -33,17 +33,17 @@
 
 androidXMultiplatform {
     android()
-    desktop()
+    jvmStubs()
 
     defaultPlatform(PlatformIdentifier.ANDROID)
 
     sourceSets {
         commonMain {
             dependencies {
-                implementation(libs.kotlinStdlibCommon)
+                implementation(libs.kotlinStdlib)
                 api("androidx.compose.foundation:foundation:1.6.5")
                 api("androidx.compose.ui:ui-geometry:1.6.5")
-                api("androidx.window:window-core:1.3.0-beta02")
+                api("androidx.window:window-core:1.3.0-rc01")
             }
         }
 
@@ -55,7 +55,6 @@
         jvmMain {
             dependsOn(commonMain)
             dependencies {
-                implementation(libs.kotlinStdlib)
             }
         }
 
@@ -64,28 +63,18 @@
             dependencies {
                 api("androidx.annotation:annotation:1.1.0")
                 api("androidx.annotation:annotation-experimental:1.4.0")
-                api("androidx.window:window:1.3.0-beta02")
+                api("androidx.window:window:1.3.0-rc01")
             }
         }
 
-        desktopMain {
+        jvmStubsMain {
             dependsOn(jvmMain)
             dependencies {
             }
         }
 
-        jvmTest {
-            dependsOn(commonTest)
-            dependencies {
-            }
-        }
-
-        desktopTest {
-            dependsOn(jvmTest)
-        }
-
         androidInstrumentedTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(project(":compose:material3:material3"))
                 implementation(project(":compose:test-utils"))
@@ -97,7 +86,7 @@
         }
 
         androidUnitTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(libs.junit)
                 implementation(libs.testRunner)
diff --git a/compose/material3/adaptive/adaptive/src/desktopMain/kotlin/androidx/compose/material3/adaptive/DesktopWindowInfo.desktop.kt b/compose/material3/adaptive/adaptive/src/desktopMain/kotlin/androidx/compose/material3/adaptive/DesktopWindowInfo.desktop.kt
deleted file mode 100644
index a32d0d4..0000000
--- a/compose/material3/adaptive/adaptive/src/desktopMain/kotlin/androidx/compose/material3/adaptive/DesktopWindowInfo.desktop.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material3.adaptive
-
-import androidx.compose.runtime.Composable
-
-@Composable
-actual fun currentWindowAdaptiveInfo(): WindowAdaptiveInfo {
-    TODO("Not yet implemented")
-}
diff --git a/compose/material3/adaptive/adaptive/src/jvmStubsMain/kotlin/androidx/compose/material3/adaptive/DesktopWindowInfo.jvmStubs.kt b/compose/material3/adaptive/adaptive/src/jvmStubsMain/kotlin/androidx/compose/material3/adaptive/DesktopWindowInfo.jvmStubs.kt
new file mode 100644
index 0000000..a85f34a
--- /dev/null
+++ b/compose/material3/adaptive/adaptive/src/jvmStubsMain/kotlin/androidx/compose/material3/adaptive/DesktopWindowInfo.jvmStubs.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3.adaptive
+
+import androidx.compose.runtime.Composable
+
+@Composable
+actual fun currentWindowAdaptiveInfo(): WindowAdaptiveInfo = implementedInJetBrainsFork()
diff --git a/compose/material3/adaptive/adaptive/src/jvmStubsMain/kotlin/androidx/compose/material3/adaptive/NotImplemented.jvmStubs.kt b/compose/material3/adaptive/adaptive/src/jvmStubsMain/kotlin/androidx/compose/material3/adaptive/NotImplemented.jvmStubs.kt
new file mode 100644
index 0000000..53311a1
--- /dev/null
+++ b/compose/material3/adaptive/adaptive/src/jvmStubsMain/kotlin/androidx/compose/material3/adaptive/NotImplemented.jvmStubs.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3.adaptive
+
+@Suppress("NOTHING_TO_INLINE")
+internal inline fun implementedInJetBrainsFork(): Nothing =
+    throw NotImplementedError(
+        """
+        Implemented only in JetBrains fork.
+        Please use `org.jetbrains.compose.material3.adaptive:adaptive` package instead.
+        """
+            .trimIndent()
+    )
diff --git a/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/ExposedDropdownMenuBenchmark.kt b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/ExposedDropdownMenuBenchmark.kt
index e90106d..b48e703 100644
--- a/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/ExposedDropdownMenuBenchmark.kt
+++ b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/ExposedDropdownMenuBenchmark.kt
@@ -22,9 +22,9 @@
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.size
 import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.ExposedDropdownMenuAnchorType
 import androidx.compose.material3.ExposedDropdownMenuBox
 import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.MenuAnchorType
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.MutableState
 import androidx.compose.runtime.mutableStateOf
@@ -113,7 +113,10 @@
                 expanded = expanded,
                 onExpandedChange = {},
             ) {
-                Spacer(Modifier.size(100.dp).menuAnchor(MenuAnchorType.PrimaryNotEditable))
+                Spacer(
+                    Modifier.size(100.dp)
+                        .menuAnchor(ExposedDropdownMenuAnchorType.PrimaryNotEditable)
+                )
                 // Can't test ExposedDropdownMenu directly because Popup can't be benchmarked
             }
         }
diff --git a/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/LoadingIndicatorBenchmark.kt b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/LoadingIndicatorBenchmark.kt
new file mode 100644
index 0000000..bd16c00
--- /dev/null
+++ b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/LoadingIndicatorBenchmark.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3.benchmark
+
+import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
+import androidx.compose.material3.LoadingIndicator
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.MutableFloatState
+import androidx.compose.runtime.mutableFloatStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.testutils.LayeredComposeTestCase
+import androidx.compose.testutils.ToggleableTestCase
+import androidx.compose.testutils.benchmark.ComposeBenchmarkRule
+import androidx.compose.testutils.benchmark.benchmarkToFirstPixel
+import androidx.compose.testutils.benchmark.toggleStateBenchmarkComposeMeasureLayout
+import androidx.test.filters.MediumTest
+import org.junit.Rule
+import org.junit.Test
+
+@MediumTest
+class LoadingIndicatorBenchmark {
+    @get:Rule val benchmarkRule = ComposeBenchmarkRule()
+
+    private val testCaseFactory = { LoadingIndicatorTestCase() }
+
+    @Test
+    fun firstPixel() {
+        benchmarkRule.benchmarkToFirstPixel(testCaseFactory)
+    }
+
+    @Test
+    fun changeProgress() {
+        benchmarkRule.toggleStateBenchmarkComposeMeasureLayout(
+            caseFactory = testCaseFactory,
+            requireRecomposition = false,
+        )
+    }
+}
+
+internal class LoadingIndicatorTestCase : LayeredComposeTestCase(), ToggleableTestCase {
+    private lateinit var state: MutableFloatState
+
+    @OptIn(ExperimentalMaterial3ExpressiveApi::class)
+    @Composable
+    override fun MeasuredContent() {
+        state = remember { mutableFloatStateOf(0f) }
+        LoadingIndicator(progress = { state.floatValue })
+    }
+
+    @Composable
+    override fun ContentWrappers(content: @Composable () -> Unit) {
+        MaterialTheme { content() }
+    }
+
+    override fun toggleState() {
+        state.floatValue = if (state.floatValue == 0f) 0.5f else 0.0f
+    }
+}
diff --git a/compose/material3/material3-adaptive-navigation-suite/build.gradle b/compose/material3/material3-adaptive-navigation-suite/build.gradle
index 8ebe6a3..35ca4949 100644
--- a/compose/material3/material3-adaptive-navigation-suite/build.gradle
+++ b/compose/material3/material3-adaptive-navigation-suite/build.gradle
@@ -33,14 +33,14 @@
 
 androidXMultiplatform {
     android()
-    desktop()
+    jvmStubs()
 
     defaultPlatform(PlatformIdentifier.ANDROID)
 
     sourceSets {
         commonMain {
             dependencies {
-                implementation(libs.kotlinStdlibCommon)
+                implementation(libs.kotlinStdlib)
                 api(project(":compose:material3:material3"))
                 api(project(":compose:material3:adaptive:adaptive"))
                 implementation("androidx.compose.ui:ui-util:1.6.0")
@@ -56,7 +56,6 @@
         jvmMain {
             dependsOn(commonMain)
             dependencies {
-                implementation(libs.kotlinStdlib)
             }
         }
 
@@ -68,24 +67,14 @@
             }
         }
 
-        desktopMain {
+        jvmStubsMain {
             dependsOn(jvmMain)
             dependencies {
             }
         }
 
-        jvmTest {
-            dependsOn(commonTest)
-            dependencies {
-            }
-        }
-
-        desktopTest {
-            dependsOn(jvmTest)
-        }
-
         androidInstrumentedTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(project(":compose:test-utils"))
                 implementation(project(":window:window-testing"))
@@ -96,7 +85,7 @@
         }
 
         androidUnitTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(libs.junit)
                 implementation(libs.testRunner)
diff --git a/compose/material3/material3-common/build.gradle b/compose/material3/material3-common/build.gradle
index 8bf304a5..286e981 100644
--- a/compose/material3/material3-common/build.gradle
+++ b/compose/material3/material3-common/build.gradle
@@ -34,14 +34,14 @@
 
 androidXMultiplatform {
     android()
-    desktop()
+    jvmStubs()
 
     defaultPlatform(PlatformIdentifier.ANDROID)
 
     sourceSets {
         commonMain {
             dependencies {
-                implementation(libs.kotlinStdlibCommon)
+                implementation(libs.kotlinStdlib)
                 implementation(project(":compose:ui:ui-util"))
                 api("androidx.compose.foundation:foundation:1.6.0")
                 api("androidx.compose.foundation:foundation-layout:1.6.0")
@@ -50,8 +50,6 @@
                 api("androidx.compose.ui:ui-text:1.6.0")
             }
         }
-        androidMain.dependencies {
-        }
 
         commonTest {
             dependencies {
@@ -61,7 +59,6 @@
         jvmMain {
             dependsOn(commonMain)
             dependencies {
-                implementation(libs.kotlinStdlib)
             }
         }
 
@@ -72,20 +69,14 @@
             }
         }
 
-        desktopMain {
+        jvmStubsMain {
             dependsOn(jvmMain)
             dependencies {
             }
         }
 
-        jvmTest {
-            dependsOn(commonTest)
-            dependencies {
-            }
-        }
-
         androidInstrumentedTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(project(":compose:material3:material3"))
                 implementation(project(":compose:material3:material3-common"))
@@ -95,12 +86,6 @@
                 implementation(libs.truth)
             }
         }
-
-        desktopTest {
-            dependsOn(jvmTest)
-            dependencies {
-            }
-        }
     }
 }
 
diff --git a/compose/material3/material3-window-size-class/build.gradle b/compose/material3/material3-window-size-class/build.gradle
index 82ac0b0..1f443e0 100644
--- a/compose/material3/material3-window-size-class/build.gradle
+++ b/compose/material3/material3-window-size-class/build.gradle
@@ -32,14 +32,14 @@
 
 androidXMultiplatform {
     android()
-    desktop()
+    jvmStubs()
 
     defaultPlatform(PlatformIdentifier.ANDROID)
 
     sourceSets {
         commonMain {
             dependencies {
-                implementation(libs.kotlinStdlibCommon)
+                implementation(libs.kotlinStdlib)
                 implementation("androidx.compose.ui:ui-util:1.6.0")
                 api("androidx.compose.runtime:runtime:1.7.0-beta02")
                 api("androidx.compose.ui:ui:1.6.0")
@@ -49,20 +49,12 @@
 
         commonTest {
             dependencies {
-
             }
         }
 
         jvmMain {
             dependsOn(commonMain)
             dependencies {
-                implementation(libs.kotlinStdlib)
-            }
-        }
-
-        skikoMain {
-            dependsOn(commonMain)
-            dependencies {
             }
         }
 
@@ -74,22 +66,14 @@
             }
         }
 
-        desktopMain {
-            dependsOn(skikoMain)
+        jvmStubsMain {
             dependsOn(jvmMain)
             dependencies {
-
-            }
-        }
-
-        jvmTest {
-            dependsOn(commonTest)
-            dependencies {
             }
         }
 
         androidInstrumentedTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(project(":compose:test-utils"))
                 implementation("androidx.compose.foundation:foundation:1.6.0")
@@ -101,19 +85,12 @@
         }
 
         androidUnitTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(libs.kotlinTest)
                 implementation(libs.truth)
             }
         }
-
-        desktopTest {
-            dependsOn(jvmTest)
-            dependencies {
-
-            }
-        }
     }
 }
 
diff --git a/compose/material3/material3/api/current.ignore b/compose/material3/material3/api/current.ignore
index de249ef3..6bb94cb 100644
--- a/compose/material3/material3/api/current.ignore
+++ b/compose/material3/material3/api/current.ignore
@@ -1,3 +1,3 @@
 // Baseline format: 1.0
-AddedClass: androidx.compose.material3.ModalBottomSheetKt:
-    Added class androidx.compose.material3.ModalBottomSheetKt
+RemovedClass: androidx.compose.material3.MenuAnchorType:
+    Removed class androidx.compose.material3.MenuAnchorType
diff --git a/compose/material3/material3/api/current.txt b/compose/material3/material3/api/current.txt
index f28280d..ba89d47 100644
--- a/compose/material3/material3/api/current.txt
+++ b/compose/material3/material3/api/current.txt
@@ -43,10 +43,13 @@
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void CenterAlignedTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @Deprecated @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void LargeTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void LargeTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional float collapsedHeight, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public static void LargeTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, kotlin.jvm.functions.Function0<kotlin.Unit>? subtitle, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional int titleHorizontalAlignment, optional float collapsedHeight, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @Deprecated @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void MediumTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void MediumTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional float collapsedHeight, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public static void MediumTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, kotlin.jvm.functions.Function0<kotlin.Unit>? subtitle, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional int titleHorizontalAlignment, optional float collapsedHeight, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @Deprecated @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void TopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void TopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public static void TopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, kotlin.jvm.functions.Function0<kotlin.Unit> subtitle, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional int titleHorizontalAlignment, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.BottomAppBarState rememberBottomAppBarState(optional float initialHeightOffsetLimit, optional float initialHeightOffset, optional float initialContentOffset);
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.TopAppBarState rememberTopAppBarState(optional float initialHeightOffsetLimit, optional float initialHeightOffset, optional float initialContentOffset);
   }
@@ -696,11 +699,24 @@
   @SuppressCompatibility @kotlin.RequiresOptIn(message="This material3 API is experimental and is likely to change or to be removed in the" + " future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalMaterial3ExpressiveApi {
   }
 
+  @kotlin.jvm.JvmInline public final value class ExposedDropdownMenuAnchorType {
+    field public static final androidx.compose.material3.ExposedDropdownMenuAnchorType.Companion Companion;
+  }
+
+  public static final class ExposedDropdownMenuAnchorType.Companion {
+    method public String getPrimaryEditable();
+    method public String getPrimaryNotEditable();
+    method public String getSecondaryEditable();
+    property public final String PrimaryEditable;
+    property public final String PrimaryNotEditable;
+    property public final String SecondaryEditable;
+  }
+
   @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public abstract sealed class ExposedDropdownMenuBoxScope {
-    method @androidx.compose.runtime.Composable public final void ExposedDropdownMenu(boolean expanded, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.ScrollState scrollState, optional boolean matchTextFieldWidth, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional float tonalElevation, optional float shadowElevation, optional androidx.compose.foundation.BorderStroke? border, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public final void ExposedDropdownMenu(boolean expanded, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.ScrollState scrollState, optional boolean matchAnchorWidth, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional float tonalElevation, optional float shadowElevation, optional androidx.compose.foundation.BorderStroke? border, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
     method @Deprecated @androidx.compose.runtime.Composable public final void ExposedDropdownMenu(boolean expanded, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.ScrollState scrollState, optional boolean focusable, optional boolean matchTextFieldWidth, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional float tonalElevation, optional float shadowElevation, optional androidx.compose.foundation.BorderStroke? border, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
     method @Deprecated @androidx.compose.runtime.Composable public void ExposedDropdownMenu(boolean expanded, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.ScrollState scrollState, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
-    method public abstract androidx.compose.ui.Modifier exposedDropdownSize(androidx.compose.ui.Modifier, optional boolean matchTextFieldWidth);
+    method public abstract androidx.compose.ui.Modifier exposedDropdownSize(androidx.compose.ui.Modifier, optional boolean matchAnchorWidth);
     method @Deprecated public final androidx.compose.ui.Modifier menuAnchor(androidx.compose.ui.Modifier);
     method public abstract androidx.compose.ui.Modifier menuAnchor(androidx.compose.ui.Modifier, String type, optional boolean enabled);
   }
@@ -882,6 +898,13 @@
     method @androidx.compose.runtime.Composable public androidx.compose.material3.IconToggleButtonColors filledTonalIconToggleButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor, optional long checkedContainerColor, optional long checkedContentColor);
     method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getFilledShape();
     method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getOutlinedShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getRoundShape();
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi public long getSmallContainerSize();
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi public float getSmallIconSize();
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi public long getSmallNarrowContainerSize();
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi public long getSmallWideContainerSize();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getSquareShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getStandardShape();
     method @androidx.compose.runtime.Composable public androidx.compose.material3.IconButtonColors iconButtonColors();
     method @androidx.compose.runtime.Composable public androidx.compose.material3.IconButtonColors iconButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
     method @androidx.compose.runtime.Composable public androidx.compose.material3.IconToggleButtonColors iconToggleButtonColors();
@@ -892,8 +915,15 @@
     method @androidx.compose.runtime.Composable public androidx.compose.foundation.BorderStroke? outlinedIconToggleButtonBorder(boolean enabled, boolean checked);
     method @androidx.compose.runtime.Composable public androidx.compose.material3.IconToggleButtonColors outlinedIconToggleButtonColors();
     method @androidx.compose.runtime.Composable public androidx.compose.material3.IconToggleButtonColors outlinedIconToggleButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor, optional long checkedContainerColor, optional long checkedContentColor);
+    property @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi public final long SmallContainerSize;
+    property @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi public final float SmallIconSize;
+    property @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi public final long SmallNarrowContainerSize;
+    property @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi public final long SmallWideContainerSize;
     property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape filledShape;
     property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape outlinedShape;
+    property @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape roundShape;
+    property @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape squareShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape standardShape;
     field public static final androidx.compose.material3.IconButtonDefaults INSTANCE;
   }
 
@@ -902,8 +932,10 @@
     method @androidx.compose.runtime.Composable public static void FilledIconToggleButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.IconToggleButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
     method @androidx.compose.runtime.Composable public static void FilledTonalIconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
     method @androidx.compose.runtime.Composable public static void FilledTonalIconToggleButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.IconToggleButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
-    method @androidx.compose.runtime.Composable public static void IconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
-    method @androidx.compose.runtime.Composable public static void IconToggleButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.material3.IconToggleButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void IconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, optional androidx.compose.ui.graphics.Shape shape, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @Deprecated @androidx.compose.runtime.Composable public static void IconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void IconToggleButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.material3.IconToggleButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, optional androidx.compose.ui.graphics.Shape shape, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @Deprecated @androidx.compose.runtime.Composable public static void IconToggleButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.material3.IconToggleButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
     method @androidx.compose.runtime.Composable public static void OutlinedIconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
     method @androidx.compose.runtime.Composable public static void OutlinedIconToggleButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.IconToggleButtonColors colors, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
   }
@@ -999,6 +1031,113 @@
     method @androidx.compose.runtime.Composable public static void ListItem(kotlin.jvm.functions.Function0<kotlin.Unit> headlineContent, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? overlineContent, optional kotlin.jvm.functions.Function0<kotlin.Unit>? supportingContent, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingContent, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingContent, optional androidx.compose.material3.ListItemColors colors, optional float tonalElevation, optional float shadowElevation);
   }
 
+  @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi public final class LoadingIndicatorDefaults {
+    method @androidx.compose.runtime.Composable public long getContainerColor();
+    method public float getContainerHeight();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getContainerShape();
+    method public float getContainerWidth();
+    method public java.util.List<androidx.graphics.shapes.RoundedPolygon> getDeterminateIndicatorPolygons();
+    method public java.util.List<androidx.graphics.shapes.RoundedPolygon> getIndeterminateIndicatorPolygons();
+    method @androidx.compose.runtime.Composable public long getIndicatorColor();
+    method public float getIndicatorSize();
+    property @androidx.compose.runtime.Composable public final long ContainerColor;
+    property public final float ContainerHeight;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape ContainerShape;
+    property public final float ContainerWidth;
+    property public final java.util.List<androidx.graphics.shapes.RoundedPolygon> DeterminateIndicatorPolygons;
+    property public final java.util.List<androidx.graphics.shapes.RoundedPolygon> IndeterminateIndicatorPolygons;
+    property @androidx.compose.runtime.Composable public final long IndicatorColor;
+    property public final float IndicatorSize;
+    field public static final androidx.compose.material3.LoadingIndicatorDefaults INSTANCE;
+  }
+
+  public final class LoadingIndicatorKt {
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public static void LoadingIndicator(optional androidx.compose.ui.Modifier modifier, optional long containerColor, optional long indicatorColor, optional androidx.compose.ui.graphics.Shape containerShape, optional java.util.List<androidx.graphics.shapes.RoundedPolygon> indicatorPolygons);
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public static void LoadingIndicator(kotlin.jvm.functions.Function0<java.lang.Float> progress, optional androidx.compose.ui.Modifier modifier, optional long containerColor, optional long indicatorColor, optional androidx.compose.ui.graphics.Shape containerShape, optional java.util.List<androidx.graphics.shapes.RoundedPolygon> indicatorPolygons);
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi public abstract sealed class MaterialShapes {
+    field public static final androidx.compose.material3.MaterialShapes.Companion Companion;
+  }
+
+  public static final class MaterialShapes.Companion {
+    method public androidx.graphics.shapes.RoundedPolygon getArch();
+    method public androidx.graphics.shapes.RoundedPolygon getArrow();
+    method public androidx.graphics.shapes.RoundedPolygon getBoom();
+    method public androidx.graphics.shapes.RoundedPolygon getBun();
+    method public androidx.graphics.shapes.RoundedPolygon getBurst();
+    method public androidx.graphics.shapes.RoundedPolygon getCircle();
+    method public androidx.graphics.shapes.RoundedPolygon getClamShell();
+    method public androidx.graphics.shapes.RoundedPolygon getClover4Leaf();
+    method public androidx.graphics.shapes.RoundedPolygon getClover8Leaf();
+    method public androidx.graphics.shapes.RoundedPolygon getCookie12Sided();
+    method public androidx.graphics.shapes.RoundedPolygon getCookie4Sided();
+    method public androidx.graphics.shapes.RoundedPolygon getCookie6Sided();
+    method public androidx.graphics.shapes.RoundedPolygon getCookie7Sided();
+    method public androidx.graphics.shapes.RoundedPolygon getCookie9Sided();
+    method public androidx.graphics.shapes.RoundedPolygon getDiamond();
+    method public androidx.graphics.shapes.RoundedPolygon getFan();
+    method public androidx.graphics.shapes.RoundedPolygon getFlower();
+    method public androidx.graphics.shapes.RoundedPolygon getGem();
+    method public androidx.graphics.shapes.RoundedPolygon getGhostish();
+    method public androidx.graphics.shapes.RoundedPolygon getHeart();
+    method public androidx.graphics.shapes.RoundedPolygon getOval();
+    method public androidx.graphics.shapes.RoundedPolygon getPentagon();
+    method public androidx.graphics.shapes.RoundedPolygon getPill();
+    method public androidx.graphics.shapes.RoundedPolygon getPixelCircle();
+    method public androidx.graphics.shapes.RoundedPolygon getPixelTriangle();
+    method public androidx.graphics.shapes.RoundedPolygon getPuffy();
+    method public androidx.graphics.shapes.RoundedPolygon getPuffyDiamond();
+    method public androidx.graphics.shapes.RoundedPolygon getSemiCircle();
+    method public androidx.graphics.shapes.RoundedPolygon getSlanted();
+    method public androidx.graphics.shapes.RoundedPolygon getSoftBoom();
+    method public androidx.graphics.shapes.RoundedPolygon getSoftBurst();
+    method public androidx.graphics.shapes.RoundedPolygon getSquare();
+    method public androidx.graphics.shapes.RoundedPolygon getSunny();
+    method public androidx.graphics.shapes.RoundedPolygon getTriangle();
+    method public androidx.graphics.shapes.RoundedPolygon getVerySunny();
+    property public final androidx.graphics.shapes.RoundedPolygon Arch;
+    property public final androidx.graphics.shapes.RoundedPolygon Arrow;
+    property public final androidx.graphics.shapes.RoundedPolygon Boom;
+    property public final androidx.graphics.shapes.RoundedPolygon Bun;
+    property public final androidx.graphics.shapes.RoundedPolygon Burst;
+    property public final androidx.graphics.shapes.RoundedPolygon Circle;
+    property public final androidx.graphics.shapes.RoundedPolygon ClamShell;
+    property public final androidx.graphics.shapes.RoundedPolygon Clover4Leaf;
+    property public final androidx.graphics.shapes.RoundedPolygon Clover8Leaf;
+    property public final androidx.graphics.shapes.RoundedPolygon Cookie12Sided;
+    property public final androidx.graphics.shapes.RoundedPolygon Cookie4Sided;
+    property public final androidx.graphics.shapes.RoundedPolygon Cookie6Sided;
+    property public final androidx.graphics.shapes.RoundedPolygon Cookie7Sided;
+    property public final androidx.graphics.shapes.RoundedPolygon Cookie9Sided;
+    property public final androidx.graphics.shapes.RoundedPolygon Diamond;
+    property public final androidx.graphics.shapes.RoundedPolygon Fan;
+    property public final androidx.graphics.shapes.RoundedPolygon Flower;
+    property public final androidx.graphics.shapes.RoundedPolygon Gem;
+    property public final androidx.graphics.shapes.RoundedPolygon Ghostish;
+    property public final androidx.graphics.shapes.RoundedPolygon Heart;
+    property public final androidx.graphics.shapes.RoundedPolygon Oval;
+    property public final androidx.graphics.shapes.RoundedPolygon Pentagon;
+    property public final androidx.graphics.shapes.RoundedPolygon Pill;
+    property public final androidx.graphics.shapes.RoundedPolygon PixelCircle;
+    property public final androidx.graphics.shapes.RoundedPolygon PixelTriangle;
+    property public final androidx.graphics.shapes.RoundedPolygon Puffy;
+    property public final androidx.graphics.shapes.RoundedPolygon PuffyDiamond;
+    property public final androidx.graphics.shapes.RoundedPolygon SemiCircle;
+    property public final androidx.graphics.shapes.RoundedPolygon Slanted;
+    property public final androidx.graphics.shapes.RoundedPolygon SoftBoom;
+    property public final androidx.graphics.shapes.RoundedPolygon SoftBurst;
+    property public final androidx.graphics.shapes.RoundedPolygon Square;
+    property public final androidx.graphics.shapes.RoundedPolygon Sunny;
+    property public final androidx.graphics.shapes.RoundedPolygon Triangle;
+    property public final androidx.graphics.shapes.RoundedPolygon VerySunny;
+  }
+
+  public final class MaterialShapesKt {
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public static androidx.compose.ui.graphics.Path toPath(androidx.graphics.shapes.RoundedPolygon, optional int startAngle);
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public static androidx.compose.ui.graphics.Shape toShape(androidx.graphics.shapes.RoundedPolygon, optional int startAngle);
+  }
+
   public final class MaterialTheme {
     method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.compose.material3.ColorScheme getColorScheme();
     method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.compose.material3.Shapes getShapes();
@@ -1014,19 +1153,6 @@
     method @androidx.compose.runtime.Composable public static void MaterialTheme(optional androidx.compose.material3.ColorScheme colorScheme, optional androidx.compose.material3.Shapes shapes, optional androidx.compose.material3.Typography typography, kotlin.jvm.functions.Function0<kotlin.Unit> content);
   }
 
-  @kotlin.jvm.JvmInline public final value class MenuAnchorType {
-    field public static final androidx.compose.material3.MenuAnchorType.Companion Companion;
-  }
-
-  public static final class MenuAnchorType.Companion {
-    method public String getPrimaryEditable();
-    method public String getPrimaryNotEditable();
-    method public String getSecondaryEditable();
-    property public final String PrimaryEditable;
-    property public final String PrimaryNotEditable;
-    property public final String SecondaryEditable;
-  }
-
   public final class MenuDefaults {
     method @androidx.compose.runtime.Composable public long getContainerColor();
     method public androidx.compose.foundation.layout.PaddingValues getDropdownMenuItemContentPadding();
@@ -2223,8 +2349,12 @@
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarScrollBehavior exitUntilCollapsedScrollBehavior(optional androidx.compose.material3.TopAppBarState state, optional kotlin.jvm.functions.Function0<java.lang.Boolean> canScroll, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float>? snapAnimationSpec, optional androidx.compose.animation.core.DecayAnimationSpec<java.lang.Float>? flingAnimationSpec);
     method public float getLargeAppBarCollapsedHeight();
     method public float getLargeAppBarExpandedHeight();
+    method public float getLargeAppBarWithSubtitleExpandedHeight();
+    method public float getLargeAppBarWithoutSubtitleExpandedHeight();
     method public float getMediumAppBarCollapsedHeight();
     method public float getMediumAppBarExpandedHeight();
+    method public float getMediumAppBarWithSubtitleExpandedHeight();
+    method public float getMediumAppBarWithoutSubtitleExpandedHeight();
     method public float getTopAppBarExpandedHeight();
     method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
     method @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors largeTopAppBarColors();
@@ -2236,8 +2366,12 @@
     method @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors topAppBarColors(optional long containerColor, optional long scrolledContainerColor, optional long navigationIconContentColor, optional long titleContentColor, optional long actionIconContentColor);
     property public final float LargeAppBarCollapsedHeight;
     property public final float LargeAppBarExpandedHeight;
+    property public final float LargeAppBarWithSubtitleExpandedHeight;
+    property public final float LargeAppBarWithoutSubtitleExpandedHeight;
     property public final float MediumAppBarCollapsedHeight;
     property public final float MediumAppBarExpandedHeight;
+    property public final float MediumAppBarWithSubtitleExpandedHeight;
+    property public final float MediumAppBarWithoutSubtitleExpandedHeight;
     property public final float TopAppBarExpandedHeight;
     property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets windowInsets;
     field public static final androidx.compose.material3.TopAppBarDefaults INSTANCE;
@@ -2279,6 +2413,19 @@
     property public final androidx.compose.runtime.saveable.Saver<androidx.compose.material3.TopAppBarState,? extends java.lang.Object?> Saver;
   }
 
+  @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @kotlin.jvm.JvmInline public final value class TopAppBarTitleAlignment {
+    field public static final androidx.compose.material3.TopAppBarTitleAlignment.Companion Companion;
+  }
+
+  public static final class TopAppBarTitleAlignment.Companion {
+    method public int getCenter();
+    method public int getEnd();
+    method public int getStart();
+    property public final int Center;
+    property public final int End;
+    property public final int Start;
+  }
+
   @androidx.compose.runtime.Immutable public final class Typography {
     ctor public Typography(optional androidx.compose.ui.text.TextStyle displayLarge, optional androidx.compose.ui.text.TextStyle displayMedium, optional androidx.compose.ui.text.TextStyle displaySmall, optional androidx.compose.ui.text.TextStyle headlineLarge, optional androidx.compose.ui.text.TextStyle headlineMedium, optional androidx.compose.ui.text.TextStyle headlineSmall, optional androidx.compose.ui.text.TextStyle titleLarge, optional androidx.compose.ui.text.TextStyle titleMedium, optional androidx.compose.ui.text.TextStyle titleSmall, optional androidx.compose.ui.text.TextStyle bodyLarge, optional androidx.compose.ui.text.TextStyle bodyMedium, optional androidx.compose.ui.text.TextStyle bodySmall, optional androidx.compose.ui.text.TextStyle labelLarge, optional androidx.compose.ui.text.TextStyle labelMedium, optional androidx.compose.ui.text.TextStyle labelSmall);
     method public androidx.compose.material3.Typography copy(optional androidx.compose.ui.text.TextStyle displayLarge, optional androidx.compose.ui.text.TextStyle displayMedium, optional androidx.compose.ui.text.TextStyle displaySmall, optional androidx.compose.ui.text.TextStyle headlineLarge, optional androidx.compose.ui.text.TextStyle headlineMedium, optional androidx.compose.ui.text.TextStyle headlineSmall, optional androidx.compose.ui.text.TextStyle titleLarge, optional androidx.compose.ui.text.TextStyle titleMedium, optional androidx.compose.ui.text.TextStyle titleSmall, optional androidx.compose.ui.text.TextStyle bodyLarge, optional androidx.compose.ui.text.TextStyle bodyMedium, optional androidx.compose.ui.text.TextStyle bodySmall, optional androidx.compose.ui.text.TextStyle labelLarge, optional androidx.compose.ui.text.TextStyle labelMedium, optional androidx.compose.ui.text.TextStyle labelSmall);
@@ -2324,11 +2471,12 @@
     method @androidx.compose.runtime.Composable public long getIndicatorColor();
     method public float getLinearContainerHeight();
     method public float getLinearContainerWidth();
+    method public float getLinearDeterminateWavelength();
+    method public float getLinearIndeterminateWavelength();
     method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.drawscope.Stroke getLinearIndicatorStroke();
     method public float getLinearIndicatorTrackGapSize();
     method public float getLinearTrackStopIndicatorSize();
     method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.drawscope.Stroke getLinearTrackStroke();
-    method public float getLinearWavelength();
     method public androidx.compose.animation.core.AnimationSpec<java.lang.Float> getProgressAnimationSpec();
     method @androidx.compose.runtime.Composable public long getTrackColor();
     property public final float CircularContainerSize;
@@ -2336,9 +2484,10 @@
     property public final float CircularWavelength;
     property public final float LinearContainerHeight;
     property public final float LinearContainerWidth;
+    property public final float LinearDeterminateWavelength;
+    property public final float LinearIndeterminateWavelength;
     property public final float LinearIndicatorTrackGapSize;
     property public final float LinearTrackStopIndicatorSize;
-    property public final float LinearWavelength;
     property public final androidx.compose.animation.core.AnimationSpec<java.lang.Float> ProgressAnimationSpec;
     property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.drawscope.Stroke circularIndicatorStroke;
     property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.drawscope.Stroke circularTrackStroke;
@@ -2421,15 +2570,20 @@
   @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public final class PullToRefreshDefaults {
     method @androidx.compose.runtime.Composable public void Indicator(androidx.compose.material3.pulltorefresh.PullToRefreshState state, boolean isRefreshing, optional androidx.compose.ui.Modifier modifier, optional long containerColor, optional long color, optional float threshold);
     method @androidx.compose.runtime.Composable public void IndicatorBox(androidx.compose.material3.pulltorefresh.PullToRefreshState state, boolean isRefreshing, optional androidx.compose.ui.Modifier modifier, optional float threshold, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional float elevation, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
-    method @androidx.compose.runtime.Composable public long getContainerColor();
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public void LoadingIndicator(androidx.compose.material3.pulltorefresh.PullToRefreshState state, boolean isRefreshing, optional androidx.compose.ui.Modifier modifier, optional long containerColor, optional long color, optional float elevation, optional float threshold);
+    method @Deprecated @androidx.compose.runtime.Composable public long getContainerColor();
     method public float getElevation();
-    method @androidx.compose.runtime.Composable public long getIndicatorColor();
+    method @Deprecated @androidx.compose.runtime.Composable public long getIndicatorColor();
+    method @androidx.compose.runtime.Composable public long getLoadingIndicatorColor();
+    method @androidx.compose.runtime.Composable public long getLoadingIndicatorContainerColor();
     method public float getPositionalThreshold();
     method public androidx.compose.ui.graphics.Shape getShape();
     property public final float Elevation;
     property public final float PositionalThreshold;
-    property @androidx.compose.runtime.Composable public final long containerColor;
-    property @androidx.compose.runtime.Composable public final long indicatorColor;
+    property @Deprecated @androidx.compose.runtime.Composable public final long containerColor;
+    property @Deprecated @androidx.compose.runtime.Composable public final long indicatorColor;
+    property @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public final long loadingIndicatorColor;
+    property @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public final long loadingIndicatorContainerColor;
     property public final androidx.compose.ui.graphics.Shape shape;
     field public static final androidx.compose.material3.pulltorefresh.PullToRefreshDefaults INSTANCE;
   }
diff --git a/compose/material3/material3/api/restricted_current.ignore b/compose/material3/material3/api/restricted_current.ignore
index de249ef3..6bb94cb 100644
--- a/compose/material3/material3/api/restricted_current.ignore
+++ b/compose/material3/material3/api/restricted_current.ignore
@@ -1,3 +1,3 @@
 // Baseline format: 1.0
-AddedClass: androidx.compose.material3.ModalBottomSheetKt:
-    Added class androidx.compose.material3.ModalBottomSheetKt
+RemovedClass: androidx.compose.material3.MenuAnchorType:
+    Removed class androidx.compose.material3.MenuAnchorType
diff --git a/compose/material3/material3/api/restricted_current.txt b/compose/material3/material3/api/restricted_current.txt
index f28280d..ba89d47 100644
--- a/compose/material3/material3/api/restricted_current.txt
+++ b/compose/material3/material3/api/restricted_current.txt
@@ -43,10 +43,13 @@
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void CenterAlignedTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @Deprecated @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void LargeTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void LargeTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional float collapsedHeight, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public static void LargeTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, kotlin.jvm.functions.Function0<kotlin.Unit>? subtitle, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional int titleHorizontalAlignment, optional float collapsedHeight, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @Deprecated @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void MediumTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void MediumTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional float collapsedHeight, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public static void MediumTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, kotlin.jvm.functions.Function0<kotlin.Unit>? subtitle, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional int titleHorizontalAlignment, optional float collapsedHeight, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @Deprecated @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void TopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void TopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public static void TopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, kotlin.jvm.functions.Function0<kotlin.Unit> subtitle, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional int titleHorizontalAlignment, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.BottomAppBarState rememberBottomAppBarState(optional float initialHeightOffsetLimit, optional float initialHeightOffset, optional float initialContentOffset);
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.TopAppBarState rememberTopAppBarState(optional float initialHeightOffsetLimit, optional float initialHeightOffset, optional float initialContentOffset);
   }
@@ -696,11 +699,24 @@
   @SuppressCompatibility @kotlin.RequiresOptIn(message="This material3 API is experimental and is likely to change or to be removed in the" + " future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalMaterial3ExpressiveApi {
   }
 
+  @kotlin.jvm.JvmInline public final value class ExposedDropdownMenuAnchorType {
+    field public static final androidx.compose.material3.ExposedDropdownMenuAnchorType.Companion Companion;
+  }
+
+  public static final class ExposedDropdownMenuAnchorType.Companion {
+    method public String getPrimaryEditable();
+    method public String getPrimaryNotEditable();
+    method public String getSecondaryEditable();
+    property public final String PrimaryEditable;
+    property public final String PrimaryNotEditable;
+    property public final String SecondaryEditable;
+  }
+
   @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public abstract sealed class ExposedDropdownMenuBoxScope {
-    method @androidx.compose.runtime.Composable public final void ExposedDropdownMenu(boolean expanded, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.ScrollState scrollState, optional boolean matchTextFieldWidth, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional float tonalElevation, optional float shadowElevation, optional androidx.compose.foundation.BorderStroke? border, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public final void ExposedDropdownMenu(boolean expanded, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.ScrollState scrollState, optional boolean matchAnchorWidth, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional float tonalElevation, optional float shadowElevation, optional androidx.compose.foundation.BorderStroke? border, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
     method @Deprecated @androidx.compose.runtime.Composable public final void ExposedDropdownMenu(boolean expanded, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.ScrollState scrollState, optional boolean focusable, optional boolean matchTextFieldWidth, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional float tonalElevation, optional float shadowElevation, optional androidx.compose.foundation.BorderStroke? border, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
     method @Deprecated @androidx.compose.runtime.Composable public void ExposedDropdownMenu(boolean expanded, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.ScrollState scrollState, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
-    method public abstract androidx.compose.ui.Modifier exposedDropdownSize(androidx.compose.ui.Modifier, optional boolean matchTextFieldWidth);
+    method public abstract androidx.compose.ui.Modifier exposedDropdownSize(androidx.compose.ui.Modifier, optional boolean matchAnchorWidth);
     method @Deprecated public final androidx.compose.ui.Modifier menuAnchor(androidx.compose.ui.Modifier);
     method public abstract androidx.compose.ui.Modifier menuAnchor(androidx.compose.ui.Modifier, String type, optional boolean enabled);
   }
@@ -882,6 +898,13 @@
     method @androidx.compose.runtime.Composable public androidx.compose.material3.IconToggleButtonColors filledTonalIconToggleButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor, optional long checkedContainerColor, optional long checkedContentColor);
     method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getFilledShape();
     method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getOutlinedShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getRoundShape();
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi public long getSmallContainerSize();
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi public float getSmallIconSize();
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi public long getSmallNarrowContainerSize();
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi public long getSmallWideContainerSize();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getSquareShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getStandardShape();
     method @androidx.compose.runtime.Composable public androidx.compose.material3.IconButtonColors iconButtonColors();
     method @androidx.compose.runtime.Composable public androidx.compose.material3.IconButtonColors iconButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
     method @androidx.compose.runtime.Composable public androidx.compose.material3.IconToggleButtonColors iconToggleButtonColors();
@@ -892,8 +915,15 @@
     method @androidx.compose.runtime.Composable public androidx.compose.foundation.BorderStroke? outlinedIconToggleButtonBorder(boolean enabled, boolean checked);
     method @androidx.compose.runtime.Composable public androidx.compose.material3.IconToggleButtonColors outlinedIconToggleButtonColors();
     method @androidx.compose.runtime.Composable public androidx.compose.material3.IconToggleButtonColors outlinedIconToggleButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor, optional long checkedContainerColor, optional long checkedContentColor);
+    property @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi public final long SmallContainerSize;
+    property @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi public final float SmallIconSize;
+    property @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi public final long SmallNarrowContainerSize;
+    property @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi public final long SmallWideContainerSize;
     property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape filledShape;
     property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape outlinedShape;
+    property @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape roundShape;
+    property @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape squareShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape standardShape;
     field public static final androidx.compose.material3.IconButtonDefaults INSTANCE;
   }
 
@@ -902,8 +932,10 @@
     method @androidx.compose.runtime.Composable public static void FilledIconToggleButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.IconToggleButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
     method @androidx.compose.runtime.Composable public static void FilledTonalIconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
     method @androidx.compose.runtime.Composable public static void FilledTonalIconToggleButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.IconToggleButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
-    method @androidx.compose.runtime.Composable public static void IconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
-    method @androidx.compose.runtime.Composable public static void IconToggleButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.material3.IconToggleButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void IconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, optional androidx.compose.ui.graphics.Shape shape, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @Deprecated @androidx.compose.runtime.Composable public static void IconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void IconToggleButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.material3.IconToggleButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, optional androidx.compose.ui.graphics.Shape shape, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @Deprecated @androidx.compose.runtime.Composable public static void IconToggleButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.material3.IconToggleButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
     method @androidx.compose.runtime.Composable public static void OutlinedIconButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.IconButtonColors colors, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
     method @androidx.compose.runtime.Composable public static void OutlinedIconToggleButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.IconToggleButtonColors colors, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
   }
@@ -999,6 +1031,113 @@
     method @androidx.compose.runtime.Composable public static void ListItem(kotlin.jvm.functions.Function0<kotlin.Unit> headlineContent, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? overlineContent, optional kotlin.jvm.functions.Function0<kotlin.Unit>? supportingContent, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingContent, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingContent, optional androidx.compose.material3.ListItemColors colors, optional float tonalElevation, optional float shadowElevation);
   }
 
+  @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi public final class LoadingIndicatorDefaults {
+    method @androidx.compose.runtime.Composable public long getContainerColor();
+    method public float getContainerHeight();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getContainerShape();
+    method public float getContainerWidth();
+    method public java.util.List<androidx.graphics.shapes.RoundedPolygon> getDeterminateIndicatorPolygons();
+    method public java.util.List<androidx.graphics.shapes.RoundedPolygon> getIndeterminateIndicatorPolygons();
+    method @androidx.compose.runtime.Composable public long getIndicatorColor();
+    method public float getIndicatorSize();
+    property @androidx.compose.runtime.Composable public final long ContainerColor;
+    property public final float ContainerHeight;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape ContainerShape;
+    property public final float ContainerWidth;
+    property public final java.util.List<androidx.graphics.shapes.RoundedPolygon> DeterminateIndicatorPolygons;
+    property public final java.util.List<androidx.graphics.shapes.RoundedPolygon> IndeterminateIndicatorPolygons;
+    property @androidx.compose.runtime.Composable public final long IndicatorColor;
+    property public final float IndicatorSize;
+    field public static final androidx.compose.material3.LoadingIndicatorDefaults INSTANCE;
+  }
+
+  public final class LoadingIndicatorKt {
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public static void LoadingIndicator(optional androidx.compose.ui.Modifier modifier, optional long containerColor, optional long indicatorColor, optional androidx.compose.ui.graphics.Shape containerShape, optional java.util.List<androidx.graphics.shapes.RoundedPolygon> indicatorPolygons);
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public static void LoadingIndicator(kotlin.jvm.functions.Function0<java.lang.Float> progress, optional androidx.compose.ui.Modifier modifier, optional long containerColor, optional long indicatorColor, optional androidx.compose.ui.graphics.Shape containerShape, optional java.util.List<androidx.graphics.shapes.RoundedPolygon> indicatorPolygons);
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi public abstract sealed class MaterialShapes {
+    field public static final androidx.compose.material3.MaterialShapes.Companion Companion;
+  }
+
+  public static final class MaterialShapes.Companion {
+    method public androidx.graphics.shapes.RoundedPolygon getArch();
+    method public androidx.graphics.shapes.RoundedPolygon getArrow();
+    method public androidx.graphics.shapes.RoundedPolygon getBoom();
+    method public androidx.graphics.shapes.RoundedPolygon getBun();
+    method public androidx.graphics.shapes.RoundedPolygon getBurst();
+    method public androidx.graphics.shapes.RoundedPolygon getCircle();
+    method public androidx.graphics.shapes.RoundedPolygon getClamShell();
+    method public androidx.graphics.shapes.RoundedPolygon getClover4Leaf();
+    method public androidx.graphics.shapes.RoundedPolygon getClover8Leaf();
+    method public androidx.graphics.shapes.RoundedPolygon getCookie12Sided();
+    method public androidx.graphics.shapes.RoundedPolygon getCookie4Sided();
+    method public androidx.graphics.shapes.RoundedPolygon getCookie6Sided();
+    method public androidx.graphics.shapes.RoundedPolygon getCookie7Sided();
+    method public androidx.graphics.shapes.RoundedPolygon getCookie9Sided();
+    method public androidx.graphics.shapes.RoundedPolygon getDiamond();
+    method public androidx.graphics.shapes.RoundedPolygon getFan();
+    method public androidx.graphics.shapes.RoundedPolygon getFlower();
+    method public androidx.graphics.shapes.RoundedPolygon getGem();
+    method public androidx.graphics.shapes.RoundedPolygon getGhostish();
+    method public androidx.graphics.shapes.RoundedPolygon getHeart();
+    method public androidx.graphics.shapes.RoundedPolygon getOval();
+    method public androidx.graphics.shapes.RoundedPolygon getPentagon();
+    method public androidx.graphics.shapes.RoundedPolygon getPill();
+    method public androidx.graphics.shapes.RoundedPolygon getPixelCircle();
+    method public androidx.graphics.shapes.RoundedPolygon getPixelTriangle();
+    method public androidx.graphics.shapes.RoundedPolygon getPuffy();
+    method public androidx.graphics.shapes.RoundedPolygon getPuffyDiamond();
+    method public androidx.graphics.shapes.RoundedPolygon getSemiCircle();
+    method public androidx.graphics.shapes.RoundedPolygon getSlanted();
+    method public androidx.graphics.shapes.RoundedPolygon getSoftBoom();
+    method public androidx.graphics.shapes.RoundedPolygon getSoftBurst();
+    method public androidx.graphics.shapes.RoundedPolygon getSquare();
+    method public androidx.graphics.shapes.RoundedPolygon getSunny();
+    method public androidx.graphics.shapes.RoundedPolygon getTriangle();
+    method public androidx.graphics.shapes.RoundedPolygon getVerySunny();
+    property public final androidx.graphics.shapes.RoundedPolygon Arch;
+    property public final androidx.graphics.shapes.RoundedPolygon Arrow;
+    property public final androidx.graphics.shapes.RoundedPolygon Boom;
+    property public final androidx.graphics.shapes.RoundedPolygon Bun;
+    property public final androidx.graphics.shapes.RoundedPolygon Burst;
+    property public final androidx.graphics.shapes.RoundedPolygon Circle;
+    property public final androidx.graphics.shapes.RoundedPolygon ClamShell;
+    property public final androidx.graphics.shapes.RoundedPolygon Clover4Leaf;
+    property public final androidx.graphics.shapes.RoundedPolygon Clover8Leaf;
+    property public final androidx.graphics.shapes.RoundedPolygon Cookie12Sided;
+    property public final androidx.graphics.shapes.RoundedPolygon Cookie4Sided;
+    property public final androidx.graphics.shapes.RoundedPolygon Cookie6Sided;
+    property public final androidx.graphics.shapes.RoundedPolygon Cookie7Sided;
+    property public final androidx.graphics.shapes.RoundedPolygon Cookie9Sided;
+    property public final androidx.graphics.shapes.RoundedPolygon Diamond;
+    property public final androidx.graphics.shapes.RoundedPolygon Fan;
+    property public final androidx.graphics.shapes.RoundedPolygon Flower;
+    property public final androidx.graphics.shapes.RoundedPolygon Gem;
+    property public final androidx.graphics.shapes.RoundedPolygon Ghostish;
+    property public final androidx.graphics.shapes.RoundedPolygon Heart;
+    property public final androidx.graphics.shapes.RoundedPolygon Oval;
+    property public final androidx.graphics.shapes.RoundedPolygon Pentagon;
+    property public final androidx.graphics.shapes.RoundedPolygon Pill;
+    property public final androidx.graphics.shapes.RoundedPolygon PixelCircle;
+    property public final androidx.graphics.shapes.RoundedPolygon PixelTriangle;
+    property public final androidx.graphics.shapes.RoundedPolygon Puffy;
+    property public final androidx.graphics.shapes.RoundedPolygon PuffyDiamond;
+    property public final androidx.graphics.shapes.RoundedPolygon SemiCircle;
+    property public final androidx.graphics.shapes.RoundedPolygon Slanted;
+    property public final androidx.graphics.shapes.RoundedPolygon SoftBoom;
+    property public final androidx.graphics.shapes.RoundedPolygon SoftBurst;
+    property public final androidx.graphics.shapes.RoundedPolygon Square;
+    property public final androidx.graphics.shapes.RoundedPolygon Sunny;
+    property public final androidx.graphics.shapes.RoundedPolygon Triangle;
+    property public final androidx.graphics.shapes.RoundedPolygon VerySunny;
+  }
+
+  public final class MaterialShapesKt {
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public static androidx.compose.ui.graphics.Path toPath(androidx.graphics.shapes.RoundedPolygon, optional int startAngle);
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public static androidx.compose.ui.graphics.Shape toShape(androidx.graphics.shapes.RoundedPolygon, optional int startAngle);
+  }
+
   public final class MaterialTheme {
     method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.compose.material3.ColorScheme getColorScheme();
     method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.compose.material3.Shapes getShapes();
@@ -1014,19 +1153,6 @@
     method @androidx.compose.runtime.Composable public static void MaterialTheme(optional androidx.compose.material3.ColorScheme colorScheme, optional androidx.compose.material3.Shapes shapes, optional androidx.compose.material3.Typography typography, kotlin.jvm.functions.Function0<kotlin.Unit> content);
   }
 
-  @kotlin.jvm.JvmInline public final value class MenuAnchorType {
-    field public static final androidx.compose.material3.MenuAnchorType.Companion Companion;
-  }
-
-  public static final class MenuAnchorType.Companion {
-    method public String getPrimaryEditable();
-    method public String getPrimaryNotEditable();
-    method public String getSecondaryEditable();
-    property public final String PrimaryEditable;
-    property public final String PrimaryNotEditable;
-    property public final String SecondaryEditable;
-  }
-
   public final class MenuDefaults {
     method @androidx.compose.runtime.Composable public long getContainerColor();
     method public androidx.compose.foundation.layout.PaddingValues getDropdownMenuItemContentPadding();
@@ -2223,8 +2349,12 @@
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarScrollBehavior exitUntilCollapsedScrollBehavior(optional androidx.compose.material3.TopAppBarState state, optional kotlin.jvm.functions.Function0<java.lang.Boolean> canScroll, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float>? snapAnimationSpec, optional androidx.compose.animation.core.DecayAnimationSpec<java.lang.Float>? flingAnimationSpec);
     method public float getLargeAppBarCollapsedHeight();
     method public float getLargeAppBarExpandedHeight();
+    method public float getLargeAppBarWithSubtitleExpandedHeight();
+    method public float getLargeAppBarWithoutSubtitleExpandedHeight();
     method public float getMediumAppBarCollapsedHeight();
     method public float getMediumAppBarExpandedHeight();
+    method public float getMediumAppBarWithSubtitleExpandedHeight();
+    method public float getMediumAppBarWithoutSubtitleExpandedHeight();
     method public float getTopAppBarExpandedHeight();
     method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
     method @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors largeTopAppBarColors();
@@ -2236,8 +2366,12 @@
     method @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors topAppBarColors(optional long containerColor, optional long scrolledContainerColor, optional long navigationIconContentColor, optional long titleContentColor, optional long actionIconContentColor);
     property public final float LargeAppBarCollapsedHeight;
     property public final float LargeAppBarExpandedHeight;
+    property public final float LargeAppBarWithSubtitleExpandedHeight;
+    property public final float LargeAppBarWithoutSubtitleExpandedHeight;
     property public final float MediumAppBarCollapsedHeight;
     property public final float MediumAppBarExpandedHeight;
+    property public final float MediumAppBarWithSubtitleExpandedHeight;
+    property public final float MediumAppBarWithoutSubtitleExpandedHeight;
     property public final float TopAppBarExpandedHeight;
     property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets windowInsets;
     field public static final androidx.compose.material3.TopAppBarDefaults INSTANCE;
@@ -2279,6 +2413,19 @@
     property public final androidx.compose.runtime.saveable.Saver<androidx.compose.material3.TopAppBarState,? extends java.lang.Object?> Saver;
   }
 
+  @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @kotlin.jvm.JvmInline public final value class TopAppBarTitleAlignment {
+    field public static final androidx.compose.material3.TopAppBarTitleAlignment.Companion Companion;
+  }
+
+  public static final class TopAppBarTitleAlignment.Companion {
+    method public int getCenter();
+    method public int getEnd();
+    method public int getStart();
+    property public final int Center;
+    property public final int End;
+    property public final int Start;
+  }
+
   @androidx.compose.runtime.Immutable public final class Typography {
     ctor public Typography(optional androidx.compose.ui.text.TextStyle displayLarge, optional androidx.compose.ui.text.TextStyle displayMedium, optional androidx.compose.ui.text.TextStyle displaySmall, optional androidx.compose.ui.text.TextStyle headlineLarge, optional androidx.compose.ui.text.TextStyle headlineMedium, optional androidx.compose.ui.text.TextStyle headlineSmall, optional androidx.compose.ui.text.TextStyle titleLarge, optional androidx.compose.ui.text.TextStyle titleMedium, optional androidx.compose.ui.text.TextStyle titleSmall, optional androidx.compose.ui.text.TextStyle bodyLarge, optional androidx.compose.ui.text.TextStyle bodyMedium, optional androidx.compose.ui.text.TextStyle bodySmall, optional androidx.compose.ui.text.TextStyle labelLarge, optional androidx.compose.ui.text.TextStyle labelMedium, optional androidx.compose.ui.text.TextStyle labelSmall);
     method public androidx.compose.material3.Typography copy(optional androidx.compose.ui.text.TextStyle displayLarge, optional androidx.compose.ui.text.TextStyle displayMedium, optional androidx.compose.ui.text.TextStyle displaySmall, optional androidx.compose.ui.text.TextStyle headlineLarge, optional androidx.compose.ui.text.TextStyle headlineMedium, optional androidx.compose.ui.text.TextStyle headlineSmall, optional androidx.compose.ui.text.TextStyle titleLarge, optional androidx.compose.ui.text.TextStyle titleMedium, optional androidx.compose.ui.text.TextStyle titleSmall, optional androidx.compose.ui.text.TextStyle bodyLarge, optional androidx.compose.ui.text.TextStyle bodyMedium, optional androidx.compose.ui.text.TextStyle bodySmall, optional androidx.compose.ui.text.TextStyle labelLarge, optional androidx.compose.ui.text.TextStyle labelMedium, optional androidx.compose.ui.text.TextStyle labelSmall);
@@ -2324,11 +2471,12 @@
     method @androidx.compose.runtime.Composable public long getIndicatorColor();
     method public float getLinearContainerHeight();
     method public float getLinearContainerWidth();
+    method public float getLinearDeterminateWavelength();
+    method public float getLinearIndeterminateWavelength();
     method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.drawscope.Stroke getLinearIndicatorStroke();
     method public float getLinearIndicatorTrackGapSize();
     method public float getLinearTrackStopIndicatorSize();
     method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.drawscope.Stroke getLinearTrackStroke();
-    method public float getLinearWavelength();
     method public androidx.compose.animation.core.AnimationSpec<java.lang.Float> getProgressAnimationSpec();
     method @androidx.compose.runtime.Composable public long getTrackColor();
     property public final float CircularContainerSize;
@@ -2336,9 +2484,10 @@
     property public final float CircularWavelength;
     property public final float LinearContainerHeight;
     property public final float LinearContainerWidth;
+    property public final float LinearDeterminateWavelength;
+    property public final float LinearIndeterminateWavelength;
     property public final float LinearIndicatorTrackGapSize;
     property public final float LinearTrackStopIndicatorSize;
-    property public final float LinearWavelength;
     property public final androidx.compose.animation.core.AnimationSpec<java.lang.Float> ProgressAnimationSpec;
     property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.drawscope.Stroke circularIndicatorStroke;
     property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.drawscope.Stroke circularTrackStroke;
@@ -2421,15 +2570,20 @@
   @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public final class PullToRefreshDefaults {
     method @androidx.compose.runtime.Composable public void Indicator(androidx.compose.material3.pulltorefresh.PullToRefreshState state, boolean isRefreshing, optional androidx.compose.ui.Modifier modifier, optional long containerColor, optional long color, optional float threshold);
     method @androidx.compose.runtime.Composable public void IndicatorBox(androidx.compose.material3.pulltorefresh.PullToRefreshState state, boolean isRefreshing, optional androidx.compose.ui.Modifier modifier, optional float threshold, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional float elevation, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
-    method @androidx.compose.runtime.Composable public long getContainerColor();
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public void LoadingIndicator(androidx.compose.material3.pulltorefresh.PullToRefreshState state, boolean isRefreshing, optional androidx.compose.ui.Modifier modifier, optional long containerColor, optional long color, optional float elevation, optional float threshold);
+    method @Deprecated @androidx.compose.runtime.Composable public long getContainerColor();
     method public float getElevation();
-    method @androidx.compose.runtime.Composable public long getIndicatorColor();
+    method @Deprecated @androidx.compose.runtime.Composable public long getIndicatorColor();
+    method @androidx.compose.runtime.Composable public long getLoadingIndicatorColor();
+    method @androidx.compose.runtime.Composable public long getLoadingIndicatorContainerColor();
     method public float getPositionalThreshold();
     method public androidx.compose.ui.graphics.Shape getShape();
     property public final float Elevation;
     property public final float PositionalThreshold;
-    property @androidx.compose.runtime.Composable public final long containerColor;
-    property @androidx.compose.runtime.Composable public final long indicatorColor;
+    property @Deprecated @androidx.compose.runtime.Composable public final long containerColor;
+    property @Deprecated @androidx.compose.runtime.Composable public final long indicatorColor;
+    property @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public final long loadingIndicatorColor;
+    property @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public final long loadingIndicatorContainerColor;
     property public final androidx.compose.ui.graphics.Shape shape;
     field public static final androidx.compose.material3.pulltorefresh.PullToRefreshDefaults INSTANCE;
   }
diff --git a/compose/material3/material3/build.gradle b/compose/material3/material3/build.gradle
index 6445364..07129e1 100644
--- a/compose/material3/material3/build.gradle
+++ b/compose/material3/material3/build.gradle
@@ -32,14 +32,14 @@
 
 androidXMultiplatform {
     android()
-    desktop()
+    jvmStubs()
 
     defaultPlatform(PlatformIdentifier.ANDROID)
 
     sourceSets {
         commonMain {
             dependencies {
-                implementation(libs.kotlinStdlibCommon)
+                implementation(libs.kotlinStdlib)
                 // Keep pinned unless there is a need for tip of tree behavior
                 implementation("androidx.collection:collection:1.4.0")
                 implementation("androidx.compose.animation:animation-core:1.6.0")
@@ -66,12 +66,6 @@
             }
         }
 
-        skikoMain {
-            dependsOn(commonMain)
-            dependencies {
-            }
-        }
-
         androidMain {
             dependsOn(jvmMain)
             dependencies {
@@ -83,22 +77,14 @@
             }
         }
 
-        desktopMain {
-            dependsOn(skikoMain)
+        jvmStubsMain {
             dependsOn(jvmMain)
             dependencies {
-                implementation(libs.kotlinStdlib)
-            }
-        }
-
-        jvmTest {
-            dependsOn(commonTest)
-            dependencies {
             }
         }
 
         androidUnitTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(libs.testRules)
                 implementation(libs.testRunner)
@@ -108,7 +94,7 @@
         }
 
         androidInstrumentedTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(project(":compose:material3:material3:material3-samples"))
                 implementation(project(":compose:test-utils"))
@@ -124,16 +110,6 @@
                 implementation(libs.testUiautomator)
             }
         }
-
-        desktopTest {
-            dependsOn(jvmTest)
-            dependencies {
-                implementation(project(":compose:ui:ui-test-junit4"))
-                implementation(libs.truth)
-                implementation(libs.junit)
-                implementation(libs.skikoCurrentOs)
-            }
-        }
     }
 }
 
diff --git a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Components.kt b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Components.kt
index 74706e9..37555f9 100644
--- a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Components.kt
+++ b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Components.kt
@@ -262,6 +262,22 @@
         sourceUrl = "$Material3SourceUrl/ListItem.kt",
         examples = ListsExamples,
     )
+
+private val LoadingIndicators =
+    Component(
+        id = nextId(),
+        name = "Loading indicators",
+        description =
+            "Loading indicators express an unspecified wait time or display the length of " +
+                "a loading process.",
+        // No loading indicator icon
+        guidelinesUrl = "$ComponentGuidelinesUrl/loading-indicators",
+        tintIcon = true,
+        docsUrl = "$PackageSummaryUrl#loadingindicator",
+        sourceUrl = "$Material3SourceUrl/LoadingIndicator.kt",
+        examples = LoadingIndicatorsExamples,
+    )
+
 private val Menus =
     Component(
         id = nextId(),
@@ -528,6 +544,7 @@
         FloatingAppBars,
         IconButtons,
         Lists,
+        LoadingIndicators,
         Menus,
         NavigationBar,
         NavigationDrawer,
diff --git a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Examples.kt b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Examples.kt
index 6741b9e..3d68f05 100644
--- a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Examples.kt
+++ b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Examples.kt
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-@file:Suppress("COMPOSABLE_FUNCTION_REFERENCE")
-
 package androidx.compose.material3.catalog.library.model
 
 import androidx.compose.foundation.layout.Box
@@ -54,6 +52,7 @@
 import androidx.compose.material3.samples.DatePickerSample
 import androidx.compose.material3.samples.DatePickerWithDateSelectableDatesSample
 import androidx.compose.material3.samples.DateRangePickerSample
+import androidx.compose.material3.samples.DeterminateLoadingIndicatorSample
 import androidx.compose.material3.samples.DismissibleNavigationDrawerSample
 import androidx.compose.material3.samples.DockedSearchBarSample
 import androidx.compose.material3.samples.EditableExposedDropdownMenuSample
@@ -65,6 +64,8 @@
 import androidx.compose.material3.samples.ElevatedSuggestionChipSample
 import androidx.compose.material3.samples.EnterAlwaysTopAppBar
 import androidx.compose.material3.samples.ExitAlwaysBottomAppBar
+import androidx.compose.material3.samples.ExitUntilCollapsedCenterAlignedLargeTopAppBarWithSubtitle
+import androidx.compose.material3.samples.ExitUntilCollapsedCenterAlignedMediumTopAppBarWithSubtitle
 import androidx.compose.material3.samples.ExitUntilCollapsedLargeTopAppBar
 import androidx.compose.material3.samples.ExitUntilCollapsedMediumTopAppBar
 import androidx.compose.material3.samples.ExposedDropdownMenuSample
@@ -98,6 +99,8 @@
 import androidx.compose.material3.samples.LeadingIconTabs
 import androidx.compose.material3.samples.LinearProgressIndicatorSample
 import androidx.compose.material3.samples.LinearWavyProgressIndicatorSample
+import androidx.compose.material3.samples.LoadingIndicatorPullToRefreshSample
+import androidx.compose.material3.samples.LoadingIndicatorSample
 import androidx.compose.material3.samples.MenuSample
 import androidx.compose.material3.samples.MenuWithScrollStateSample
 import androidx.compose.material3.samples.ModalBottomSheetSample
@@ -129,6 +132,7 @@
 import androidx.compose.material3.samples.PullToRefreshSampleCustomState
 import androidx.compose.material3.samples.PullToRefreshScalingSample
 import androidx.compose.material3.samples.PullToRefreshViewModelSample
+import androidx.compose.material3.samples.PullToRefreshWithLoadingIndicatorSample
 import androidx.compose.material3.samples.RadioButtonSample
 import androidx.compose.material3.samples.RadioGroupSample
 import androidx.compose.material3.samples.RangeSliderSample
@@ -155,9 +159,11 @@
 import androidx.compose.material3.samples.SimpleBottomAppBar
 import androidx.compose.material3.samples.SimpleBottomSheetScaffoldSample
 import androidx.compose.material3.samples.SimpleCenterAlignedTopAppBar
+import androidx.compose.material3.samples.SimpleCenterAlignedTopAppBarWithSubtitle
 import androidx.compose.material3.samples.SimpleOutlinedTextFieldSample
 import androidx.compose.material3.samples.SimpleTextFieldSample
 import androidx.compose.material3.samples.SimpleTopAppBar
+import androidx.compose.material3.samples.SimpleTopAppBarWithSubtitle
 import androidx.compose.material3.samples.SliderSample
 import androidx.compose.material3.samples.SliderWithCustomThumbSample
 import androidx.compose.material3.samples.SliderWithCustomTrackAndThumb
@@ -206,21 +212,21 @@
 val AdaptiveExamples =
     listOf(
         Example(
-            name = ::ListDetailPaneScaffoldSample.name,
+            name = "ListDetailPaneScaffoldSample",
             description = AdaptiveExampleDescription,
             sourceUrl = AdaptiveExampleSourceUrl
         ) {
             ListDetailPaneScaffoldSample()
         },
         Example(
-            name = ::ListDetailPaneScaffoldSampleWithExtraPane.name,
+            name = "ListDetailPaneScaffoldSampleWithExtraPane",
             description = AdaptiveExampleDescription,
             sourceUrl = AdaptiveExampleSourceUrl
         ) {
             ListDetailPaneScaffoldSampleWithExtraPane()
         },
         Example(
-            name = ::ListDetailPaneScaffoldWithNavigationSample.name,
+            name = "ListDetailPaneScaffoldWithNavigationSample",
             description = AdaptiveExampleDescription,
             sourceUrl = AdaptiveExampleSourceUrl
         ) {
@@ -233,7 +239,7 @@
 val BadgeExamples =
     listOf(
         Example(
-            name = ::NavigationBarItemWithBadge.name,
+            name = "NavigationBarItemWithBadge",
             description = BadgeExampleDescription,
             sourceUrl = BadgeExampleSourceUrl
         ) {
@@ -246,21 +252,21 @@
 val BottomSheetExamples =
     listOf(
         Example(
-            name = ::ModalBottomSheetSample.name,
+            name = "ModalBottomSheetSample",
             description = BottomSheetExampleDescription,
             sourceUrl = BottomSheetExampleSourceUrl
         ) {
             ModalBottomSheetSample()
         },
         Example(
-            name = ::SimpleBottomSheetScaffoldSample.name,
+            name = "SimpleBottomSheetScaffoldSample",
             description = BottomSheetExampleDescription,
             sourceUrl = BottomSheetExampleSourceUrl
         ) {
             SimpleBottomSheetScaffoldSample()
         },
         Example(
-            name = ::BottomSheetScaffoldNestedScrollSample.name,
+            name = "BottomSheetScaffoldNestedScrollSample",
             description = BottomSheetExampleDescription,
             sourceUrl = BottomSheetExampleSourceUrl
         ) {
@@ -273,42 +279,42 @@
 val ButtonsExamples =
     listOf(
         Example(
-            name = ::ButtonSample.name,
+            name = "ButtonSample",
             description = ButtonsExampleDescription,
             sourceUrl = ButtonsExampleSourceUrl,
         ) {
             ButtonSample()
         },
         Example(
-            name = ::ElevatedButtonSample.name,
+            name = "ElevatedButtonSample",
             description = ButtonsExampleDescription,
             sourceUrl = ButtonsExampleSourceUrl,
         ) {
             ElevatedButtonSample()
         },
         Example(
-            name = ::FilledTonalButtonSample.name,
+            name = "FilledTonalButtonSample",
             description = ButtonsExampleDescription,
             sourceUrl = ButtonsExampleSourceUrl,
         ) {
             FilledTonalButtonSample()
         },
         Example(
-            name = ::OutlinedButtonSample.name,
+            name = "OutlinedButtonSample",
             description = ButtonsExampleDescription,
             sourceUrl = ButtonsExampleSourceUrl,
         ) {
             OutlinedButtonSample()
         },
         Example(
-            name = ::TextButtonSample.name,
+            name = "TextButtonSample",
             description = ButtonsExampleDescription,
             sourceUrl = ButtonsExampleSourceUrl,
         ) {
             TextButtonSample()
         },
         Example(
-            name = ::ButtonWithIconSample.name,
+            name = "ButtonWithIconSample",
             description = ButtonsExampleDescription,
             sourceUrl = ButtonsExampleSourceUrl,
         ) {
@@ -321,42 +327,42 @@
 val CardExamples =
     listOf(
         Example(
-            name = ::CardSample.name,
+            name = "CardSample",
             description = CardsExampleDescription,
             sourceUrl = CardsExampleSourceUrl
         ) {
             CardSample()
         },
         Example(
-            name = ::ClickableCardSample.name,
+            name = "ClickableCardSample",
             description = CardsExampleDescription,
             sourceUrl = CardsExampleSourceUrl
         ) {
             ClickableCardSample()
         },
         Example(
-            name = ::ElevatedCardSample.name,
+            name = "ElevatedCardSample",
             description = CardsExampleDescription,
             sourceUrl = CardsExampleSourceUrl
         ) {
             ElevatedCardSample()
         },
         Example(
-            name = ::ClickableElevatedCardSample.name,
+            name = "ClickableElevatedCardSample",
             description = CardsExampleDescription,
             sourceUrl = CardsExampleSourceUrl
         ) {
             ClickableElevatedCardSample()
         },
         Example(
-            name = ::OutlinedCardSample.name,
+            name = "OutlinedCardSample",
             description = CardsExampleDescription,
             sourceUrl = CardsExampleSourceUrl
         ) {
             OutlinedCardSample()
         },
         Example(
-            name = ::ClickableOutlinedCardSample.name,
+            name = "ClickableOutlinedCardSample",
             description = CardsExampleDescription,
             sourceUrl = CardsExampleSourceUrl
         ) {
@@ -369,21 +375,21 @@
 val CarouselExamples =
     listOf(
         Example(
-            name = ::HorizontalMultiBrowseCarouselSample.name,
+            name = "HorizontalMultiBrowseCarouselSample",
             description = CarouselExampleDescription,
             sourceUrl = CarouselExampleSourceUrl
         ) {
             HorizontalMultiBrowseCarouselSample()
         },
         Example(
-            name = ::HorizontalUncontainedCarouselSample.name,
+            name = "HorizontalUncontainedCarouselSample",
             description = CarouselExampleDescription,
             sourceUrl = CarouselExampleSourceUrl
         ) {
             HorizontalUncontainedCarouselSample()
         },
         Example(
-            name = ::FadingHorizontalMultiBrowseCarouselSample.name,
+            name = "FadingHorizontalMultiBrowseCarouselSample",
             description = CarouselExampleDescription,
             sourceUrl = CarouselExampleSourceUrl
         ) {
@@ -396,21 +402,21 @@
 val CheckboxesExamples =
     listOf(
         Example(
-            name = ::CheckboxSample.name,
+            name = "CheckboxSample",
             description = CheckboxesExampleDescription,
             sourceUrl = CheckboxesExampleSourceUrl
         ) {
             CheckboxSample()
         },
         Example(
-            name = ::CheckboxWithTextSample.name,
+            name = "CheckboxWithTextSample",
             description = CheckboxesExampleDescription,
             sourceUrl = CheckboxesExampleSourceUrl
         ) {
             CheckboxWithTextSample()
         },
         Example(
-            name = ::TriStateCheckboxSample.name,
+            name = "TriStateCheckboxSample",
             description = CheckboxesExampleDescription,
             sourceUrl = CheckboxesExampleSourceUrl
         ) {
@@ -423,77 +429,77 @@
 val ChipsExamples =
     listOf(
         Example(
-            name = ::AssistChipSample.name,
+            name = "AssistChipSample",
             description = ChipsExampleDescription,
             sourceUrl = ChipsExampleSourceUrl
         ) {
             AssistChipSample()
         },
         Example(
-            name = ::ElevatedAssistChipSample.name,
+            name = "ElevatedAssistChipSample",
             description = ChipsExampleDescription,
             sourceUrl = ChipsExampleSourceUrl
         ) {
             ElevatedAssistChipSample()
         },
         Example(
-            name = ::FilterChipSample.name,
+            name = "FilterChipSample",
             description = ChipsExampleDescription,
             sourceUrl = ChipsExampleSourceUrl
         ) {
             FilterChipSample()
         },
         Example(
-            name = ::ElevatedFilterChipSample.name,
+            name = "ElevatedFilterChipSample",
             description = ChipsExampleDescription,
             sourceUrl = ChipsExampleSourceUrl
         ) {
             ElevatedFilterChipSample()
         },
         Example(
-            name = ::FilterChipWithLeadingIconSample.name,
+            name = "FilterChipWithLeadingIconSample",
             description = ChipsExampleDescription,
             sourceUrl = ChipsExampleSourceUrl
         ) {
             FilterChipWithLeadingIconSample()
         },
         Example(
-            name = ::InputChipSample.name,
+            name = "InputChipSample",
             description = ChipsExampleDescription,
             sourceUrl = ChipsExampleSourceUrl
         ) {
             InputChipSample()
         },
         Example(
-            name = ::InputChipWithAvatarSample.name,
+            name = "InputChipWithAvatarSample",
             description = ChipsExampleDescription,
             sourceUrl = ChipsExampleSourceUrl
         ) {
             InputChipWithAvatarSample()
         },
         Example(
-            name = ::SuggestionChipSample.name,
+            name = "SuggestionChipSample",
             description = ChipsExampleDescription,
             sourceUrl = ChipsExampleSourceUrl
         ) {
             SuggestionChipSample()
         },
         Example(
-            name = ::ElevatedSuggestionChipSample.name,
+            name = "ElevatedSuggestionChipSample",
             description = ChipsExampleDescription,
             sourceUrl = ChipsExampleSourceUrl
         ) {
             ElevatedSuggestionChipSample()
         },
         Example(
-            name = ::ChipGroupSingleLineSample.name,
+            name = "ChipGroupSingleLineSample",
             description = ChipsExampleDescription,
             sourceUrl = ChipsExampleSourceUrl
         ) {
             ChipGroupSingleLineSample()
         },
         Example(
-            name = ::ChipGroupReflowSample.name,
+            name = "ChipGroupReflowSample",
             description = ChipsExampleDescription,
             sourceUrl = ChipsExampleSourceUrl
         ) {
@@ -506,35 +512,35 @@
 val DatePickerExamples =
     listOf(
         Example(
-            name = ::DatePickerSample.name,
+            name = "DatePickerSample",
             description = DatePickerExampleDescription,
             sourceUrl = DatePickerExampleSourceUrl
         ) {
             DatePickerSample()
         },
         Example(
-            name = ::DatePickerDialogSample.name,
+            name = "DatePickerDialogSample",
             description = DatePickerExampleDescription,
             sourceUrl = DatePickerExampleSourceUrl
         ) {
             DatePickerDialogSample()
         },
         Example(
-            name = ::DatePickerWithDateSelectableDatesSample.name,
+            name = "DatePickerWithDateSelectableDatesSample",
             description = DatePickerExampleDescription,
             sourceUrl = DatePickerExampleSourceUrl
         ) {
             DatePickerWithDateSelectableDatesSample()
         },
         Example(
-            name = ::DateInputSample.name,
+            name = "DateInputSample",
             description = DatePickerExampleDescription,
             sourceUrl = DatePickerExampleSourceUrl
         ) {
             DateInputSample()
         },
         Example(
-            name = ::DateRangePickerSample.name,
+            name = "DateRangePickerSample",
             description = DatePickerExampleDescription,
             sourceUrl = DatePickerExampleSourceUrl
         ) {
@@ -547,21 +553,21 @@
 val DialogExamples =
     listOf(
         Example(
-            name = ::AlertDialogSample.name,
+            name = "AlertDialogSample",
             description = DialogExampleDescription,
             sourceUrl = DialogExampleSourceUrl,
         ) {
             AlertDialogSample()
         },
         Example(
-            name = ::AlertDialogWithIconSample.name,
+            name = "AlertDialogWithIconSample",
             description = DialogExampleDescription,
             sourceUrl = DialogExampleSourceUrl,
         ) {
             AlertDialogWithIconSample()
         },
         Example(
-            name = ::BasicAlertDialogSample.name,
+            name = "BasicAlertDialogSample",
             description = DialogExampleDescription,
             sourceUrl = DialogExampleSourceUrl,
         ) {
@@ -574,21 +580,21 @@
 val BottomAppBarsExamples =
     listOf(
         Example(
-            name = ::SimpleBottomAppBar.name,
+            name = "SimpleBottomAppBar",
             description = BottomAppBarsExampleDescription,
             sourceUrl = BottomAppBarsExampleSourceUrl,
         ) {
             SimpleBottomAppBar()
         },
         Example(
-            name = ::BottomAppBarWithFAB.name,
+            name = "BottomAppBarWithFAB",
             description = BottomAppBarsExampleDescription,
             sourceUrl = BottomAppBarsExampleSourceUrl,
         ) {
             BottomAppBarWithFAB()
         },
         Example(
-            name = ::ExitAlwaysBottomAppBar.name,
+            name = "ExitAlwaysBottomAppBar",
             description = BottomAppBarsExampleDescription,
             sourceUrl = BottomAppBarsExampleSourceUrl,
         ) {
@@ -601,47 +607,75 @@
 val TopAppBarExamples =
     listOf(
         Example(
-            name = ::SimpleTopAppBar.name,
+            name = "SimpleTopAppBar",
             description = TopAppBarExampleDescription,
             sourceUrl = TopAppBarExampleSourceUrl,
         ) {
             SimpleTopAppBar()
         },
         Example(
-            name = ::SimpleCenterAlignedTopAppBar.name,
+            name = "SimpleTopAppBarWithSubtitle",
+            description = TopAppBarExampleDescription,
+            sourceUrl = TopAppBarExampleSourceUrl,
+        ) {
+            SimpleTopAppBarWithSubtitle()
+        },
+        Example(
+            name = "SimpleCenterAlignedTopAppBar",
             description = TopAppBarExampleDescription,
             sourceUrl = TopAppBarExampleSourceUrl,
         ) {
             SimpleCenterAlignedTopAppBar()
         },
         Example(
-            name = ::PinnedTopAppBar.name,
+            name = "SimpleCenterAlignedTopAppBarWithSubtitle",
+            description = TopAppBarExampleDescription,
+            sourceUrl = TopAppBarExampleSourceUrl,
+        ) {
+            SimpleCenterAlignedTopAppBarWithSubtitle()
+        },
+        Example(
+            name = "PinnedTopAppBar",
             description = TopAppBarExampleDescription,
             sourceUrl = TopAppBarExampleSourceUrl,
         ) {
             PinnedTopAppBar()
         },
         Example(
-            name = ::EnterAlwaysTopAppBar.name,
+            name = "EnterAlwaysTopAppBar",
             description = TopAppBarExampleDescription,
             sourceUrl = TopAppBarExampleSourceUrl,
         ) {
             EnterAlwaysTopAppBar()
         },
         Example(
-            name = ::ExitUntilCollapsedMediumTopAppBar.name,
+            name = "ExitUntilCollapsedMediumTopAppBar",
             description = TopAppBarExampleDescription,
             sourceUrl = TopAppBarExampleSourceUrl,
         ) {
             ExitUntilCollapsedMediumTopAppBar()
         },
         Example(
-            name = ::ExitUntilCollapsedLargeTopAppBar.name,
+            name = "ExitUntilCollapsedCenterAlignedMediumTopAppBarWithSubtitle",
+            description = TopAppBarExampleDescription,
+            sourceUrl = TopAppBarExampleSourceUrl,
+        ) {
+            ExitUntilCollapsedCenterAlignedMediumTopAppBarWithSubtitle()
+        },
+        Example(
+            name = "ExitUntilCollapsedLargeTopAppBar",
             description = TopAppBarExampleDescription,
             sourceUrl = TopAppBarExampleSourceUrl,
         ) {
             ExitUntilCollapsedLargeTopAppBar()
         },
+        Example(
+            name = "ExitUntilCollapsedCenterAlignedLargeTopAppBarWithSubtitle",
+            description = TopAppBarExampleDescription,
+            sourceUrl = TopAppBarExampleSourceUrl,
+        ) {
+            ExitUntilCollapsedCenterAlignedLargeTopAppBarWithSubtitle()
+        },
     )
 
 private const val FloatingAppBarsExampleDescription = "Floating app bar examples"
@@ -650,14 +684,14 @@
 val FloatingAppBarsExamples =
     listOf(
         Example(
-            name = ::HorizontalFloatingAppBar.name,
+            name = "HorizontalFloatingAppBar",
             description = FloatingAppBarsExampleDescription,
             sourceUrl = FloatingAppBarsExampleSourceUrl,
         ) {
             HorizontalFloatingAppBar()
         },
         Example(
-            name = ::VerticalFloatingAppBar.name,
+            name = "VerticalFloatingAppBar",
             description = FloatingAppBarsExampleDescription,
             sourceUrl = FloatingAppBarsExampleSourceUrl,
         ) {
@@ -670,21 +704,21 @@
 val ExtendedFABExamples =
     listOf(
         Example(
-            name = ::ExtendedFloatingActionButtonSample.name,
+            name = "ExtendedFloatingActionButtonSample",
             description = ExtendedFABExampleDescription,
             sourceUrl = ExtendedFABExampleSourceUrl,
         ) {
             ExtendedFloatingActionButtonSample()
         },
         Example(
-            name = ::ExtendedFloatingActionButtonTextSample.name,
+            name = "ExtendedFloatingActionButtonTextSample",
             description = ExtendedFABExampleDescription,
             sourceUrl = ExtendedFABExampleSourceUrl,
         ) {
             ExtendedFloatingActionButtonTextSample()
         },
         Example(
-            name = ::AnimatedExtendedFloatingActionButtonSample.name,
+            name = "AnimatedExtendedFloatingActionButtonSample",
             description = ExtendedFABExampleDescription,
             sourceUrl = ExtendedFABExampleSourceUrl,
         ) {
@@ -698,21 +732,21 @@
 val FloatingActionButtonsExamples =
     listOf(
         Example(
-            name = ::FloatingActionButtonSample.name,
+            name = "FloatingActionButtonSample",
             description = FloatingActionButtonsExampleDescription,
             sourceUrl = FloatingActionButtonsExampleSourceUrl,
         ) {
             FloatingActionButtonSample()
         },
         Example(
-            name = ::LargeFloatingActionButtonSample.name,
+            name = "LargeFloatingActionButtonSample",
             description = FloatingActionButtonsExampleDescription,
             sourceUrl = FloatingActionButtonsExampleSourceUrl,
         ) {
             LargeFloatingActionButtonSample()
         },
         Example(
-            name = ::SmallFloatingActionButtonSample.name,
+            name = "SmallFloatingActionButtonSample",
             description = FloatingActionButtonsExampleDescription,
             sourceUrl = FloatingActionButtonsExampleSourceUrl,
         ) {
@@ -725,28 +759,28 @@
 val ListsExamples =
     listOf(
         Example(
-            name = ::OneLineListItem.name,
+            name = "OneLineListItem",
             description = ListsExampleDescription,
             sourceUrl = ListsExampleSourceUrl
         ) {
             OneLineListItem()
         },
         Example(
-            name = ::TwoLineListItem.name,
+            name = "TwoLineListItem",
             description = ListsExampleDescription,
             sourceUrl = ListsExampleSourceUrl
         ) {
             TwoLineListItem()
         },
         Example(
-            name = ::ThreeLineListItemWithOverlineAndSupporting.name,
+            name = "ThreeLineListItemWithOverlineAndSupporting",
             description = ListsExampleDescription,
             sourceUrl = ListsExampleSourceUrl
         ) {
             ThreeLineListItemWithOverlineAndSupporting()
         },
         Example(
-            name = ::ThreeLineListItemWithExtendedSupporting.name,
+            name = "ThreeLineListItemWithExtendedSupporting",
             description = ListsExampleDescription,
             sourceUrl = ListsExampleSourceUrl
         ) {
@@ -759,63 +793,63 @@
 val IconButtonExamples =
     listOf(
         Example(
-            name = ::IconButtonSample.name,
+            name = "IconButtonSample",
             description = IconButtonExampleDescription,
             sourceUrl = IconButtonExampleSourceUrl,
         ) {
             IconButtonSample()
         },
         Example(
-            name = ::TintedIconButtonSample.name,
+            name = "TintedIconButtonSample",
             description = IconButtonExampleDescription,
             sourceUrl = IconButtonExampleSourceUrl,
         ) {
             TintedIconButtonSample()
         },
         Example(
-            name = ::IconToggleButtonSample.name,
+            name = "IconToggleButtonSample",
             description = IconButtonExampleDescription,
             sourceUrl = IconButtonExampleSourceUrl,
         ) {
             IconToggleButtonSample()
         },
         Example(
-            name = ::FilledIconButtonSample.name,
+            name = "FilledIconButtonSample",
             description = IconButtonExampleDescription,
             sourceUrl = IconButtonExampleSourceUrl,
         ) {
             FilledIconButtonSample()
         },
         Example(
-            name = ::FilledIconToggleButtonSample.name,
+            name = "FilledIconToggleButtonSample",
             description = IconButtonExampleDescription,
             sourceUrl = IconButtonExampleSourceUrl,
         ) {
             FilledIconToggleButtonSample()
         },
         Example(
-            name = ::FilledTonalIconButtonSample.name,
+            name = "FilledTonalIconButtonSample",
             description = IconButtonExampleDescription,
             sourceUrl = IconButtonExampleSourceUrl,
         ) {
             FilledTonalIconButtonSample()
         },
         Example(
-            name = ::FilledTonalIconToggleButtonSample.name,
+            name = "FilledTonalIconToggleButtonSample",
             description = IconButtonExampleDescription,
             sourceUrl = IconButtonExampleSourceUrl,
         ) {
             FilledTonalIconToggleButtonSample()
         },
         Example(
-            name = ::OutlinedIconButtonSample.name,
+            name = "OutlinedIconButtonSample",
             description = IconButtonExampleDescription,
             sourceUrl = IconButtonExampleSourceUrl,
         ) {
             OutlinedIconButtonSample()
         },
         Example(
-            name = ::OutlinedIconToggleButtonSample.name,
+            name = "OutlinedIconToggleButtonSample",
             description = IconButtonExampleDescription,
             sourceUrl = IconButtonExampleSourceUrl,
         ) {
@@ -823,33 +857,61 @@
         }
     )
 
+private const val LoadingIndicatorsExampleDescription = "Loading indicators examples"
+private const val LoadingIndicatorsExampleSourceUrl =
+    "$SampleSourceUrl/" + "LoadingIndicatorSamples.kt"
+val LoadingIndicatorsExamples =
+    listOf(
+        Example(
+            name = "LoadingIndicatorSample",
+            description = LoadingIndicatorsExampleDescription,
+            sourceUrl = LoadingIndicatorsExampleSourceUrl
+        ) {
+            LoadingIndicatorSample()
+        },
+        Example(
+            name = "DeterminateLoadingIndicatorSample",
+            description = LoadingIndicatorsExampleDescription,
+            sourceUrl = LoadingIndicatorsExampleSourceUrl
+        ) {
+            DeterminateLoadingIndicatorSample()
+        },
+        Example(
+            name = "LoadingIndicatorPullToRefreshSample",
+            description = LoadingIndicatorsExampleDescription,
+            sourceUrl = LoadingIndicatorsExampleSourceUrl
+        ) {
+            LoadingIndicatorPullToRefreshSample()
+        },
+    )
+
 private const val MenusExampleDescription = "Menus examples"
 private const val MenusExampleSourceUrl = "$SampleSourceUrl/MenuSamples.kt"
 val MenusExamples =
     listOf(
         Example(
-            name = ::MenuSample.name,
+            name = "MenuSample",
             description = MenusExampleDescription,
             sourceUrl = MenusExampleSourceUrl
         ) {
             MenuSample()
         },
         Example(
-            name = ::MenuWithScrollStateSample.name,
+            name = "MenuWithScrollStateSample",
             description = MenusExampleDescription,
             sourceUrl = MenusExampleSourceUrl
         ) {
             MenuWithScrollStateSample()
         },
         Example(
-            name = ::ExposedDropdownMenuSample.name,
+            name = "ExposedDropdownMenuSample",
             description = MenusExampleDescription,
             sourceUrl = MenusExampleSourceUrl
         ) {
             ExposedDropdownMenuSample()
         },
         Example(
-            name = ::EditableExposedDropdownMenuSample.name,
+            name = "EditableExposedDropdownMenuSample",
             description = MenusExampleDescription,
             sourceUrl = MenusExampleSourceUrl
         ) {
@@ -862,28 +924,28 @@
 val NavigationBarExamples =
     listOf(
         Example(
-            name = ::ShortNavigationBarSample.name,
+            name = "ShortNavigationBarSample",
             description = NavigationBarExampleDescription,
             sourceUrl = NavigationBarExampleSourceUrl,
         ) {
             ShortNavigationBarSample()
         },
         Example(
-            name = ::ShortNavigationBarWithHorizontalItemsSample.name,
+            name = "ShortNavigationBarWithHorizontalItemsSample",
             description = NavigationBarExampleDescription,
             sourceUrl = NavigationBarExampleSourceUrl,
         ) {
             ShortNavigationBarWithHorizontalItemsSample()
         },
         Example(
-            name = ::NavigationBarSample.name,
+            name = "NavigationBarSample",
             description = NavigationBarExampleDescription,
             sourceUrl = NavigationBarExampleSourceUrl,
         ) {
             NavigationBarSample()
         },
         Example(
-            name = ::NavigationBarWithOnlySelectedLabelsSample.name,
+            name = "NavigationBarWithOnlySelectedLabelsSample",
             description = NavigationBarExampleDescription,
             sourceUrl = NavigationBarExampleSourceUrl,
         ) {
@@ -896,21 +958,21 @@
 val NavigationRailExamples =
     listOf(
         Example(
-            name = ::NavigationRailSample.name,
+            name = "NavigationRailSample",
             description = NavigationRailExampleDescription,
             sourceUrl = NavigationRailExampleSourceUrl,
         ) {
             NavigationRailSample()
         },
         Example(
-            name = ::NavigationRailWithOnlySelectedLabelsSample.name,
+            name = "NavigationRailWithOnlySelectedLabelsSample",
             description = NavigationRailExampleDescription,
             sourceUrl = NavigationRailExampleSourceUrl,
         ) {
             NavigationRailWithOnlySelectedLabelsSample()
         },
         Example(
-            name = ::NavigationRailBottomAlignSample.name,
+            name = "NavigationRailBottomAlignSample",
             description = NavigationRailExampleDescription,
             sourceUrl = NavigationRailExampleSourceUrl,
         ) {
@@ -923,21 +985,21 @@
 val NavigationDrawerExamples =
     listOf(
         Example(
-            name = ::ModalNavigationDrawerSample.name,
+            name = "ModalNavigationDrawerSample",
             description = NavigationDrawerExampleDescription,
             sourceUrl = NavigationDrawerExampleSourceUrl
         ) {
             ModalNavigationDrawerSample()
         },
         Example(
-            name = ::PermanentNavigationDrawerSample.name,
+            name = "PermanentNavigationDrawerSample",
             description = NavigationDrawerExampleDescription,
             sourceUrl = NavigationDrawerExampleSourceUrl
         ) {
             PermanentNavigationDrawerSample()
         },
         Example(
-            name = ::DismissibleNavigationDrawerSample.name,
+            name = "DismissibleNavigationDrawerSample",
             description = NavigationDrawerExampleDescription,
             sourceUrl = NavigationDrawerExampleSourceUrl
         ) {
@@ -951,21 +1013,21 @@
 val NavigationSuiteScaffoldExamples =
     listOf(
         Example(
-            name = ::NavigationSuiteScaffoldSample.name,
+            name = "NavigationSuiteScaffoldSample",
             description = NavigationSuiteScaffoldExampleDescription,
             sourceUrl = NavigationSuiteScaffoldExampleSourceUrl,
         ) {
             NavigationSuiteScaffoldSample()
         },
         Example(
-            name = ::NavigationSuiteScaffoldCustomConfigSample.name,
+            name = "NavigationSuiteScaffoldCustomConfigSample",
             description = NavigationSuiteScaffoldExampleDescription,
             sourceUrl = NavigationSuiteScaffoldExampleSourceUrl,
         ) {
             NavigationSuiteScaffoldCustomConfigSample()
         },
         Example(
-            name = ::NavigationSuiteScaffoldCustomNavigationRail.name,
+            name = "NavigationSuiteScaffoldCustomNavigationRail",
             description = NavigationSuiteScaffoldExampleDescription,
             sourceUrl = NavigationSuiteScaffoldExampleSourceUrl,
         ) {
@@ -979,56 +1041,56 @@
 val ProgressIndicatorsExamples =
     listOf(
         Example(
-            name = ::LinearProgressIndicatorSample.name,
+            name = "LinearProgressIndicatorSample",
             description = ProgressIndicatorsExampleDescription,
             sourceUrl = ProgressIndicatorsExampleSourceUrl
         ) {
             LinearProgressIndicatorSample()
         },
         Example(
-            name = ::LinearWavyProgressIndicatorSample.name,
+            name = "LinearWavyProgressIndicatorSample",
             description = ProgressIndicatorsExampleDescription,
             sourceUrl = ProgressIndicatorsExampleSourceUrl
         ) {
             LinearWavyProgressIndicatorSample()
         },
         Example(
-            name = ::IndeterminateLinearProgressIndicatorSample.name,
+            name = "IndeterminateLinearProgressIndicatorSample",
             description = ProgressIndicatorsExampleDescription,
             sourceUrl = ProgressIndicatorsExampleSourceUrl
         ) {
             IndeterminateLinearProgressIndicatorSample()
         },
         Example(
-            name = ::IndeterminateLinearWavyProgressIndicatorSample.name,
+            name = "IndeterminateLinearWavyProgressIndicatorSample",
             description = ProgressIndicatorsExampleDescription,
             sourceUrl = ProgressIndicatorsExampleSourceUrl
         ) {
             IndeterminateLinearWavyProgressIndicatorSample()
         },
         Example(
-            name = ::CircularProgressIndicatorSample.name,
+            name = "CircularProgressIndicatorSample",
             description = ProgressIndicatorsExampleDescription,
             sourceUrl = ProgressIndicatorsExampleSourceUrl
         ) {
             CircularProgressIndicatorSample()
         },
         Example(
-            name = ::CircularWavyProgressIndicatorSample.name,
+            name = "CircularWavyProgressIndicatorSample",
             description = ProgressIndicatorsExampleDescription,
             sourceUrl = ProgressIndicatorsExampleSourceUrl
         ) {
             CircularWavyProgressIndicatorSample()
         },
         Example(
-            name = ::IndeterminateCircularProgressIndicatorSample.name,
+            name = "IndeterminateCircularProgressIndicatorSample",
             description = ProgressIndicatorsExampleDescription,
             sourceUrl = ProgressIndicatorsExampleSourceUrl
         ) {
             IndeterminateCircularProgressIndicatorSample()
         },
         Example(
-            name = ::IndeterminateCircularWavyProgressIndicatorSample.name,
+            name = "IndeterminateCircularWavyProgressIndicatorSample",
             description = ProgressIndicatorsExampleDescription,
             sourceUrl = ProgressIndicatorsExampleSourceUrl
         ) {
@@ -1041,35 +1103,42 @@
 val PullToRefreshExamples =
     listOf(
         Example(
-            name = ::PullToRefreshSample.name,
+            name = "PullToRefreshSample",
             description = PullToRefreshExampleDescription,
             sourceUrl = PullToRefreshExampleSourceUrl
         ) {
             PullToRefreshSample()
         },
         Example(
-            name = ::PullToRefreshScalingSample.name,
+            name = "PullToRefreshWithLoadingIndicatorSample",
+            description = PullToRefreshExampleDescription,
+            sourceUrl = PullToRefreshExampleSourceUrl
+        ) {
+            PullToRefreshWithLoadingIndicatorSample()
+        },
+        Example(
+            name = "PullToRefreshScalingSample",
             description = PullToRefreshExampleDescription,
             sourceUrl = PullToRefreshExampleSourceUrl
         ) {
             PullToRefreshScalingSample()
         },
         Example(
-            name = ::PullToRefreshSampleCustomState.name,
+            name = "PullToRefreshSampleCustomState",
             description = PullToRefreshExampleDescription,
             sourceUrl = PullToRefreshExampleSourceUrl
         ) {
             PullToRefreshSampleCustomState()
         },
         Example(
-            name = ::PullToRefreshViewModelSample.name,
+            name = "PullToRefreshViewModelSample",
             description = PullToRefreshExampleDescription,
             sourceUrl = PullToRefreshExampleSourceUrl
         ) {
             PullToRefreshViewModelSample()
         },
         Example(
-            name = ::PullToRefreshViewModelSample.name,
+            name = "PullToRefreshViewModelSample",
             description = PullToRefreshExampleDescription,
             sourceUrl = PullToRefreshExampleSourceUrl
         ) {
@@ -1082,14 +1151,14 @@
 val RadioButtonsExamples =
     listOf(
         Example(
-            name = ::RadioButtonSample.name,
+            name = "RadioButtonSample",
             description = RadioButtonsExampleDescription,
             sourceUrl = RadioButtonsExampleSourceUrl
         ) {
             RadioButtonSample()
         },
         Example(
-            name = ::RadioGroupSample.name,
+            name = "RadioGroupSample",
             description = RadioButtonsExampleDescription,
             sourceUrl = RadioButtonsExampleSourceUrl
         ) {
@@ -1102,14 +1171,14 @@
 val SearchBarExamples =
     listOf(
         Example(
-            name = ::SearchBarSample.name,
+            name = "SearchBarSample",
             description = SearchBarExampleDescription,
             sourceUrl = SearchBarExampleSourceUrl
         ) {
             SearchBarSample()
         },
         Example(
-            name = ::DockedSearchBarSample.name,
+            name = "DockedSearchBarSample",
             description = SearchBarExampleDescription,
             sourceUrl = SearchBarExampleSourceUrl
         ) {
@@ -1122,14 +1191,14 @@
 val SegmentedButtonExamples =
     listOf(
         Example(
-            name = ::SegmentedButtonSingleSelectSample.name,
+            name = "SegmentedButtonSingleSelectSample",
             description = SegmentedButtonExampleDescription,
             sourceUrl = SegmentedButtonSourceUrl
         ) {
             SegmentedButtonSingleSelectSample()
         },
         Example(
-            name = ::SegmentedButtonMultiSelectSample.name,
+            name = "SegmentedButtonMultiSelectSample",
             description = SegmentedButtonExampleDescription,
             sourceUrl = SegmentedButtonSourceUrl
         ) {
@@ -1142,49 +1211,49 @@
 val SlidersExamples =
     listOf(
         Example(
-            name = ::SliderSample.name,
+            name = "SliderSample",
             description = SlidersExampleDescription,
             sourceUrl = SlidersExampleSourceUrl
         ) {
             SliderSample()
         },
         Example(
-            name = ::StepsSliderSample.name,
+            name = "StepsSliderSample",
             description = SlidersExampleDescription,
             sourceUrl = SlidersExampleSourceUrl
         ) {
             StepsSliderSample()
         },
         Example(
-            name = ::SliderWithCustomThumbSample.name,
+            name = "SliderWithCustomThumbSample",
             description = SlidersExampleDescription,
             sourceUrl = SlidersExampleSourceUrl
         ) {
             SliderWithCustomThumbSample()
         },
         Example(
-            name = ::SliderWithCustomTrackAndThumb.name,
+            name = "SliderWithCustomTrackAndThumb",
             description = SlidersExampleDescription,
             sourceUrl = SlidersExampleSourceUrl
         ) {
             SliderWithCustomTrackAndThumb()
         },
         Example(
-            name = ::RangeSliderSample.name,
+            name = "RangeSliderSample",
             description = SlidersExampleDescription,
             sourceUrl = SlidersExampleSourceUrl
         ) {
             RangeSliderSample()
         },
         Example(
-            name = ::StepRangeSliderSample.name,
+            name = "StepRangeSliderSample",
             description = SlidersExampleDescription,
             sourceUrl = SlidersExampleSourceUrl
         ) {
             StepRangeSliderSample()
         },
         Example(
-            name = ::RangeSliderWithCustomComponents.name,
+            name = "RangeSliderWithCustomComponents",
             description = SlidersExampleDescription,
             sourceUrl = SlidersExampleSourceUrl
         ) {
@@ -1197,35 +1266,35 @@
 val SnackbarsExamples =
     listOf(
         Example(
-            name = ::ScaffoldWithSimpleSnackbar.name,
+            name = "ScaffoldWithSimpleSnackbar",
             description = SnackbarsExampleDescription,
             sourceUrl = SnackbarsExampleSourceUrl
         ) {
             ScaffoldWithSimpleSnackbar()
         },
         Example(
-            name = ::ScaffoldWithIndefiniteSnackbar.name,
+            name = "ScaffoldWithIndefiniteSnackbar",
             description = SnackbarsExampleDescription,
             sourceUrl = SnackbarsExampleSourceUrl
         ) {
             ScaffoldWithIndefiniteSnackbar()
         },
         Example(
-            name = ::ScaffoldWithCustomSnackbar.name,
+            name = "ScaffoldWithCustomSnackbar",
             description = SnackbarsExampleDescription,
             sourceUrl = SnackbarsExampleSourceUrl
         ) {
             ScaffoldWithCustomSnackbar()
         },
         Example(
-            name = ::ScaffoldWithCoroutinesSnackbar.name,
+            name = "ScaffoldWithCoroutinesSnackbar",
             description = SnackbarsExampleDescription,
             sourceUrl = SnackbarsExampleSourceUrl
         ) {
             ScaffoldWithCoroutinesSnackbar()
         },
         Example(
-            name = ::ScaffoldWithMultilineSnackbar.name,
+            name = "ScaffoldWithMultilineSnackbar",
             description = SnackbarsExampleDescription,
             sourceUrl = SnackbarsExampleSourceUrl
         ) {
@@ -1238,49 +1307,49 @@
 val SplitButtonExamples =
     listOf(
         Example(
-            name = ::SplitButtonSample.name,
+            name = "SplitButtonSample",
             description = SplitButtonExampleDescription,
             sourceUrl = SplitButtonSourceUrl
         ) {
             SplitButtonSample()
         },
         Example(
-            name = ::FilledSplitButtonSample.name,
+            name = "FilledSplitButtonSample",
             description = SplitButtonExampleDescription,
             sourceUrl = SplitButtonSourceUrl
         ) {
             FilledSplitButtonSample()
         },
         Example(
-            name = ::TonalSplitButtonSample.name,
+            name = "TonalSplitButtonSample",
             description = SplitButtonExampleDescription,
             sourceUrl = SplitButtonSourceUrl
         ) {
             TonalSplitButtonSample()
         },
         Example(
-            name = ::ElevatedSplitButtonSample.name,
+            name = "ElevatedSplitButtonSample",
             description = SplitButtonExampleDescription,
             sourceUrl = SplitButtonSourceUrl
         ) {
             ElevatedSplitButtonSample()
         },
         Example(
-            name = ::OutlinedSplitButtonSample.name,
+            name = "OutlinedSplitButtonSample",
             description = SplitButtonExampleDescription,
             sourceUrl = SplitButtonSourceUrl
         ) {
             OutlinedSplitButtonSample()
         },
         Example(
-            name = ::SplitButtonWithTextSample.name,
+            name = "SplitButtonWithTextSample",
             description = SplitButtonExampleDescription,
             sourceUrl = SplitButtonSourceUrl
         ) {
             SplitButtonWithTextSample()
         },
         Example(
-            name = ::SplitButtonWithIconSample.name,
+            name = "SplitButtonWithIconSample",
             description = SplitButtonExampleDescription,
             sourceUrl = SplitButtonSourceUrl
         ) {
@@ -1293,14 +1362,14 @@
 val SwitchExamples =
     listOf(
         Example(
-            name = ::SwitchSample.name,
+            name = "SwitchSample",
             description = SwitchExampleDescription,
             sourceUrl = SwitchExampleSourceUrl
         ) {
             SwitchSample()
         },
         Example(
-            name = ::SwitchWithThumbIconSample.name,
+            name = "SwitchWithThumbIconSample",
             description = SwitchExampleDescription,
             sourceUrl = SwitchExampleSourceUrl
         ) {
@@ -1313,84 +1382,84 @@
 val TabsExamples =
     listOf(
         Example(
-            name = ::PrimaryTextTabs.name,
+            name = "PrimaryTextTabs",
             description = TabsExampleDescription,
             sourceUrl = TabsExampleSourceUrl
         ) {
             PrimaryTextTabs()
         },
         Example(
-            name = ::PrimaryIconTabs.name,
+            name = "PrimaryIconTabs",
             description = TabsExampleDescription,
             sourceUrl = TabsExampleSourceUrl
         ) {
             PrimaryIconTabs()
         },
         Example(
-            name = ::SecondaryTextTabs.name,
+            name = "SecondaryTextTabs",
             description = TabsExampleDescription,
             sourceUrl = TabsExampleSourceUrl
         ) {
             SecondaryTextTabs()
         },
         Example(
-            name = ::SecondaryIconTabs.name,
+            name = "SecondaryIconTabs",
             description = TabsExampleDescription,
             sourceUrl = TabsExampleSourceUrl
         ) {
             SecondaryIconTabs()
         },
         Example(
-            name = ::TextAndIconTabs.name,
+            name = "TextAndIconTabs",
             description = TabsExampleDescription,
             sourceUrl = TabsExampleSourceUrl
         ) {
             TextAndIconTabs()
         },
         Example(
-            name = ::LeadingIconTabs.name,
+            name = "LeadingIconTabs",
             description = TabsExampleDescription,
             sourceUrl = TabsExampleSourceUrl
         ) {
             LeadingIconTabs()
         },
         Example(
-            name = ::ScrollingPrimaryTextTabs.name,
+            name = "ScrollingPrimaryTextTabs",
             description = TabsExampleDescription,
             sourceUrl = TabsExampleSourceUrl
         ) {
             ScrollingPrimaryTextTabs()
         },
         Example(
-            name = ::ScrollingSecondaryTextTabs.name,
+            name = "ScrollingSecondaryTextTabs",
             description = TabsExampleDescription,
             sourceUrl = TabsExampleSourceUrl
         ) {
             ScrollingSecondaryTextTabs()
         },
         Example(
-            name = ::FancyTabs.name,
+            name = "FancyTabs",
             description = TabsExampleDescription,
             sourceUrl = TabsExampleSourceUrl
         ) {
             FancyTabs()
         },
         Example(
-            name = ::FancyIndicatorTabs.name,
+            name = "FancyIndicatorTabs",
             description = TabsExampleDescription,
             sourceUrl = TabsExampleSourceUrl
         ) {
             FancyIndicatorTabs()
         },
         Example(
-            name = ::FancyIndicatorContainerTabs.name,
+            name = "FancyIndicatorContainerTabs",
             description = TabsExampleDescription,
             sourceUrl = TabsExampleSourceUrl
         ) {
             FancyIndicatorContainerTabs()
         },
         Example(
-            name = ::ScrollingFancyIndicatorContainerTabs.name,
+            name = "ScrollingFancyIndicatorContainerTabs",
             description = TabsExampleDescription,
             sourceUrl = TabsExampleSourceUrl
         ) {
@@ -1403,21 +1472,21 @@
 val TimePickerExamples =
     listOf(
         Example(
-            name = ::TimePickerSample.name,
+            name = "TimePickerSample",
             description = TimePickerDescription,
             sourceUrl = TimePickerSourceUrl
         ) {
             TimePickerSample()
         },
         Example(
-            name = ::TimeInputSample.name,
+            name = "TimeInputSample",
             description = TimePickerDescription,
             sourceUrl = TimePickerSourceUrl
         ) {
             TimeInputSample()
         },
         Example(
-            name = ::TimePickerSwitchableSample.name,
+            name = "TimePickerSwitchableSample",
             description = TimePickerDescription,
             sourceUrl = TimePickerSourceUrl
         ) {
@@ -1430,84 +1499,84 @@
 val TextFieldsExamples =
     listOf(
             Example(
-                name = ::SimpleTextFieldSample.name,
+                name = "SimpleTextFieldSample",
                 description = TextFieldsExampleDescription,
                 sourceUrl = TextFieldsExampleSourceUrl
             ) {
                 SimpleTextFieldSample()
             },
             Example(
-                name = ::TextFieldSample.name,
+                name = "TextFieldSample",
                 description = TextFieldsExampleDescription,
                 sourceUrl = TextFieldsExampleSourceUrl
             ) {
                 TextFieldSample()
             },
             Example(
-                name = ::SimpleOutlinedTextFieldSample.name,
+                name = "SimpleOutlinedTextFieldSample",
                 description = TextFieldsExampleDescription,
                 sourceUrl = TextFieldsExampleSourceUrl
             ) {
                 SimpleOutlinedTextFieldSample()
             },
             Example(
-                name = ::OutlinedTextFieldSample.name,
+                name = "OutlinedTextFieldSample",
                 description = TextFieldsExampleDescription,
                 sourceUrl = TextFieldsExampleSourceUrl
             ) {
                 OutlinedTextFieldSample()
             },
             Example(
-                name = ::TextFieldWithIcons.name,
+                name = "TextFieldWithIcons",
                 description = TextFieldsExampleDescription,
                 sourceUrl = TextFieldsExampleSourceUrl
             ) {
                 TextFieldWithIcons()
             },
             Example(
-                name = ::TextFieldWithPlaceholder.name,
+                name = "TextFieldWithPlaceholder",
                 description = TextFieldsExampleDescription,
                 sourceUrl = TextFieldsExampleSourceUrl
             ) {
                 TextFieldWithPlaceholder()
             },
             Example(
-                name = ::TextFieldWithPrefixAndSuffix.name,
+                name = "TextFieldWithPrefixAndSuffix",
                 description = TextFieldsExampleDescription,
                 sourceUrl = TextFieldsExampleSourceUrl
             ) {
                 TextFieldWithPrefixAndSuffix()
             },
             Example(
-                name = ::TextFieldWithErrorState.name,
+                name = "TextFieldWithErrorState",
                 description = TextFieldsExampleDescription,
                 sourceUrl = TextFieldsExampleSourceUrl
             ) {
                 TextFieldWithErrorState()
             },
             Example(
-                name = ::TextFieldWithSupportingText.name,
+                name = "TextFieldWithSupportingText",
                 description = TextFieldsExampleDescription,
                 sourceUrl = TextFieldsExampleSourceUrl
             ) {
                 TextFieldWithSupportingText()
             },
             Example(
-                name = ::PasswordTextField.name,
+                name = "PasswordTextField",
                 description = TextFieldsExampleDescription,
                 sourceUrl = TextFieldsExampleSourceUrl
             ) {
                 PasswordTextField()
             },
             Example(
-                name = ::TextFieldWithHideKeyboardOnImeAction.name,
+                name = "TextFieldWithHideKeyboardOnImeAction",
                 description = TextFieldsExampleDescription,
                 sourceUrl = TextFieldsExampleSourceUrl
             ) {
                 TextFieldWithHideKeyboardOnImeAction()
             },
             Example(
-                name = ::TextArea.name,
+                name = "TextArea",
                 description = TextFieldsExampleDescription,
                 sourceUrl = TextFieldsExampleSourceUrl
             ) {
@@ -1528,56 +1597,56 @@
 val TooltipsExamples =
     listOf(
         Example(
-            name = ::PlainTooltipSample.name,
+            name = "PlainTooltipSample",
             description = TooltipsExampleDescription,
             sourceUrl = TooltipsExampleSourceUrl
         ) {
             PlainTooltipSample()
         },
         Example(
-            name = ::PlainTooltipWithManualInvocationSample.name,
+            name = "PlainTooltipWithManualInvocationSample",
             description = TooltipsExampleDescription,
             sourceUrl = TooltipsExampleSourceUrl
         ) {
             PlainTooltipWithManualInvocationSample()
         },
         Example(
-            name = ::PlainTooltipWithCaret.name,
+            name = "PlainTooltipWithCaret",
             description = TooltipsExampleDescription,
             sourceUrl = TooltipsExampleSourceUrl
         ) {
             PlainTooltipWithCaret()
         },
         Example(
-            name = ::PlainTooltipWithCustomCaret.name,
+            name = "PlainTooltipWithCustomCaret",
             description = TooltipsExampleDescription,
             sourceUrl = TooltipsExampleSourceUrl
         ) {
             PlainTooltipWithCustomCaret()
         },
         Example(
-            name = ::RichTooltipSample.name,
+            name = "RichTooltipSample",
             description = TooltipsExampleDescription,
             sourceUrl = TooltipsExampleSourceUrl
         ) {
             RichTooltipSample()
         },
         Example(
-            name = ::RichTooltipWithManualInvocationSample.name,
+            name = "RichTooltipWithManualInvocationSample",
             description = TooltipsExampleDescription,
             sourceUrl = TooltipsExampleSourceUrl
         ) {
             RichTooltipWithManualInvocationSample()
         },
         Example(
-            name = ::RichTooltipWithCaretSample.name,
+            name = "RichTooltipWithCaretSample",
             description = TooltipsExampleDescription,
             sourceUrl = TooltipsExampleSourceUrl
         ) {
             RichTooltipWithCaretSample()
         },
         Example(
-            name = ::RichTooltipWithCustomCaretSample.name,
+            name = "RichTooltipWithCustomCaretSample",
             description = TooltipsExampleDescription,
             sourceUrl = TooltipsExampleSourceUrl
         ) {
diff --git a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/AppBarSamples.kt b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/AppBarSamples.kt
index 04fbae7..5a92111 100644
--- a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/AppBarSamples.kt
+++ b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/AppBarSamples.kt
@@ -32,6 +32,7 @@
 import androidx.compose.material3.BottomAppBarDefaults
 import androidx.compose.material3.CenterAlignedTopAppBar
 import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
 import androidx.compose.material3.FabPosition
 import androidx.compose.material3.FloatingActionButton
 import androidx.compose.material3.FloatingActionButtonDefaults
@@ -44,6 +45,7 @@
 import androidx.compose.material3.Text
 import androidx.compose.material3.TopAppBar
 import androidx.compose.material3.TopAppBarDefaults
+import androidx.compose.material3.TopAppBarTitleAlignment
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.input.nestedscroll.nestedScroll
@@ -104,6 +106,59 @@
 }
 
 /**
+ * A sample for a simple use of small [TopAppBar] with a subtitle.
+ *
+ * The top app bar here does not react to any scroll events in the content under it.
+ */
+@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
+@Preview
+@Sampled
+@Composable
+fun SimpleTopAppBarWithSubtitle() {
+    Scaffold(
+        topBar = {
+            TopAppBar(
+                title = {
+                    Text("Simple TopAppBar", maxLines = 1, overflow = TextOverflow.Ellipsis)
+                },
+                subtitle = { Text("Subtitle", maxLines = 1, overflow = TextOverflow.Ellipsis) },
+                navigationIcon = {
+                    IconButton(onClick = { /* doSomething() */ }) {
+                        Icon(
+                            imageVector = Icons.Filled.Menu,
+                            contentDescription = "Localized description"
+                        )
+                    }
+                },
+                actions = {
+                    IconButton(onClick = { /* doSomething() */ }) {
+                        Icon(
+                            imageVector = Icons.Filled.Favorite,
+                            contentDescription = "Localized description"
+                        )
+                    }
+                }
+            )
+        },
+        content = { innerPadding ->
+            LazyColumn(
+                contentPadding = innerPadding,
+                verticalArrangement = Arrangement.spacedBy(8.dp)
+            ) {
+                val list = (0..75).map { it.toString() }
+                items(count = list.size) {
+                    Text(
+                        text = list[it],
+                        style = MaterialTheme.typography.bodyLarge,
+                        modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
+                    )
+                }
+            }
+        }
+    )
+}
+
+/**
  * A sample for a simple use of [CenterAlignedTopAppBar].
  *
  * The top app bar here does not react to any scroll events in the content under it.
@@ -156,6 +211,60 @@
 }
 
 /**
+ * A sample for a simple use of small [CenterAlignedTopAppBar] with a subtitle.
+ *
+ * The top app bar here does not react to any scroll events in the content under it.
+ */
+@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
+@Preview
+@Sampled
+@Composable
+fun SimpleCenterAlignedTopAppBarWithSubtitle() {
+    Scaffold(
+        topBar = {
+            TopAppBar(
+                title = {
+                    Text("Simple TopAppBar", maxLines = 1, overflow = TextOverflow.Ellipsis)
+                },
+                subtitle = { Text("Subtitle", maxLines = 1, overflow = TextOverflow.Ellipsis) },
+                titleHorizontalAlignment = TopAppBarTitleAlignment.Center,
+                navigationIcon = {
+                    IconButton(onClick = { /* doSomething() */ }) {
+                        Icon(
+                            imageVector = Icons.Filled.Menu,
+                            contentDescription = "Localized description"
+                        )
+                    }
+                },
+                actions = {
+                    IconButton(onClick = { /* doSomething() */ }) {
+                        Icon(
+                            imageVector = Icons.Filled.Favorite,
+                            contentDescription = "Localized description"
+                        )
+                    }
+                }
+            )
+        },
+        content = { innerPadding ->
+            LazyColumn(
+                contentPadding = innerPadding,
+                verticalArrangement = Arrangement.spacedBy(8.dp)
+            ) {
+                val list = (0..75).map { it.toString() }
+                items(count = list.size) {
+                    Text(
+                        text = list[it],
+                        style = MaterialTheme.typography.bodyLarge,
+                        modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
+                    )
+                }
+            }
+        }
+    )
+}
+
+/**
  * A sample for a pinned small [TopAppBar].
  *
  * The top app bar here is pinned to its location and changes its container color when the content
@@ -220,7 +329,7 @@
  * A sample for a small [TopAppBar] that collapses when the content is scrolled up, and appears when
  * the content scrolled down.
  */
-@OptIn(ExperimentalMaterial3Api::class)
+@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
 @Preview
 @Sampled
 @Composable
@@ -231,6 +340,7 @@
         topBar = {
             TopAppBar(
                 title = { Text("TopAppBar", maxLines = 1, overflow = TextOverflow.Ellipsis) },
+                subtitle = { Text("Subtitle", maxLines = 1, overflow = TextOverflow.Ellipsis) },
                 navigationIcon = {
                     IconButton(onClick = { /* doSomething() */ }) {
                         Icon(
@@ -323,6 +433,62 @@
 }
 
 /**
+ * A sample for a [MediumTopAppBar] that collapses when the content is scrolled up, and appears when
+ * the content is completely scrolled back down, centered with subtitle.
+ */
+@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
+@Preview
+@Sampled
+@Composable
+fun ExitUntilCollapsedCenterAlignedMediumTopAppBarWithSubtitle() {
+    val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
+    Scaffold(
+        modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
+        topBar = {
+            MediumTopAppBar(
+                title = {
+                    Text("Medium TopAppBar", maxLines = 1, overflow = TextOverflow.Ellipsis)
+                },
+                subtitle = { Text("Subtitle", maxLines = 1, overflow = TextOverflow.Ellipsis) },
+                titleHorizontalAlignment = TopAppBarTitleAlignment.Center,
+                navigationIcon = {
+                    IconButton(onClick = { /* doSomething() */ }) {
+                        Icon(
+                            imageVector = Icons.Filled.Menu,
+                            contentDescription = "Localized description"
+                        )
+                    }
+                },
+                actions = {
+                    IconButton(onClick = { /* doSomething() */ }) {
+                        Icon(
+                            imageVector = Icons.Filled.Favorite,
+                            contentDescription = "Localized description"
+                        )
+                    }
+                },
+                scrollBehavior = scrollBehavior
+            )
+        },
+        content = { innerPadding ->
+            LazyColumn(
+                contentPadding = innerPadding,
+                verticalArrangement = Arrangement.spacedBy(8.dp)
+            ) {
+                val list = (0..75).map { it.toString() }
+                items(count = list.size) {
+                    Text(
+                        text = list[it],
+                        style = MaterialTheme.typography.bodyLarge,
+                        modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
+                    )
+                }
+            }
+        }
+    )
+}
+
+/**
  * A sample for a [LargeTopAppBar] that collapses when the content is scrolled up, and appears when
  * the content is completely scrolled back down.
  */
@@ -374,6 +540,60 @@
     )
 }
 
+/**
+ * A sample for a [LargeTopAppBar] that collapses when the content is scrolled up, and appears when
+ * the content is completely scrolled back down, centered with subtitle.
+ */
+@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
+@Preview
+@Sampled
+@Composable
+fun ExitUntilCollapsedCenterAlignedLargeTopAppBarWithSubtitle() {
+    val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
+    Scaffold(
+        modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
+        topBar = {
+            LargeTopAppBar(
+                title = { Text("Large TopAppBar", maxLines = 1, overflow = TextOverflow.Ellipsis) },
+                subtitle = { Text("Subtitle", maxLines = 1, overflow = TextOverflow.Ellipsis) },
+                titleHorizontalAlignment = TopAppBarTitleAlignment.Center,
+                navigationIcon = {
+                    IconButton(onClick = { /* doSomething() */ }) {
+                        Icon(
+                            imageVector = Icons.Filled.Menu,
+                            contentDescription = "Localized description"
+                        )
+                    }
+                },
+                actions = {
+                    IconButton(onClick = { /* doSomething() */ }) {
+                        Icon(
+                            imageVector = Icons.Filled.Favorite,
+                            contentDescription = "Localized description"
+                        )
+                    }
+                },
+                scrollBehavior = scrollBehavior
+            )
+        },
+        content = { innerPadding ->
+            LazyColumn(
+                contentPadding = innerPadding,
+                verticalArrangement = Arrangement.spacedBy(8.dp)
+            ) {
+                val list = (0..75).map { it.toString() }
+                items(count = list.size) {
+                    Text(
+                        text = list[it],
+                        style = MaterialTheme.typography.bodyLarge,
+                        modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
+                    )
+                }
+            }
+        }
+    )
+}
+
 @Preview
 @Sampled
 @Composable
diff --git a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/ExposedDropdownMenuSamples.kt b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/ExposedDropdownMenuSamples.kt
index ce0814a08..b63b53d 100644
--- a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/ExposedDropdownMenuSamples.kt
+++ b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/ExposedDropdownMenuSamples.kt
@@ -19,10 +19,10 @@
 import androidx.annotation.Sampled
 import androidx.compose.material3.DropdownMenuItem
 import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.ExposedDropdownMenuAnchorType
 import androidx.compose.material3.ExposedDropdownMenuBox
 import androidx.compose.material3.ExposedDropdownMenuDefaults
 import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.MenuAnchorType
 import androidx.compose.material3.Text
 import androidx.compose.material3.TextField
 import androidx.compose.runtime.Composable
@@ -57,7 +57,7 @@
             // The `menuAnchor` modifier must be passed to the text field to handle
             // expanding/collapsing the menu on click. A read-only text field has
             // the anchor type `PrimaryNotEditable`.
-            modifier = Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable),
+            modifier = Modifier.menuAnchor(ExposedDropdownMenuAnchorType.PrimaryNotEditable),
             value = text,
             onValueChange = {},
             readOnly = true,
@@ -107,7 +107,7 @@
             // The `menuAnchor` modifier must be passed to the text field to handle
             // expanding/collapsing the menu on click. An editable text field has
             // the anchor type `PrimaryEditable`.
-            modifier = Modifier.menuAnchor(MenuAnchorType.PrimaryEditable),
+            modifier = Modifier.menuAnchor(ExposedDropdownMenuAnchorType.PrimaryEditable),
             value = text,
             onValueChange = { text = it },
             singleLine = true,
@@ -119,7 +119,7 @@
                     // trailing icon a `menuAnchor` of type `SecondaryEditable`. This
                     // provides a better experience for certain accessibility services
                     // to choose a menu option without typing.
-                    modifier = Modifier.menuAnchor(MenuAnchorType.SecondaryEditable),
+                    modifier = Modifier.menuAnchor(ExposedDropdownMenuAnchorType.SecondaryEditable),
                 )
             },
             colors = ExposedDropdownMenuDefaults.textFieldColors(),
diff --git a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/FloatingActionButtonSamples.kt b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/FloatingActionButtonSamples.kt
index 0c75f2f..2850b62 100644
--- a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/FloatingActionButtonSamples.kt
+++ b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/FloatingActionButtonSamples.kt
@@ -22,15 +22,15 @@
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.lazy.rememberLazyListState
-import androidx.compose.material.FabPosition
-import androidx.compose.material.Scaffold
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Add
 import androidx.compose.material3.ExtendedFloatingActionButton
+import androidx.compose.material3.FabPosition
 import androidx.compose.material3.FloatingActionButton
 import androidx.compose.material3.FloatingActionButtonDefaults
 import androidx.compose.material3.Icon
 import androidx.compose.material3.LargeFloatingActionButton
+import androidx.compose.material3.Scaffold
 import androidx.compose.material3.SmallFloatingActionButton
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
@@ -113,7 +113,6 @@
                 text = { Text(text = "Extended FAB") },
             )
         },
-        isFloatingActionButtonDocked = false,
         floatingActionButtonPosition = FabPosition.End,
     ) {
         LazyColumn(state = listState, modifier = Modifier.fillMaxSize()) {
diff --git a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/IconButtonSamples.kt b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/IconButtonSamples.kt
index fe4772d..7613a08 100644
--- a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/IconButtonSamples.kt
+++ b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/IconButtonSamples.kt
@@ -17,16 +17,19 @@
 package androidx.compose.material3.samples
 
 import androidx.annotation.Sampled
+import androidx.compose.foundation.layout.size
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Lock
 import androidx.compose.material.icons.outlined.Lock
 import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
 import androidx.compose.material3.FilledIconButton
 import androidx.compose.material3.FilledIconToggleButton
 import androidx.compose.material3.FilledTonalIconButton
 import androidx.compose.material3.FilledTonalIconToggleButton
 import androidx.compose.material3.Icon
 import androidx.compose.material3.IconButton
+import androidx.compose.material3.IconButtonDefaults
 import androidx.compose.material3.IconToggleButton
 import androidx.compose.material3.OutlinedIconButton
 import androidx.compose.material3.OutlinedIconToggleButton
@@ -35,6 +38,7 @@
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.vector.rememberVectorPainter
 import androidx.compose.ui.tooling.preview.Preview
@@ -48,6 +52,42 @@
     }
 }
 
+@OptIn(ExperimentalMaterial3ExpressiveApi::class)
+@Preview
+@Sampled
+@Composable
+fun SmallSquareNarrowIconButtonSample() {
+    IconButton(
+        onClick = { /* doSomething() */ },
+        modifier = Modifier.size(IconButtonDefaults.SmallNarrowContainerSize),
+        shape = IconButtonDefaults.squareShape
+    ) {
+        Icon(
+            Icons.Outlined.Lock,
+            contentDescription = "Localized description",
+            modifier = Modifier.size(IconButtonDefaults.SmallIconSize)
+        )
+    }
+}
+
+@OptIn(ExperimentalMaterial3ExpressiveApi::class)
+@Preview
+@Sampled
+@Composable
+fun SmallRoundWideIconButtonSample() {
+    IconButton(
+        onClick = { /* doSomething() */ },
+        modifier = Modifier.size(IconButtonDefaults.SmallWideContainerSize),
+        shape = IconButtonDefaults.roundShape
+    ) {
+        Icon(
+            Icons.Outlined.Lock,
+            contentDescription = "Localized description",
+            modifier = Modifier.size(IconButtonDefaults.SmallIconSize)
+        )
+    }
+}
+
 @OptIn(ExperimentalMaterial3Api::class)
 @Preview
 @Sampled
diff --git a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/LoadingIndicatorSamples.kt b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/LoadingIndicatorSamples.kt
new file mode 100644
index 0000000..93040ab
--- /dev/null
+++ b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/LoadingIndicatorSamples.kt
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3.samples
+
+import androidx.annotation.Sampled
+import androidx.compose.animation.core.LinearOutSlowInEasing
+import androidx.compose.animation.core.Spring
+import androidx.compose.animation.core.animateFloatAsState
+import androidx.compose.animation.core.spring
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.requiredHeight
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Refresh
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.ListItem
+import androidx.compose.material3.LoadingIndicator
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.Slider
+import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults
+import androidx.compose.material3.pulltorefresh.pullToRefresh
+import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableFloatStateOf
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.graphicsLayer
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+
+@OptIn(ExperimentalMaterial3ExpressiveApi::class)
+@Preview
+@Sampled
+@Composable
+fun LoadingIndicatorSample() {
+    Column(horizontalAlignment = Alignment.CenterHorizontally) { LoadingIndicator() }
+}
+
+@OptIn(ExperimentalMaterial3ExpressiveApi::class)
+@Preview
+@Sampled
+@Composable
+fun DeterminateLoadingIndicatorSample() {
+    var progress by remember { mutableFloatStateOf(0f) }
+    val animatedProgress by
+        animateFloatAsState(
+            targetValue = progress,
+            animationSpec =
+                spring(
+                    dampingRatio = Spring.DampingRatioNoBouncy,
+                    stiffness = Spring.StiffnessVeryLow,
+                    visibilityThreshold = 1 / 1000f
+                )
+        )
+
+    Column(horizontalAlignment = Alignment.CenterHorizontally) {
+        LoadingIndicator(progress = { animatedProgress })
+        Spacer(Modifier.requiredHeight(30.dp))
+        Text("Set loading progress:")
+        Slider(
+            modifier = Modifier.width(300.dp),
+            value = progress,
+            valueRange = 0f..1f,
+            onValueChange = { progress = it },
+        )
+    }
+}
+
+@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
+@Sampled
+@Composable
+@Preview
+fun LoadingIndicatorPullToRefreshSample() {
+    var itemCount by remember { mutableStateOf(15) }
+    var isRefreshing by remember { mutableStateOf(false) }
+    val state = rememberPullToRefreshState()
+    val coroutineScope = rememberCoroutineScope()
+    val onRefresh: () -> Unit = {
+        isRefreshing = true
+        coroutineScope.launch {
+            // fetch something
+            delay(5000)
+            itemCount += 5
+            isRefreshing = false
+        }
+    }
+
+    val scaleFraction = {
+        if (isRefreshing) 1f
+        else LinearOutSlowInEasing.transform(state.distanceFraction).coerceIn(0f, 1f)
+    }
+
+    Scaffold(
+        modifier =
+            Modifier.pullToRefresh(
+                state = state,
+                isRefreshing = isRefreshing,
+                onRefresh = onRefresh
+            ),
+        topBar = {
+            TopAppBar(
+                title = { Text("TopAppBar") },
+                // Provide an accessible alternative to trigger refresh.
+                actions = {
+                    IconButton(onClick = onRefresh) {
+                        Icon(Icons.Filled.Refresh, "Trigger Refresh")
+                    }
+                }
+            )
+        }
+    ) {
+        Box(Modifier.padding(it)) {
+            LazyColumn(Modifier.fillMaxSize()) {
+                if (!isRefreshing) {
+                    items(itemCount) { ListItem({ Text(text = "Item ${itemCount - it}") }) }
+                }
+            }
+            Box(
+                Modifier.align(Alignment.TopCenter).graphicsLayer {
+                    scaleX = scaleFraction()
+                    scaleY = scaleFraction()
+                }
+            ) {
+                PullToRefreshDefaults.LoadingIndicator(state = state, isRefreshing = isRefreshing)
+            }
+        }
+    }
+}
diff --git a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/MaterialShapesSamples.kt b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/MaterialShapesSamples.kt
new file mode 100644
index 0000000..e058b07
--- /dev/null
+++ b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/MaterialShapesSamples.kt
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3.samples
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.requiredSize
+import androidx.compose.foundation.lazy.grid.GridCells
+import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
+import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
+import androidx.compose.material3.MaterialShapes
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.toShape
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.graphics.shapes.RoundedPolygon
+
+// TODO: Consider adding this as an official @sampled code, perhaps with less shapes.
+@OptIn(ExperimentalMaterial3ExpressiveApi::class)
+@Preview
+@Composable
+fun AllShapes() {
+    Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
+        LazyVerticalGrid(
+            columns = GridCells.FixedSize(64.dp),
+            contentPadding = PaddingValues(2.dp),
+            verticalArrangement = Arrangement.spacedBy(2.dp)
+        ) {
+            allMaterialShapes().forEach { polygon ->
+                item {
+                    Spacer(
+                        modifier =
+                            Modifier.requiredSize(56.dp)
+                                .clip(polygon.toShape())
+                                .background(MaterialTheme.colorScheme.primary)
+                    )
+                }
+            }
+        }
+    }
+}
+
+@OptIn(ExperimentalMaterial3ExpressiveApi::class)
+private fun allMaterialShapes(): List<RoundedPolygon> {
+    return listOf(
+        MaterialShapes.Circle,
+        MaterialShapes.Square,
+        MaterialShapes.Slanted,
+        MaterialShapes.Arch,
+        MaterialShapes.Fan,
+        MaterialShapes.Arrow,
+        MaterialShapes.SemiCircle,
+        MaterialShapes.Oval,
+        MaterialShapes.Pill,
+        MaterialShapes.Triangle,
+        MaterialShapes.Diamond,
+        MaterialShapes.ClamShell,
+        MaterialShapes.Pentagon,
+        MaterialShapes.Gem,
+        MaterialShapes.Sunny,
+        MaterialShapes.VerySunny,
+        MaterialShapes.Cookie4Sided,
+        MaterialShapes.Cookie6Sided,
+        MaterialShapes.Cookie7Sided,
+        MaterialShapes.Cookie9Sided,
+        MaterialShapes.Cookie12Sided,
+        MaterialShapes.Ghostish,
+        MaterialShapes.Clover4Leaf,
+        MaterialShapes.Clover8Leaf,
+        MaterialShapes.Burst,
+        MaterialShapes.SoftBurst,
+        MaterialShapes.Boom,
+        MaterialShapes.SoftBoom,
+        MaterialShapes.Flower,
+        MaterialShapes.Puffy,
+        MaterialShapes.PuffyDiamond,
+        MaterialShapes.PixelCircle,
+        MaterialShapes.PixelTriangle,
+        MaterialShapes.Bun,
+        MaterialShapes.Heart
+    )
+}
diff --git a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/NavigationBarSamples.kt b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/NavigationBarSamples.kt
index 2c76d18..67f02f2 100644
--- a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/NavigationBarSamples.kt
+++ b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/NavigationBarSamples.kt
@@ -23,6 +23,11 @@
 import androidx.compose.foundation.layout.padding
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Favorite
+import androidx.compose.material.icons.filled.Home
+import androidx.compose.material.icons.filled.Star
+import androidx.compose.material.icons.outlined.FavoriteBorder
+import androidx.compose.material.icons.outlined.Home
+import androidx.compose.material.icons.outlined.StarBorder
 import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
 import androidx.compose.material3.Icon
 import androidx.compose.material3.NavigationBar
@@ -48,11 +53,19 @@
 fun ShortNavigationBarSample() {
     var selectedItem by remember { mutableIntStateOf(0) }
     val items = listOf("Songs", "Artists", "Playlists")
+    val selectedIcons = listOf(Icons.Filled.Home, Icons.Filled.Favorite, Icons.Filled.Star)
+    val unselectedIcons =
+        listOf(Icons.Outlined.Home, Icons.Outlined.FavoriteBorder, Icons.Outlined.StarBorder)
 
     ShortNavigationBar {
         items.forEachIndexed { index, item ->
             ShortNavigationBarItem(
-                icon = { Icon(Icons.Filled.Favorite, contentDescription = item) },
+                icon = {
+                    Icon(
+                        if (selectedItem == index) selectedIcons[index] else unselectedIcons[index],
+                        contentDescription = item
+                    )
+                },
                 label = { Text(item) },
                 selected = selectedItem == index,
                 onClick = { selectedItem = index }
@@ -68,6 +81,9 @@
 fun ShortNavigationBarWithHorizontalItemsSample() {
     var selectedItem by remember { mutableIntStateOf(0) }
     val items = listOf("Songs", "Artists", "Playlists")
+    val selectedIcons = listOf(Icons.Filled.Home, Icons.Filled.Favorite, Icons.Filled.Star)
+    val unselectedIcons =
+        listOf(Icons.Outlined.Home, Icons.Outlined.FavoriteBorder, Icons.Outlined.StarBorder)
 
     Column {
         Text(
@@ -81,7 +97,13 @@
             items.forEachIndexed { index, item ->
                 ShortNavigationBarItem(
                     iconPosition = NavigationItemIconPosition.Start,
-                    icon = { Icon(Icons.Filled.Favorite, contentDescription = item) },
+                    icon = {
+                        Icon(
+                            if (selectedItem == index) selectedIcons[index]
+                            else unselectedIcons[index],
+                            contentDescription = item
+                        )
+                    },
                     label = { Text(item) },
                     selected = selectedItem == index,
                     onClick = { selectedItem = index }
@@ -97,11 +119,19 @@
 fun NavigationBarSample() {
     var selectedItem by remember { mutableIntStateOf(0) }
     val items = listOf("Songs", "Artists", "Playlists")
+    val selectedIcons = listOf(Icons.Filled.Home, Icons.Filled.Favorite, Icons.Filled.Star)
+    val unselectedIcons =
+        listOf(Icons.Outlined.Home, Icons.Outlined.FavoriteBorder, Icons.Outlined.StarBorder)
 
     NavigationBar {
         items.forEachIndexed { index, item ->
             NavigationBarItem(
-                icon = { Icon(Icons.Filled.Favorite, contentDescription = item) },
+                icon = {
+                    Icon(
+                        if (selectedItem == index) selectedIcons[index] else unselectedIcons[index],
+                        contentDescription = item
+                    )
+                },
                 label = { Text(item) },
                 selected = selectedItem == index,
                 onClick = { selectedItem = index }
@@ -114,11 +144,19 @@
 fun NavigationBarWithOnlySelectedLabelsSample() {
     var selectedItem by remember { mutableIntStateOf(0) }
     val items = listOf("Songs", "Artists", "Playlists")
+    val selectedIcons = listOf(Icons.Filled.Home, Icons.Filled.Favorite, Icons.Filled.Star)
+    val unselectedIcons =
+        listOf(Icons.Outlined.Home, Icons.Outlined.FavoriteBorder, Icons.Outlined.StarBorder)
 
     NavigationBar {
         items.forEachIndexed { index, item ->
             NavigationBarItem(
-                icon = { Icon(Icons.Filled.Favorite, contentDescription = item) },
+                icon = {
+                    Icon(
+                        if (selectedItem == index) selectedIcons[index] else unselectedIcons[index],
+                        contentDescription = item
+                    )
+                },
                 label = { Text(item) },
                 selected = selectedItem == index,
                 onClick = { selectedItem = index },
diff --git a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/PullToRefreshSamples.kt b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/PullToRefreshSamples.kt
index ea0ea7c..728bc17 100644
--- a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/PullToRefreshSamples.kt
+++ b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/PullToRefreshSamples.kt
@@ -31,6 +31,7 @@
 import androidx.compose.material.icons.filled.Refresh
 import androidx.compose.material3.CircularProgressIndicator
 import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
 import androidx.compose.material3.Icon
 import androidx.compose.material3.IconButton
 import androidx.compose.material3.LinearProgressIndicator
@@ -72,7 +73,7 @@
     val onRefresh: () -> Unit = {
         isRefreshing = true
         coroutineScope.launch {
-            delay(1500)
+            delay(5000)
             itemCount += 5
             isRefreshing = false
         }
@@ -104,6 +105,57 @@
     }
 }
 
+@Sampled
+@Composable
+@Preview
+@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
+fun PullToRefreshWithLoadingIndicatorSample() {
+    var itemCount by remember { mutableIntStateOf(15) }
+    var isRefreshing by remember { mutableStateOf(false) }
+    val state = rememberPullToRefreshState()
+    val coroutineScope = rememberCoroutineScope()
+    val onRefresh: () -> Unit = {
+        isRefreshing = true
+        coroutineScope.launch {
+            delay(5000)
+            itemCount += 5
+            isRefreshing = false
+        }
+    }
+
+    Scaffold(
+        topBar = {
+            TopAppBar(
+                title = { Text("Title") },
+                // Provide an accessible alternative to trigger refresh.
+                actions = {
+                    IconButton(onClick = onRefresh) {
+                        Icon(Icons.Filled.Refresh, "Trigger Refresh")
+                    }
+                }
+            )
+        }
+    ) {
+        PullToRefreshBox(
+            modifier = Modifier.padding(it),
+            state = state,
+            isRefreshing = isRefreshing,
+            onRefresh = onRefresh,
+            indicator = {
+                PullToRefreshDefaults.LoadingIndicator(
+                    state = state,
+                    isRefreshing = isRefreshing,
+                    modifier = Modifier.align(Alignment.TopCenter),
+                )
+            }
+        ) {
+            LazyColumn(Modifier.fillMaxSize()) {
+                items(itemCount) { ListItem({ Text(text = "Item ${itemCount - it}") }) }
+            }
+        }
+    }
+}
+
 @Composable
 @Preview
 @Sampled
@@ -124,7 +176,7 @@
                         isRefreshing = true
                         try {
                             itemCount += 5
-                            delay(1000) // simulate doing real work
+                            delay(5000) // simulate doing real work
                         } finally {
                             isRefreshing = false
                         }
@@ -183,7 +235,7 @@
         isRefreshing = true
         coroutineScope.launch {
             // fetch something
-            delay(1500)
+            delay(5000)
             itemCount += 5
             isRefreshing = false
         }
@@ -244,7 +296,7 @@
         isRefreshing = true
         coroutineScope.launch {
             // fetch something
-            delay(1500)
+            delay(5000)
             itemCount += 5
             isRefreshing = false
         }
@@ -299,7 +351,7 @@
         isRefreshing = true
         coroutineScope.launch {
             // fetch something
-            delay(1500)
+            delay(5000)
             itemCount += 5
             isRefreshing = false
         }
diff --git a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/SplitButtonSamples.kt b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/SplitButtonSamples.kt
index 0861dea..d175861 100644
--- a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/SplitButtonSamples.kt
+++ b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/SplitButtonSamples.kt
@@ -249,6 +249,7 @@
             SplitButtonDefaults.AnimatedTrailingButton(
                 onClick = { expanded = !expanded },
                 expanded = expanded,
+                modifier = Modifier.size(40.dp)
             ) {
                 val rotation: Float by
                     animateFloatAsState(
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/AppBarScreenshotTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/AppBarScreenshotTest.kt
index de222ab..40dce46 100644
--- a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/AppBarScreenshotTest.kt
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/AppBarScreenshotTest.kt
@@ -47,7 +47,7 @@
 @LargeTest
 @RunWith(AndroidJUnit4::class)
 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
-@OptIn(ExperimentalMaterial3Api::class)
+@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
 class AppBarScreenshotTest {
 
     @get:Rule val composeTestRule = createComposeRule()
@@ -81,6 +81,60 @@
     }
 
     @Test
+    fun smallAppBar_withSubtitle_lightTheme() {
+        composeTestRule.setMaterialContent(lightColorScheme()) {
+            Box(Modifier.testTag(TopAppBarTestTag)) {
+                TopAppBar(
+                    navigationIcon = {
+                        IconButton(onClick = { /* doSomething() */ }) {
+                            Icon(
+                                imageVector = Icons.AutoMirrored.Filled.ArrowBack,
+                                contentDescription = "Back"
+                            )
+                        }
+                    },
+                    title = { Text("Title") },
+                    subtitle = { Text("Subtitle") },
+                    actions = {
+                        IconButton(onClick = { /* doSomething() */ }) {
+                            Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Like")
+                        }
+                    }
+                )
+            }
+        }
+
+        assertAppBarAgainstGolden(goldenIdentifier = "smallAppBar_withSubtitle_lightTheme")
+    }
+
+    @Test
+    fun smallAppBar_withoutSubtitle_lightTheme() {
+        composeTestRule.setMaterialContent(lightColorScheme()) {
+            Box(Modifier.testTag(TopAppBarTestTag)) {
+                TopAppBar(
+                    navigationIcon = {
+                        IconButton(onClick = { /* doSomething() */ }) {
+                            Icon(
+                                imageVector = Icons.AutoMirrored.Filled.ArrowBack,
+                                contentDescription = "Back"
+                            )
+                        }
+                    },
+                    title = { Text("Title") },
+                    subtitle = {},
+                    actions = {
+                        IconButton(onClick = { /* doSomething() */ }) {
+                            Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Like")
+                        }
+                    }
+                )
+            }
+        }
+
+        assertAppBarAgainstGolden(goldenIdentifier = "smallAppBar_withoutSubtitle_lightTheme")
+    }
+
+    @Test
     fun smallAppBar_lightTheme_clipsWhenCollapsedWithInsets() {
         composeTestRule.setMaterialContent(lightColorScheme()) {
             val behavior = enterAlwaysScrollBehavior(rememberTopAppBarState())
@@ -170,6 +224,64 @@
     }
 
     @Test
+    fun centerAlignedAppBar_withSubtitle_lightTheme() {
+        composeTestRule.setMaterialContent(lightColorScheme()) {
+            Box(Modifier.testTag(TopAppBarTestTag)) {
+                TopAppBar(
+                    navigationIcon = {
+                        IconButton(onClick = { /* doSomething() */ }) {
+                            Icon(
+                                imageVector = Icons.AutoMirrored.Filled.ArrowBack,
+                                contentDescription = "Back"
+                            )
+                        }
+                    },
+                    title = { Text("Title") },
+                    subtitle = { Text("Subtitle") },
+                    titleHorizontalAlignment = TopAppBarTitleAlignment.Center,
+                    actions = {
+                        IconButton(onClick = { /* doSomething() */ }) {
+                            Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Like")
+                        }
+                    }
+                )
+            }
+        }
+
+        assertAppBarAgainstGolden(goldenIdentifier = "centerAlignedAppBar_withSubtitle_lightTheme")
+    }
+
+    @Test
+    fun centerAlignedAppBar_withoutSubtitle_lightTheme() {
+        composeTestRule.setMaterialContent(lightColorScheme()) {
+            Box(Modifier.testTag(TopAppBarTestTag)) {
+                TopAppBar(
+                    navigationIcon = {
+                        IconButton(onClick = { /* doSomething() */ }) {
+                            Icon(
+                                imageVector = Icons.AutoMirrored.Filled.ArrowBack,
+                                contentDescription = "Back"
+                            )
+                        }
+                    },
+                    title = { Text("Title") },
+                    subtitle = {},
+                    titleHorizontalAlignment = TopAppBarTitleAlignment.Center,
+                    actions = {
+                        IconButton(onClick = { /* doSomething() */ }) {
+                            Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Like")
+                        }
+                    }
+                )
+            }
+        }
+
+        assertAppBarAgainstGolden(
+            goldenIdentifier = "centerAlignedAppBar_withoutSubtitle_lightTheme"
+        )
+    }
+
+    @Test
     fun centerAlignedAppBar_darkTheme() {
         composeTestRule.setMaterialContent(darkColorScheme()) {
             Box(Modifier.testTag(TopAppBarTestTag)) {
@@ -222,6 +334,95 @@
     }
 
     @Test
+    fun mediumAppBar_centerAligned_withSubtitle_lightTheme() {
+        composeTestRule.setMaterialContent(lightColorScheme()) {
+            Box(Modifier.testTag(TopAppBarTestTag)) {
+                MediumTopAppBar(
+                    navigationIcon = {
+                        IconButton(onClick = { /* doSomething() */ }) {
+                            Icon(
+                                imageVector = Icons.AutoMirrored.Filled.ArrowBack,
+                                contentDescription = "Back"
+                            )
+                        }
+                    },
+                    title = { Text("Title") },
+                    subtitle = { Text("Subtitle") },
+                    titleHorizontalAlignment = TopAppBarTitleAlignment.Center,
+                    actions = {
+                        IconButton(onClick = { /* doSomething() */ }) {
+                            Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Like")
+                        }
+                    }
+                )
+            }
+        }
+
+        assertAppBarAgainstGolden(
+            goldenIdentifier = "mediumAppBar_centerAligned_withSubtitle_lightTheme"
+        )
+    }
+
+    @Test
+    fun mediumAppBar_centerAligned_withoutSubtitle_lightTheme() {
+        composeTestRule.setMaterialContent(lightColorScheme()) {
+            Box(Modifier.testTag(TopAppBarTestTag)) {
+                MediumTopAppBar(
+                    navigationIcon = {
+                        IconButton(onClick = { /* doSomething() */ }) {
+                            Icon(
+                                imageVector = Icons.AutoMirrored.Filled.ArrowBack,
+                                contentDescription = "Back"
+                            )
+                        }
+                    },
+                    title = { Text("Title") },
+                    subtitle = null,
+                    titleHorizontalAlignment = TopAppBarTitleAlignment.Center,
+                    actions = {
+                        IconButton(onClick = { /* doSomething() */ }) {
+                            Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Like")
+                        }
+                    }
+                )
+            }
+        }
+
+        assertAppBarAgainstGolden(
+            goldenIdentifier = "mediumAppBar_centerAligned_withoutSubtitle_lightTheme"
+        )
+    }
+
+    @Test
+    fun mediumAppBar_startAligned_withSubtitle_darkTheme() {
+        composeTestRule.setMaterialContent(darkColorScheme()) {
+            Box(Modifier.testTag(TopAppBarTestTag)) {
+                MediumTopAppBar(
+                    navigationIcon = {
+                        IconButton(onClick = { /* doSomething() */ }) {
+                            Icon(
+                                imageVector = Icons.AutoMirrored.Filled.ArrowBack,
+                                contentDescription = "Back"
+                            )
+                        }
+                    },
+                    title = { Text("Title") },
+                    subtitle = { Text("Subtitle") },
+                    actions = {
+                        IconButton(onClick = { /* doSomething() */ }) {
+                            Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Like")
+                        }
+                    }
+                )
+            }
+        }
+
+        assertAppBarAgainstGolden(
+            goldenIdentifier = "mediumAppBar_startAligned_withSubtitle_darkTheme"
+        )
+    }
+
+    @Test
     fun mediumAppBar_darkTheme() {
         composeTestRule.setMaterialContent(darkColorScheme()) {
             Box(Modifier.testTag(TopAppBarTestTag)) {
@@ -274,6 +475,95 @@
     }
 
     @Test
+    fun largeAppBar_centerAligned_withSubtitle_lightTheme() {
+        composeTestRule.setMaterialContent(lightColorScheme()) {
+            Box(Modifier.testTag(TopAppBarTestTag)) {
+                LargeTopAppBar(
+                    navigationIcon = {
+                        IconButton(onClick = { /* doSomething() */ }) {
+                            Icon(
+                                imageVector = Icons.AutoMirrored.Filled.ArrowBack,
+                                contentDescription = "Back"
+                            )
+                        }
+                    },
+                    title = { Text("Title") },
+                    subtitle = { Text("Subtitle") },
+                    titleHorizontalAlignment = TopAppBarTitleAlignment.Center,
+                    actions = {
+                        IconButton(onClick = { /* doSomething() */ }) {
+                            Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Like")
+                        }
+                    }
+                )
+            }
+        }
+
+        assertAppBarAgainstGolden(
+            goldenIdentifier = "largeAppBar_centerAligned_withSubtitle_lightTheme"
+        )
+    }
+
+    @Test
+    fun largeAppBar_centerAligned_withoutSubtitle_lightTheme() {
+        composeTestRule.setMaterialContent(lightColorScheme()) {
+            Box(Modifier.testTag(TopAppBarTestTag)) {
+                LargeTopAppBar(
+                    navigationIcon = {
+                        IconButton(onClick = { /* doSomething() */ }) {
+                            Icon(
+                                imageVector = Icons.AutoMirrored.Filled.ArrowBack,
+                                contentDescription = "Back"
+                            )
+                        }
+                    },
+                    title = { Text("Title") },
+                    subtitle = null,
+                    titleHorizontalAlignment = TopAppBarTitleAlignment.Center,
+                    actions = {
+                        IconButton(onClick = { /* doSomething() */ }) {
+                            Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Like")
+                        }
+                    }
+                )
+            }
+        }
+
+        assertAppBarAgainstGolden(
+            goldenIdentifier = "largeAppBar_centerAligned_withoutSubtitle_lightTheme"
+        )
+    }
+
+    @Test
+    fun largeAppBar_startAligned_withSubtitle_darkTheme() {
+        composeTestRule.setMaterialContent(darkColorScheme()) {
+            Box(Modifier.testTag(TopAppBarTestTag)) {
+                LargeTopAppBar(
+                    navigationIcon = {
+                        IconButton(onClick = { /* doSomething() */ }) {
+                            Icon(
+                                imageVector = Icons.AutoMirrored.Filled.ArrowBack,
+                                contentDescription = "Back"
+                            )
+                        }
+                    },
+                    title = { Text("Title") },
+                    subtitle = { Text("Subtitle") },
+                    actions = {
+                        IconButton(onClick = { /* doSomething() */ }) {
+                            Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Like")
+                        }
+                    }
+                )
+            }
+        }
+
+        assertAppBarAgainstGolden(
+            goldenIdentifier = "largeAppBar_startAligned_withSubtitle_darkTheme"
+        )
+    }
+
+    @Test
     fun largeAppBar_darkTheme() {
         composeTestRule.setMaterialContent(darkColorScheme()) {
             Box(Modifier.testTag(TopAppBarTestTag)) {
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/AppBarTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/AppBarTest.kt
index 410f4d9..d3e034f 100644
--- a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/AppBarTest.kt
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/AppBarTest.kt
@@ -37,6 +37,7 @@
 import androidx.compose.material3.tokens.TopAppBarMediumTokens
 import androidx.compose.material3.tokens.TopAppBarSmallCenteredTokens
 import androidx.compose.material3.tokens.TopAppBarSmallTokens
+import androidx.compose.material3.tokens.TypographyKeyTokens
 import androidx.compose.runtime.Composable
 import androidx.compose.testutils.assertContainsColor
 import androidx.compose.ui.Modifier
@@ -85,7 +86,7 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 
-@OptIn(ExperimentalMaterial3Api::class)
+@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
 @MediumTest
 @RunWith(AndroidJUnit4::class)
 class AppBarTest {
@@ -110,6 +111,17 @@
     }
 
     @Test
+    fun smallTopAppBar_withSubtitle() {
+        val subtitle = "Subtitle"
+        rule.setMaterialContent(lightColorScheme()) {
+            Box(Modifier.testTag(TopAppBarTestTag)) {
+                TopAppBar(title = { Text("Title") }, subtitle = { Text(subtitle) })
+            }
+        }
+        rule.onNodeWithText(subtitle).assertIsDisplayed()
+    }
+
+    @Test
     fun smallTopAppBar_default_positioning() {
         rule.setMaterialContent(lightColorScheme()) {
             Box(Modifier.testTag(TopAppBarTestTag)) {
@@ -153,6 +165,24 @@
         assertThat(textStyle).isEqualTo(expectedTextStyle)
     }
 
+    @Test
+    fun smallTopAppBar_subtitleDefaultStyle() {
+        var textStyle: TextStyle? = null
+        var expectedTextStyle: TextStyle? = null
+        rule.setMaterialContent(lightColorScheme()) {
+            TopAppBar(
+                title = { Text("Title") },
+                subtitle = {
+                    Text("Subtitle")
+                    textStyle = LocalTextStyle.current
+                    expectedTextStyle = TypographyKeyTokens.LabelMedium.value // TODO tokens
+                }
+            )
+        }
+        assertThat(textStyle).isNotNull()
+        assertThat(textStyle).isEqualTo(expectedTextStyle)
+    }
+
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
     @Test
     fun smallTopAppBar_contentColor() {
@@ -331,6 +361,17 @@
     }
 
     @Test
+    fun centerAlignedTopAppBar_withSubtitle() {
+        val subtitle = "Subtitle"
+        rule.setMaterialContent(lightColorScheme()) {
+            Box(Modifier.testTag(TopAppBarTestTag)) {
+                TopAppBar(title = { Text("Title") }, subtitle = { Text(subtitle) })
+            }
+        }
+        rule.onNodeWithText(subtitle).assertIsDisplayed()
+    }
+
+    @Test
     fun centerAlignedTopAppBar_default_positioning() {
         rule.setMaterialContent(lightColorScheme()) {
             Box(Modifier.testTag(TopAppBarTestTag)) {
@@ -450,6 +491,24 @@
     }
 
     @Test
+    fun centerAlignedTopAppBar_subtitleDefaultStyle() {
+        var textStyle: TextStyle? = null
+        var expectedTextStyle: TextStyle? = null
+        rule.setMaterialContent(lightColorScheme()) {
+            TopAppBar(
+                title = { Text("Title") },
+                subtitle = {
+                    Text("Subtitle")
+                    textStyle = LocalTextStyle.current
+                    expectedTextStyle = TypographyKeyTokens.LabelMedium.value // TODO tokens
+                }
+            )
+        }
+        assertThat(textStyle).isNotNull()
+        assertThat(textStyle).isEqualTo(expectedTextStyle)
+    }
+
+    @Test
     fun centerAlignedTopAppBar_measureWithNonZeroMinWidth() {
         var appBarSize = IntSize.Zero
         rule.setMaterialContent(lightColorScheme()) {
@@ -670,6 +729,7 @@
             appBarMaxHeight = TopAppBarMediumTokens.ContainerHeight,
             appBarMinHeight = TopAppBarSmallTokens.ContainerHeight,
             titleContentColor = Color.Unspecified,
+            subtitleContentColor = Color.Unspecified,
             content = content
         )
     }
@@ -691,6 +751,59 @@
             appBarMaxHeight = TopAppBarMediumTokens.ContainerHeight,
             appBarMinHeight = TopAppBarSmallTokens.ContainerHeight,
             titleContentColor = Color.Green,
+            subtitleContentColor = Color.Unspecified,
+            content = content
+        )
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    @Test
+    fun mediumTopAppBar_scrolledColorsWithCustomTitleAndSubtitleTextColor() {
+        val content =
+            @Composable { scrollBehavior: TopAppBarScrollBehavior? ->
+                MediumTopAppBar(
+                    modifier = Modifier.testTag(TopAppBarTestTag),
+                    title = {
+                        Text(text = "Title", Modifier.testTag(TitleTestTag), color = Color.Green)
+                    },
+                    subtitle = {
+                        Text(
+                            text = "Subtitle",
+                            Modifier.testTag(SubtitleTestTag),
+                            color = Color.Green
+                        )
+                    },
+                    scrollBehavior = scrollBehavior
+                )
+            }
+        assertMediumOrLargeScrolledColors(
+            appBarMaxHeight = TopAppBarDefaults.MediumAppBarWithSubtitleExpandedHeight,
+            appBarMinHeight = TopAppBarSmallTokens.ContainerHeight,
+            titleContentColor = Color.Green,
+            subtitleContentColor = Color.Green,
+            content = content
+        )
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    @Test
+    fun mediumTopAppBar_scrolledColorsWithCustomTitleAndWithoutSubtitleTextColor() {
+        val content =
+            @Composable { scrollBehavior: TopAppBarScrollBehavior? ->
+                MediumTopAppBar(
+                    modifier = Modifier.testTag(TopAppBarTestTag),
+                    title = {
+                        Text(text = "Title", Modifier.testTag(TitleTestTag), color = Color.Green)
+                    },
+                    subtitle = null,
+                    scrollBehavior = scrollBehavior
+                )
+            }
+        assertMediumOrLargeScrolledColors(
+            appBarMaxHeight = TopAppBarDefaults.MediumAppBarWithoutSubtitleExpandedHeight,
+            appBarMinHeight = TopAppBarSmallTokens.ContainerHeight,
+            titleContentColor = Color.Green,
+            subtitleContentColor = Color.Unspecified,
             content = content
         )
     }
@@ -723,7 +836,29 @@
         assertMediumOrLargeScrolledSemantics(
             TopAppBarMediumTokens.ContainerHeight,
             TopAppBarSmallTokens.ContainerHeight,
-            content
+            content,
+            withSubtitle = false
+        )
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    @Test
+    fun mediumTopAppBar_withSubtitle_semantics() {
+        val content =
+            @Composable { scrollBehavior: TopAppBarScrollBehavior? ->
+                MediumTopAppBar(
+                    modifier = Modifier.testTag(TopAppBarTestTag),
+                    title = { Text("Title", Modifier.testTag(TitleTestTag)) },
+                    subtitle = { Text("Subtitle", Modifier.testTag(SubtitleTestTag)) },
+                    scrollBehavior = scrollBehavior
+                )
+            }
+
+        assertMediumOrLargeScrolledSemantics(
+            TopAppBarMediumTokens.ContainerHeight,
+            TopAppBarSmallTokens.ContainerHeight,
+            content,
+            withSubtitle = true
         )
     }
 
@@ -741,7 +876,28 @@
         assertMediumOrLargeScrolledSemantics(
             TopAppBarLargeTokens.ContainerHeight,
             TopAppBarSmallTokens.ContainerHeight,
-            content
+            content,
+            withSubtitle = false
+        )
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    @Test
+    fun largeTopAppBar_withSubtitle_semantics() {
+        val content =
+            @Composable { scrollBehavior: TopAppBarScrollBehavior? ->
+                LargeTopAppBar(
+                    modifier = Modifier.testTag(TopAppBarTestTag),
+                    title = { Text("Title", Modifier.testTag(TitleTestTag)) },
+                    subtitle = { Text("Subtitle", Modifier.testTag(SubtitleTestTag)) },
+                    scrollBehavior = scrollBehavior
+                )
+            }
+        assertMediumOrLargeScrolledSemantics(
+            TopAppBarLargeTokens.ContainerHeight,
+            TopAppBarSmallTokens.ContainerHeight,
+            content,
+            withSubtitle = true
         )
     }
 
@@ -862,6 +1018,7 @@
             appBarMaxHeight = TopAppBarLargeTokens.ContainerHeight,
             appBarMinHeight = TopAppBarSmallTokens.ContainerHeight,
             titleContentColor = Color.Unspecified,
+            subtitleContentColor = Color.Unspecified,
             content = content
         )
     }
@@ -883,6 +1040,59 @@
             appBarMaxHeight = TopAppBarLargeTokens.ContainerHeight,
             appBarMinHeight = TopAppBarSmallTokens.ContainerHeight,
             titleContentColor = Color.Red,
+            subtitleContentColor = Color.Unspecified,
+            content = content
+        )
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    @Test
+    fun largeTopAppBar_scrolledColorsWithCustomTitleAndSubtitleTextColor() {
+        val content =
+            @Composable { scrollBehavior: TopAppBarScrollBehavior? ->
+                LargeTopAppBar(
+                    modifier = Modifier.testTag(TopAppBarTestTag),
+                    title = {
+                        Text(text = "Title", Modifier.testTag(TitleTestTag), color = Color.Red)
+                    },
+                    subtitle = {
+                        Text(
+                            text = "Subtitle",
+                            Modifier.testTag(SubtitleTestTag),
+                            color = Color.Red
+                        )
+                    },
+                    scrollBehavior = scrollBehavior,
+                )
+            }
+        assertMediumOrLargeScrolledColors(
+            appBarMaxHeight = TopAppBarDefaults.LargeAppBarWithSubtitleExpandedHeight,
+            appBarMinHeight = TopAppBarSmallTokens.ContainerHeight,
+            titleContentColor = Color.Red,
+            subtitleContentColor = Color.Red,
+            content = content
+        )
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    @Test
+    fun largeTopAppBar_scrolledColorsWithCustomTitleAndWithoutSubtitleTextColor() {
+        val content =
+            @Composable { scrollBehavior: TopAppBarScrollBehavior? ->
+                LargeTopAppBar(
+                    modifier = Modifier.testTag(TopAppBarTestTag),
+                    title = {
+                        Text(text = "Title", Modifier.testTag(TitleTestTag), color = Color.Red)
+                    },
+                    subtitle = null,
+                    scrollBehavior = scrollBehavior,
+                )
+            }
+        assertMediumOrLargeScrolledColors(
+            appBarMaxHeight = TopAppBarDefaults.LargeAppBarWithoutSubtitleExpandedHeight,
+            appBarMinHeight = TopAppBarSmallTokens.ContainerHeight,
+            titleContentColor = Color.Red,
+            subtitleContentColor = Color.Unspecified,
             content = content
         )
     }
@@ -1591,6 +1801,7 @@
      * @param appBarMaxHeight the max height of the app bar [content]
      * @param appBarMinHeight the min height of the app bar [content]
      * @param titleContentColor text content color expected for the app bar's title.
+     * @param subtitleContentColor text content color expected for the app bar's subtitle.
      * @param content a Composable that adds a MediumTopAppBar or a LargeTopAppBar
      */
     @OptIn(ExperimentalMaterial3Api::class)
@@ -1599,6 +1810,7 @@
         appBarMaxHeight: Dp,
         appBarMinHeight: Dp,
         titleContentColor: Color,
+        subtitleContentColor: Color,
         content: @Composable (TopAppBarScrollBehavior?) -> Unit
     ) {
         // Note: This value is specifically picked to avoid precision issues when asserting the
@@ -1608,6 +1820,7 @@
         var fullyCollapsedContainerColor: Color = Color.Unspecified
         var expandedAppBarBackgroundColor: Color = Color.Unspecified
         var titleColor = titleContentColor
+        var subtitleColor = subtitleContentColor
         lateinit var scrollBehavior: TopAppBarScrollBehavior
         rule.setMaterialContent(lightColorScheme()) {
             scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
@@ -1623,6 +1836,9 @@
             if (titleColor == Color.Unspecified) {
                 titleColor = TopAppBarDefaults.mediumTopAppBarColors().titleContentColor
             }
+            if (subtitleColor == Color.Unspecified) {
+                subtitleColor = TopAppBarDefaults.mediumTopAppBarColors().titleContentColor
+            }
 
             with(LocalDensity.current) {
                 fullyCollapsedHeightOffsetPx = fullyCollapsedOffsetDp.toPx()
@@ -1685,13 +1901,15 @@
      * @param appBarMaxHeight the max height of the app bar [content]
      * @param appBarMinHeight the min height of the app bar [content]
      * @param content a Composable that adds a MediumTopAppBar or a LargeTopAppBar
+     * @param withSubtitle whether a subtitle is present
      */
     @OptIn(ExperimentalMaterial3Api::class)
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
     private fun assertMediumOrLargeScrolledSemantics(
         appBarMaxHeight: Dp,
         appBarMinHeight: Dp,
-        content: @Composable (TopAppBarScrollBehavior?) -> Unit
+        content: @Composable (TopAppBarScrollBehavior?) -> Unit,
+        withSubtitle: Boolean
     ) {
         val fullyCollapsedOffsetDp = appBarMaxHeight - appBarMinHeight
         val oneThirdCollapsedOffsetDp = fullyCollapsedOffsetDp / 3
@@ -1711,6 +1929,9 @@
         // Asserting that only one semantic title node is returned after the clearAndSetSemantics is
         // applied to the merged tree according to the alpha values of the titles.
         assertSingleTitleSemanticNode()
+        if (withSubtitle) {
+            assertSingleSubtitleSemanticNode()
+        }
 
         // Simulate 1/3 collapsed content.
         rule.runOnIdle {
@@ -1721,6 +1942,9 @@
 
         // Assert that only one semantic title node is available while scrolling the app bar.
         assertSingleTitleSemanticNode()
+        if (withSubtitle) {
+            assertSingleSubtitleSemanticNode()
+        }
 
         // Simulate fully collapsed content.
         rule.runOnIdle {
@@ -1731,6 +1955,9 @@
 
         // Assert that only one semantic title node is available.
         assertSingleTitleSemanticNode()
+        if (withSubtitle) {
+            assertSingleSubtitleSemanticNode()
+        }
     }
 
     /** Asserts that only one semantic node exists at app bar title when the tree is merged. */
@@ -1742,6 +1969,15 @@
         mergedTitleNodes.assertCountEquals(1)
     }
 
+    /** Asserts that only one semantic node exists at app bar subtitle when the tree is merged. */
+    private fun assertSingleSubtitleSemanticNode() {
+        val unmergedSubtitleNodes = rule.onAllNodesWithTag(SubtitleTestTag, useUnmergedTree = true)
+        unmergedSubtitleNodes.assertCountEquals(2)
+
+        val mergedSubtitleNodes = rule.onAllNodesWithTag(SubtitleTestTag, useUnmergedTree = false)
+        mergedSubtitleNodes.assertCountEquals(1)
+    }
+
     /**
      * An [IconButton] with an [Icon] inside for testing positions.
      *
@@ -1775,5 +2011,6 @@
     private val BottomAppBarTestTag = "bottomAppBar"
     private val NavigationIconTestTag = "navigationIcon"
     private val TitleTestTag = "title"
+    private val SubtitleTestTag = "subtitle"
     private val ActionsTestTag = "actions"
 }
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/ColorUtilTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/ColorUtilTest.kt
index a281147..c308447 100644
--- a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/ColorUtilTest.kt
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/ColorUtilTest.kt
@@ -16,10 +16,16 @@
 
 package androidx.compose.material3
 
+import androidx.compose.material3.internal.colorUtil.Cam
+import androidx.compose.material3.internal.colorUtil.CamUtils.lstarFromInt
+import androidx.compose.material3.internal.colorUtil.CamUtils.yFromLstar
+import androidx.compose.material3.internal.colorUtil.Frame
 import androidx.compose.ui.graphics.Color
 import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
 import androidx.test.filters.SmallTest
 import com.google.common.truth.Truth.assertThat
+import org.junit.Assert.assertEquals
 import org.junit.Test
 import org.junit.runner.RunWith
 
@@ -167,6 +173,192 @@
         assertColorWithinTolerance(Color(0xFFFFCDFF), Color.Blue.setLuminance(100f), 1f)
     }
 
+    @Test
+    fun yFromMidgray() {
+        assertEquals(18.418, yFromLstar(50.0), 0.001)
+    }
+
+    @Test
+    fun yFromBlack() {
+        assertEquals(0.0, yFromLstar(0.0), 0.001)
+    }
+
+    @Test
+    fun yFromWhite() {
+        assertEquals(100.0, yFromLstar(100.0), 0.001)
+    }
+
+    @Test
+    fun camFromRed() {
+        val cam: Cam = Cam.fromInt(RED)
+        assertEquals(46.445f, cam.j, 0.001f)
+        assertEquals(113.357f, cam.chroma, 0.001f)
+        assertEquals(27.408f, cam.hue, 0.001f)
+        assertEquals(89.494f, cam.m, 0.001f)
+        assertEquals(91.889f, cam.s, 0.001f)
+    }
+
+    @Test
+    fun camFromGreen() {
+        val cam: Cam = Cam.fromInt(GREEN)
+        assertEquals(79.331f, cam.j, 0.001f)
+        assertEquals(108.410f, cam.chroma, 0.001f)
+        assertEquals(142.139f, cam.hue, 0.001f)
+        assertEquals(85.587f, cam.m, 0.001f)
+        assertEquals(78.604f, cam.s, 0.001f)
+    }
+
+    @Test
+    fun camFromBlue() {
+        val cam: Cam = Cam.fromInt(BLUE)
+        assertEquals(25.465f, cam.j, 0.001f)
+        assertEquals(87.230f, cam.chroma, 0.001f)
+        assertEquals(282.788f, cam.hue, 0.001f)
+        assertEquals(68.867f, cam.m, 0.001f)
+        assertEquals(93.674f, cam.s, 0.001f)
+    }
+
+    @Test
+    fun camFromBlack() {
+        val cam: Cam = Cam.fromInt(BLACK)
+        assertEquals(0.0f, cam.j, 0.001f)
+        assertEquals(0.0f, cam.chroma, 0.001f)
+        assertEquals(0.0f, cam.hue, 0.001f)
+        assertEquals(0.0f, cam.m, 0.001f)
+        assertEquals(0.0f, cam.s, 0.001f)
+    }
+
+    @Test
+    fun camFromWhite() {
+        val cam: Cam = Cam.fromInt(WHITE)
+        assertEquals(100.0f, cam.j, 0.001f)
+        assertEquals(2.869f, cam.chroma, 0.001f)
+        assertEquals(209.492f, cam.hue, 0.001f)
+        assertEquals(2.265f, cam.m, 0.001f)
+        assertEquals(12.068f, cam.s, 0.001f)
+    }
+
+    @Test
+    fun redFromGamutMap() {
+        val cam: Cam = Cam.fromInt(RED)
+        val color: Int = Cam.getInt(cam.hue, cam.chroma, lstarFromInt(RED))
+        assertEquals(RED, color)
+    }
+
+    @Test
+    fun greenFromGamutMap() {
+        val cam: Cam = Cam.fromInt(GREEN)
+        val color: Int = Cam.getInt(cam.hue, cam.chroma, lstarFromInt(GREEN))
+        assertEquals(GREEN, color)
+    }
+
+    @Test
+    fun blueFromGamutMap() {
+        val cam: Cam = Cam.fromInt(BLUE)
+        val color: Int = Cam.getInt(cam.hue, cam.chroma, lstarFromInt(BLUE))
+        assertEquals(BLUE, color)
+    }
+
+    @Test
+    fun whiteFromGamutMap() {
+        val cam: Cam = Cam.fromInt(WHITE)
+        val color: Int = Cam.getInt(cam.hue, cam.chroma, lstarFromInt(WHITE))
+        assertEquals(WHITE, color)
+    }
+
+    @Test
+    fun blackFromGamutMap() {
+        val cam: Cam = Cam.fromInt(BLACK)
+        val color: Int = Cam.getInt(cam.hue, cam.chroma, lstarFromInt(BLACK))
+        assertEquals(BLACK, color)
+    }
+
+    @Test
+    fun midgrayFromGamutMap() {
+        val cam: Cam = Cam.fromInt(MIDGRAY)
+        val color: Int = Cam.getInt(cam.hue, cam.chroma, lstarFromInt(MIDGRAY))
+        assertEquals(MIDGRAY, color)
+    }
+
+    @Test
+    fun randomGreenFromGamutMap() {
+        val colorToTest = -0xff6e00
+        val cam: Cam = Cam.fromInt(colorToTest)
+        val color: Int = Cam.getInt(cam.hue, cam.chroma, lstarFromInt(colorToTest))
+        assertEquals(colorToTest.toLong(), color.toLong())
+    }
+
+    @Test
+    fun gamutMapArbitraryHCL() {
+        val color: Int = Cam.getInt(309.0f, 40.0f, 70.0f)
+        val cam: Cam = Cam.fromInt(color)
+
+        assertEquals(308.759f, cam.hue, 0.001f)
+        assertEquals(40.148f, cam.chroma, 0.001f)
+        assertEquals(70.029f, lstarFromInt(color), 0.001f)
+    }
+
+    @Test
+    fun ucsCoordinates() {
+        val cam: Cam = Cam.fromInt(RED)
+
+        assertEquals(59.584f, cam.jstar, 0.001f)
+        assertEquals(43.297f, cam.astar, 0.001f)
+        assertEquals(22.451f, cam.bstar, 0.001f)
+    }
+
+    @Test
+    fun deltaEWhiteToBlack() {
+        assertEquals(25.661f, Cam.fromInt(WHITE).distance(Cam.fromInt(BLACK)), 0.001f)
+    }
+
+    @Test
+    fun deltaERedToBlue() {
+        assertEquals(21.415f, Cam.fromInt(RED).distance(Cam.fromInt(BLUE)), 0.001f)
+    }
+
+    @Test
+    fun viewingConditions_default() {
+        val vc = Frame.Default
+
+        assertEquals(0.184f, vc.n, 0.001f)
+        assertEquals(29.981f, vc.aw, 0.001f)
+        assertEquals(1.016f, vc.nbb, 0.001f)
+        assertEquals(1.021f, vc.rgbD[0], 0.001f)
+        assertEquals(0.986f, vc.rgbD[1], 0.001f)
+        assertEquals(0.933f, vc.rgbD[2], 0.001f)
+        assertEquals(0.789f, vc.flRoot, 0.001f)
+    }
+
+    @LargeTest
+    @Test
+    fun testHctReflexivity() {
+        for (i in 0..0x00ffffff) {
+            val color = -0x1000000 or i
+            val hct: Cam = Cam.fromInt(color)
+            val reconstructedFromHct: Int = Cam.getInt(hct.hue, hct.chroma, lstarFromInt(color))
+
+            assertEquals(
+                "input was " +
+                    Integer.toHexString(color) +
+                    "; output was " +
+                    Integer.toHexString(reconstructedFromHct),
+                color.toLong(),
+                reconstructedFromHct.toLong()
+            )
+        }
+    }
+
+    companion object {
+        const val BLACK: Int = -0x1000000
+        const val WHITE: Int = -0x1
+        const val MIDGRAY: Int = -0x888889
+
+        const val RED: Int = -0x10000
+        const val GREEN: Int = -0xff0100
+        const val BLUE: Int = -0xffff01
+    }
+
     private fun assertColorWithinTolerance(expected: Color, actual: Color, tolerance: Float = 1f) {
         assertThat(expected.red).isWithin(tolerance).of(actual.red)
         assertThat(expected.green).isWithin(tolerance).of(actual.green)
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/ExposedDropdownMenuTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/ExposedDropdownMenuTest.kt
index 34b5307..7b1c830 100644
--- a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/ExposedDropdownMenuTest.kt
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/ExposedDropdownMenuTest.kt
@@ -346,7 +346,7 @@
                     ) {
                         TextField(
                             modifier =
-                                Modifier.menuAnchor(MenuAnchorType.PrimaryEditable)
+                                Modifier.menuAnchor(ExposedDropdownMenuAnchorType.PrimaryEditable)
                                     .then(
                                         if (index == testIndex)
                                             Modifier.testTag(TFTag).onSizeChanged {
@@ -433,7 +433,8 @@
                     onExpandedChange = {},
                 ) {
                     TextField(
-                        modifier = Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable),
+                        modifier =
+                            Modifier.menuAnchor(ExposedDropdownMenuAnchorType.PrimaryNotEditable),
                         readOnly = true,
                         value = "",
                         onValueChange = {},
@@ -517,7 +518,8 @@
 
                 ExposedDropdownMenuBox(expanded = true, onExpandedChange = {}) {
                     TextField(
-                        modifier = Modifier.menuAnchor(MenuAnchorType.PrimaryEditable),
+                        modifier =
+                            Modifier.menuAnchor(ExposedDropdownMenuAnchorType.PrimaryEditable),
                         value = "",
                         onValueChange = {},
                         label = { Text("Label") },
@@ -560,7 +562,8 @@
                                                 onValueChange = {},
                                                 modifier =
                                                     Modifier.menuAnchor(
-                                                        MenuAnchorType.PrimaryEditable
+                                                        ExposedDropdownMenuAnchorType
+                                                            .PrimaryEditable
                                                     ),
                                             )
                                             ExposedDropdownMenu(
@@ -602,7 +605,8 @@
                 ) {
                     scrollState = rememberScrollState()
                     TextField(
-                        modifier = Modifier.menuAnchor(MenuAnchorType.PrimaryEditable),
+                        modifier =
+                            Modifier.menuAnchor(ExposedDropdownMenuAnchorType.PrimaryEditable),
                         value = "",
                         onValueChange = {},
                         label = { Text("Label") },
@@ -751,9 +755,9 @@
                             .menuAnchor(
                                 type =
                                     if (editable) {
-                                        MenuAnchorType.PrimaryEditable
+                                        ExposedDropdownMenuAnchorType.PrimaryEditable
                                     } else {
-                                        MenuAnchorType.PrimaryNotEditable
+                                        ExposedDropdownMenuAnchorType.PrimaryNotEditable
                                     },
                                 enabled = enabled,
                             )
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/IconButtonTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/IconButtonTest.kt
index 7d0caf9..2a8c1db 100644
--- a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/IconButtonTest.kt
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/IconButtonTest.kt
@@ -15,6 +15,7 @@
  */
 package androidx.compose.material3
 
+import android.os.Build
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.requiredSize
@@ -31,6 +32,7 @@
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.setValue
+import androidx.compose.testutils.assertShape
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.geometry.Offset
@@ -38,6 +40,7 @@
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.semantics.Role
 import androidx.compose.ui.semantics.SemanticsProperties
+import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.test.SemanticsMatcher
 import androidx.compose.ui.test.assert
 import androidx.compose.ui.test.assertHeightIsEqualTo
@@ -50,6 +53,7 @@
 import androidx.compose.ui.test.assertTouchHeightIsEqualTo
 import androidx.compose.ui.test.assertTouchWidthIsEqualTo
 import androidx.compose.ui.test.assertWidthIsEqualTo
+import androidx.compose.ui.test.captureToImage
 import androidx.compose.ui.test.click
 import androidx.compose.ui.test.hasClickAction
 import androidx.compose.ui.test.isToggleable
@@ -61,6 +65,7 @@
 import androidx.compose.ui.unit.dp
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
+import androidx.test.filters.SdkSuppress
 import com.google.common.truth.Truth
 import org.junit.Rule
 import org.junit.Test
@@ -87,6 +92,41 @@
             .assertTouchHeightIsEqualTo(IconButtonAccessibilitySize)
     }
 
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    @Test
+    fun iconButton_wideShape() {
+        val shape = ShapeDefaults.Medium
+        val background = Color.Yellow
+        val iconButtonColor = Color.Blue
+        rule.setMaterialContent(lightColorScheme()) {
+            Surface(color = background) {
+                Box {
+                    IconButton(
+                        onClick = { /* doSomething() */ },
+                        modifier =
+                            Modifier.semantics(mergeDescendants = true) {}
+                                .testTag(IconTestTag)
+                                .size(50.dp),
+                        shape = shape,
+                        colors =
+                            IconButtonDefaults.iconButtonColors(containerColor = iconButtonColor)
+                    ) {}
+                }
+            }
+        }
+
+        rule
+            .onNodeWithTag(IconTestTag)
+            .captureToImage()
+            .assertShape(
+                density = rule.density,
+                shape = shape,
+                shapeColor = iconButtonColor,
+                backgroundColor = background,
+                shapeOverlapPixelCount = with(rule.density) { 1.dp.toPx() }
+            )
+    }
+
     @OptIn(ExperimentalMaterial3Api::class)
     @Test
     fun iconButton_sizeWithoutMinTargetEnforcement() {
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/LoadingIndicatorScreenshotTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/LoadingIndicatorScreenshotTest.kt
new file mode 100644
index 0000000..61febfd
--- /dev/null
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/LoadingIndicatorScreenshotTest.kt
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3
+
+import android.os.Build
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.wrapContentSize
+import androidx.compose.testutils.assertAgainstGolden
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.captureToImage
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.test.filters.MediumTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.screenshot.AndroidXScreenshotTestRule
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@OptIn(ExperimentalMaterial3ExpressiveApi::class)
+@MediumTest
+@RunWith(Parameterized::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+class LoadingIndicatorScreenshotTest(private val scheme: ColorSchemeWrapper) {
+    @get:Rule val rule = createComposeRule()
+
+    @get:Rule val screenshotRule = AndroidXScreenshotTestRule(GOLDEN_MATERIAL3)
+
+    private val wrap = Modifier.wrapContentSize(Alignment.TopStart)
+    private val wrapperTestTag = "loadingIndicatorWrapper"
+
+    @Test
+    fun loadingIndicator_determinate_start_progress() {
+        rule.setMaterialContent(scheme.colorScheme) {
+            Box(wrap.testTag(wrapperTestTag)) { LoadingIndicator(progress = { 0f }) }
+        }
+        assertIndicatorAgainstGolden("loadingIndicator_determinate_start_progress_${scheme.name}")
+    }
+
+    @Test
+    fun loadingIndicator_determinate_mid_progress() {
+        rule.setMaterialContent(scheme.colorScheme) {
+            Box(wrap.testTag(wrapperTestTag)) { LoadingIndicator(progress = { 0.5f }) }
+        }
+        assertIndicatorAgainstGolden("loadingIndicator_determinate_mid_progress_${scheme.name}")
+    }
+
+    @Test
+    fun loadingIndicator_determinate_end_progress() {
+        rule.setMaterialContent(scheme.colorScheme) {
+            Box(wrap.testTag(wrapperTestTag)) { LoadingIndicator(progress = { 1f }) }
+        }
+        assertIndicatorAgainstGolden("loadingIndicator_determinate_end_progress_${scheme.name}")
+    }
+
+    @Test
+    fun loadingIndicator_indeterminate() {
+        rule.mainClock.autoAdvance = false
+        rule.setMaterialContent(scheme.colorScheme) {
+            Box(wrap.testTag(wrapperTestTag)) { LoadingIndicator() }
+        }
+        assertIndicatorAgainstGolden("loadingIndicator_indeterminate_${scheme.name}")
+    }
+
+    @Test
+    fun loadingIndicator_indeterminate_withContainerColor() {
+        rule.mainClock.autoAdvance = false
+        rule.setMaterialContent(scheme.colorScheme) {
+            Box(wrap.testTag(wrapperTestTag)) {
+                LoadingIndicator(containerColor = LoadingIndicatorDefaults.ContainerColor)
+            }
+        }
+        assertIndicatorAgainstGolden(
+            "loadingIndicator_indeterminate_withContainerColor_${scheme.name}"
+        )
+    }
+
+    private fun assertIndicatorAgainstGolden(goldenName: String) {
+        rule
+            .onNodeWithTag(wrapperTestTag)
+            .captureToImage()
+            .assertAgainstGolden(screenshotRule, goldenName)
+    }
+
+    companion object {
+        private const val TestTag = "testTag"
+
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun parameters() =
+            arrayOf(
+                ColorSchemeWrapper("lightTheme", lightColorScheme()),
+                ColorSchemeWrapper("darkTheme", darkColorScheme()),
+            )
+    }
+
+    class ColorSchemeWrapper(val name: String, val colorScheme: ColorScheme) {
+        override fun toString(): String {
+            return name
+        }
+    }
+}
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/LoadingIndicatorTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/LoadingIndicatorTest.kt
new file mode 100644
index 0000000..636281c
--- /dev/null
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/LoadingIndicatorTest.kt
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3
+
+import androidx.compose.runtime.mutableFloatStateOf
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.semantics.ProgressBarRangeInfo
+import androidx.compose.ui.test.assertHeightIsEqualTo
+import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.assertRangeInfoEquals
+import androidx.compose.ui.test.assertWidthIsEqualTo
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalMaterial3ExpressiveApi::class)
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+class LoadingIndicatorTest {
+    @get:Rule val rule = createComposeRule()
+
+    @Test
+    fun nonMaterialSetContent() {
+        val tag = "indicator"
+        val progress = mutableFloatStateOf(0f)
+
+        rule.setContent {
+            LoadingIndicator(
+                modifier = Modifier.testTag(tag),
+                progress = { progress.value },
+            )
+        }
+
+        rule.onNodeWithTag(tag).assertIsDisplayed()
+    }
+
+    @Test
+    fun determinateLoadingIndicator_Progress() {
+        val tag = "indicator"
+        val progress = mutableFloatStateOf(0f)
+
+        rule.setMaterialContent(lightColorScheme()) {
+            LoadingIndicator(modifier = Modifier.testTag(tag), progress = { progress.value })
+        }
+
+        rule
+            .onNodeWithTag(tag)
+            .assertIsDisplayed()
+            .assertRangeInfoEquals(ProgressBarRangeInfo(0f, 0f..1f))
+
+        rule.runOnUiThread { progress.value = 0.5f }
+
+        rule
+            .onNodeWithTag(tag)
+            .assertIsDisplayed()
+            .assertRangeInfoEquals(ProgressBarRangeInfo(0.5f, 0f..1f))
+    }
+
+    @Test
+    fun determinateLoadingIndicator_ProgressIsCoercedInBounds() {
+        val tag = "indicator"
+        val progress = mutableStateOf(-1f)
+
+        rule.setMaterialContent(lightColorScheme()) {
+            LoadingIndicator(modifier = Modifier.testTag(tag), progress = { progress.value })
+        }
+
+        rule
+            .onNodeWithTag(tag)
+            .assertIsDisplayed()
+            .assertRangeInfoEquals(ProgressBarRangeInfo(0f, 0f..1f))
+
+        rule.runOnUiThread { progress.value = 1.5f }
+
+        rule
+            .onNodeWithTag(tag)
+            .assertIsDisplayed()
+            .assertRangeInfoEquals(ProgressBarRangeInfo(1f, 0f..1f))
+    }
+
+    @Test
+    fun determinateLoadingIndicator_Size() {
+        rule
+            .setMaterialContentForSizeAssertions { LoadingIndicator(progress = { 0f }) }
+            .assertWidthIsEqualTo(LoadingIndicatorDefaults.ContainerWidth)
+            .assertHeightIsEqualTo(LoadingIndicatorDefaults.ContainerHeight)
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun determinateLoadingIndicator_MinPolygons() {
+        rule.setMaterialContent(lightColorScheme()) {
+            LoadingIndicator(
+                progress = { 0f },
+                indicatorPolygons = listOf(MaterialShapes.PuffyDiamond)
+            )
+        }
+    }
+
+    @Test
+    fun indeterminateLoadingIndicator_Progress() {
+        val tag = "indicator"
+
+        rule.mainClock.autoAdvance = false
+        rule.setMaterialContent(lightColorScheme()) {
+            LoadingIndicator(modifier = Modifier.testTag(tag))
+        }
+
+        rule.mainClock.advanceTimeByFrame() // Kick off the animation
+
+        rule.onNodeWithTag(tag).assertRangeInfoEquals(ProgressBarRangeInfo.Indeterminate)
+    }
+
+    @Test
+    fun indeterminateLoadingIndicator_Size() {
+        rule.mainClock.autoAdvance = false
+        val contentToTest = rule.setMaterialContentForSizeAssertions { LoadingIndicator() }
+
+        rule.mainClock.advanceTimeByFrame() // Kick off the animation
+
+        contentToTest
+            .assertWidthIsEqualTo(LoadingIndicatorDefaults.ContainerWidth)
+            .assertHeightIsEqualTo(LoadingIndicatorDefaults.ContainerHeight)
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun indeterminateLoadingIndicator_MinPolygons() {
+        rule.setMaterialContent(lightColorScheme()) {
+            LoadingIndicator(indicatorPolygons = listOf(MaterialShapes.PuffyDiamond))
+        }
+    }
+}
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/MaterialShapesScreenshotTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/MaterialShapesScreenshotTest.kt
new file mode 100644
index 0000000..5a2855b
--- /dev/null
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/MaterialShapesScreenshotTest.kt
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3
+
+import android.os.Build
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.requiredSize
+import androidx.compose.foundation.layout.wrapContentSize
+import androidx.compose.foundation.lazy.grid.GridCells
+import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
+import androidx.compose.testutils.assertAgainstGolden
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.captureToImage
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.unit.dp
+import androidx.graphics.shapes.RoundedPolygon
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.screenshot.AndroidXScreenshotTestRule
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalMaterial3ExpressiveApi::class)
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+class MaterialShapesScreenshotTest() {
+    @get:Rule val rule = createComposeRule()
+
+    @get:Rule val screenshotRule = AndroidXScreenshotTestRule(GOLDEN_MATERIAL3)
+
+    private val wrap = Modifier.wrapContentSize(Alignment.TopStart)
+    private val wrapperTestTag = "materialShapesWrapper"
+
+    @Test
+    fun materialShapes_allShapes() {
+        rule.setMaterialContent(lightColorScheme()) {
+            Box(wrap.testTag(wrapperTestTag)) {
+                LazyVerticalGrid(
+                    columns = GridCells.FixedSize(64.dp),
+                    contentPadding = PaddingValues(2.dp),
+                    verticalArrangement = Arrangement.spacedBy(2.dp)
+                ) {
+                    allShapes().forEach { polygon ->
+                        item {
+                            Spacer(
+                                modifier =
+                                    Modifier.requiredSize(56.dp)
+                                        .clip(polygon.toShape())
+                                        .background(MaterialTheme.colorScheme.primary)
+                            )
+                        }
+                    }
+                }
+            }
+        }
+        assertIndicatorAgainstGolden("materialShapes_allShapes")
+    }
+
+    private fun allShapes(): List<RoundedPolygon> {
+        return listOf(
+            MaterialShapes.Circle,
+            MaterialShapes.Square,
+            MaterialShapes.Slanted,
+            MaterialShapes.Arch,
+            MaterialShapes.Fan,
+            MaterialShapes.Arrow,
+            MaterialShapes.SemiCircle,
+            MaterialShapes.Oval,
+            MaterialShapes.Pill,
+            MaterialShapes.Triangle,
+            MaterialShapes.Diamond,
+            MaterialShapes.ClamShell,
+            MaterialShapes.Pentagon,
+            MaterialShapes.Gem,
+            MaterialShapes.Sunny,
+            MaterialShapes.VerySunny,
+            MaterialShapes.Cookie4Sided,
+            MaterialShapes.Cookie6Sided,
+            MaterialShapes.Cookie7Sided,
+            MaterialShapes.Cookie9Sided,
+            MaterialShapes.Cookie12Sided,
+            MaterialShapes.Ghostish,
+            MaterialShapes.Clover4Leaf,
+            MaterialShapes.Clover8Leaf,
+            MaterialShapes.Burst,
+            MaterialShapes.SoftBurst,
+            MaterialShapes.Boom,
+            MaterialShapes.SoftBoom,
+            MaterialShapes.Flower,
+            MaterialShapes.Puffy,
+            MaterialShapes.PuffyDiamond,
+            MaterialShapes.PixelCircle,
+            MaterialShapes.PixelTriangle,
+            MaterialShapes.Bun,
+            MaterialShapes.Heart
+        )
+    }
+
+    private fun assertIndicatorAgainstGolden(goldenName: String) {
+        rule
+            .onNodeWithTag(wrapperTestTag)
+            .captureToImage()
+            .assertAgainstGolden(screenshotRule, goldenName)
+    }
+}
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/RippleTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/RippleTest.kt
index 99d79a0..2bb4788 100644
--- a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/RippleTest.kt
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/RippleTest.kt
@@ -556,6 +556,88 @@
     }
 
     /**
+     * Regression test for b/348379457 : going from enabled -> disabled -> enabled should show a
+     * valid ripple, and going to disabled after that should not crash.
+     */
+    @Test
+    fun rippleConfigurationToggleBetweenEnabledAndDisabled() {
+        val interactionSource = MutableInteractionSource()
+
+        val contentColor = Color.Black
+
+        var rippleConfiguration: RippleConfiguration? by mutableStateOf(RippleConfiguration())
+        val dragStart1 = DragInteraction.Start()
+        val dragStop1 = DragInteraction.Stop(dragStart1)
+        val dragStart2 = DragInteraction.Start()
+        val dragStop2 = DragInteraction.Stop(dragStart2)
+        val dragStart3 = DragInteraction.Start()
+
+        var scope: CoroutineScope? = null
+
+        rule.setContent {
+            scope = rememberCoroutineScope()
+            MaterialTheme {
+                Surface(contentColor = contentColor) {
+                    CompositionLocalProvider(
+                        LocalRippleConfiguration provides rippleConfiguration
+                    ) {
+                        Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
+                            RippleBoxWithBackground(interactionSource, ripple(), bounded = true)
+                        }
+                    }
+                }
+            }
+        }
+
+        rule.runOnIdle { scope!!.launch { interactionSource.emit(dragStart1) } }
+        rule.waitForIdle()
+
+        with(rule.onNodeWithTag(Tag)) {
+            val centerPixel =
+                captureToImage().asAndroidBitmap().run { getPixel(width / 2, height / 2) }
+
+            val expectedColor = calculateResultingRippleColor(contentColor, rippleOpacity = 0.16f)
+
+            Truth.assertThat(Color(centerPixel)).isEqualTo(expectedColor)
+        }
+
+        rule.runOnIdle { scope!!.launch { interactionSource.emit(dragStop1) } }
+        // Disable the ripple
+        rule.runOnIdle { rippleConfiguration = null }
+
+        rule.runOnIdle { scope!!.launch { interactionSource.emit(dragStart2) } }
+
+        with(rule.onNodeWithTag(Tag)) {
+            val centerPixel =
+                captureToImage().asAndroidBitmap().run { getPixel(width / 2, height / 2) }
+
+            // There should not be a ripple
+            Truth.assertThat(Color(centerPixel)).isEqualTo(RippleBoxBackgroundColor)
+        }
+
+        rule.runOnIdle { scope!!.launch { interactionSource.emit(dragStop2) } }
+        // Enable the ripple again
+        rule.runOnIdle { rippleConfiguration = RippleConfiguration() }
+
+        // The ripple should show again
+        rule.runOnIdle { scope!!.launch { interactionSource.emit(dragStart3) } }
+
+        with(rule.onNodeWithTag(Tag)) {
+            val centerPixel =
+                captureToImage().asAndroidBitmap().run { getPixel(width / 2, height / 2) }
+
+            val expectedColor = calculateResultingRippleColor(contentColor, rippleOpacity = 0.16f)
+
+            Truth.assertThat(Color(centerPixel)).isEqualTo(expectedColor)
+        }
+
+        // Disable the ripple again
+        rule.runOnIdle { rippleConfiguration = null }
+        // Should not crash
+        rule.waitForIdle()
+    }
+
+    /**
      * Asserts that the resultant color of the ripple on screen matches [expectedCenterPixelColor].
      *
      * @param interactionSource the [MutableInteractionSource] driving the ripple
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/SplitButtonScreenshotTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/SplitButtonScreenshotTest.kt
index ee35790..d0ae210 100644
--- a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/SplitButtonScreenshotTest.kt
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/SplitButtonScreenshotTest.kt
@@ -142,15 +142,20 @@
                         Icon(
                             Icons.Outlined.Edit,
                             contentDescription = "Localized description",
+                            modifier = Modifier.size(28.dp)
                         )
                         Spacer(Modifier.size(ButtonDefaults.IconSpacing))
-                        Text("My Button")
+                        Text("My Button", fontSize = 18.sp)
                     },
                     trailingContent = {
-                        Box(modifier = Modifier.size(44.dp), contentAlignment = Alignment.Center) {
+                        Box(
+                            modifier = Modifier.fillMaxHeight().aspectRatio(1f),
+                            contentAlignment = Alignment.Center
+                        ) {
                             Icon(
                                 Icons.Outlined.KeyboardArrowDown,
-                                modifier = Modifier.graphicsLayer { this.rotationZ = 180f },
+                                modifier =
+                                    Modifier.size(38.dp).graphicsLayer { this.rotationZ = 180f },
                                 contentDescription = "Localized description"
                             )
                         }
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/TextFieldTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/TextFieldTest.kt
index e2cb589..c934995 100644
--- a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/TextFieldTest.kt
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/TextFieldTest.kt
@@ -53,6 +53,7 @@
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.testutils.assertIsEqualTo
 import androidx.compose.testutils.assertPixels
 import androidx.compose.testutils.assertShape
 import androidx.compose.ui.ExperimentalComposeUiApi
@@ -86,6 +87,7 @@
 import androidx.compose.ui.test.assertWidthIsEqualTo
 import androidx.compose.ui.test.captureToImage
 import androidx.compose.ui.test.click
+import androidx.compose.ui.test.getBoundsInRoot
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.test.onChildren
 import androidx.compose.ui.test.onNodeWithTag
@@ -105,6 +107,7 @@
 import androidx.compose.ui.unit.Density
 import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.height
 import androidx.compose.ui.unit.sp
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
@@ -119,7 +122,6 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 
-@OptIn(ExperimentalMaterial3Api::class)
 @MediumTest
 @RunWith(AndroidJUnit4::class)
 class TextFieldTest {
@@ -175,6 +177,35 @@
     }
 
     @Test
+    fun testTextField_heightDoesNotChange_duringFocusAnimation() {
+        val numTicks = 5
+        val tick = TextFieldAnimationDuration / numTicks
+        rule.mainClock.autoAdvance = false
+
+        rule.setMaterialContent(lightColorScheme()) {
+            TextField(
+                modifier = Modifier.testTag(TextFieldTag),
+                value = "",
+                onValueChange = {},
+                label = { Text("Label") },
+            )
+        }
+
+        // click to focus
+        rule.onNodeWithTag(TextFieldTag).performClick()
+
+        repeat(numTicks + 1) {
+            rule
+                .onNodeWithTag(TextFieldTag)
+                .getBoundsInRoot()
+                .height
+                .assertIsEqualTo(ExpectedDefaultTextFieldHeight)
+
+            rule.mainClock.advanceTimeBy(tick.toLong())
+        }
+    }
+
+    @Test
     fun testTextFields_singleFocus() {
         val textField1Tag = "TextField1"
         val textField2Tag = "TextField2"
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/TimePickerTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/TimePickerTest.kt
index 7ee9fb4..0dbe53e3 100644
--- a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/TimePickerTest.kt
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/TimePickerTest.kt
@@ -451,6 +451,37 @@
         assertThat(state.hour).isEqualTo(22)
     }
 
+    @OptIn(ExperimentalTestApi::class)
+    @Test
+    fun timeInput_keyboardInput_maintainsPm() {
+        val state = TimePickerState(initialHour = 23, initialMinute = 23, is24Hour = false)
+
+        rule.setMaterialContent(lightColorScheme()) { TimeInput(state) }
+
+        assertThat(state.isAfternoon).isTrue()
+
+        rule.onNodeWithText("11").performKeyInput { pressKey(Key.Four) }
+
+        assertThat(state.isAfternoon).isTrue()
+    }
+
+    @OptIn(ExperimentalTestApi::class)
+    @Test
+    fun timeInput_deleting_maintainsPm() {
+        val state = TimePickerState(initialHour = 23, initialMinute = 23, is24Hour = false)
+
+        rule.setMaterialContent(lightColorScheme()) { TimeInput(state) }
+
+        assertThat(state.isAfternoon).isTrue()
+
+        rule.onNodeWithText("11").performKeyInput {
+            pressKey(Key.Delete)
+            pressKey(Key.Delete)
+        }
+
+        assertThat(state.isAfternoon).isTrue()
+    }
+
     @Test
     fun timeInput_24Hour_noAmPm_Toggle() {
         val state = TimePickerState(initialHour = 22, initialMinute = 23, is24Hour = true)
@@ -479,6 +510,21 @@
 
     @Test
     @OptIn(ExperimentalTestApi::class)
+    fun timeInput_24HourStartingAfternoon_writeAfternoonHour() {
+        val state = TimePickerState(initialHour = 20, initialMinute = 23, is24Hour = true)
+
+        rule.setMaterialContent(lightColorScheme()) { TimeInput(state) }
+
+        rule.onNodeWithText("20").performKeyInput {
+            pressKey(Key.Two)
+            pressKey(Key.Two)
+        }
+
+        assertThat(state.hour).isEqualTo(22)
+    }
+
+    @Test
+    @OptIn(ExperimentalTestApi::class)
     fun timeInput_24Hour_writeNoon() {
         val state = TimePickerState(initialHour = 10, initialMinute = 23, is24Hour = true)
 
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/WavyProgressIndicatorTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/WavyProgressIndicatorTest.kt
index 4da64c7..d33f34b 100644
--- a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/WavyProgressIndicatorTest.kt
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/WavyProgressIndicatorTest.kt
@@ -207,7 +207,7 @@
             }
         }
 
-        rule.mainClock.advanceTimeBy(300)
+        rule.mainClock.advanceTimeBy(200)
 
         rule.onNodeWithTag(tag).captureToImage().toPixelMap().let {
             assertEquals(expectedSize.width, it.width)
diff --git a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/DynamicTonalPalette.android.kt b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/DynamicTonalPalette.android.kt
index 8fb01df..4a5ded7 100644
--- a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/DynamicTonalPalette.android.kt
+++ b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/DynamicTonalPalette.android.kt
@@ -24,11 +24,10 @@
 import androidx.annotation.DoNotInline
 import androidx.annotation.FloatRange
 import androidx.annotation.RequiresApi
+import androidx.compose.material3.internal.colorUtil.Cam
+import androidx.compose.material3.internal.colorUtil.CamUtils
 import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.colorspace.ColorSpaces
-import androidx.core.math.MathUtils
-import kotlin.math.pow
-import kotlin.math.roundToInt
+import androidx.compose.ui.graphics.toArgb
 
 /** Dynamic colors in Material. */
 @RequiresApi(31)
@@ -250,55 +249,13 @@
  */
 internal fun Color.setLuminance(@FloatRange(from = 0.0, to = 100.0) newLuminance: Float): Color {
     if ((newLuminance < 0.0001) or (newLuminance > 99.9999)) {
-        // aRGBFromLstar() from monet ColorUtil.java
-        val y = 100 * labInvf((newLuminance + 16) / 116)
-        val component = delinearized(y)
-        return Color(
-            /* red = */ component,
-            /* green = */ component,
-            /* blue = */ component,
-        )
+        return Color(CamUtils.argbFromLstar(newLuminance.toDouble()))
     }
 
-    val sLAB = this.convert(ColorSpaces.CieLab)
-    return Color(
-            /* luminance = */ newLuminance,
-            /* a = */ sLAB.component2(),
-            /* b = */ sLAB.component3(),
-            colorSpace = ColorSpaces.CieLab
-        )
-        .convert(ColorSpaces.Srgb)
-}
+    val baseCam: Cam = Cam.fromInt(this.toArgb())
+    val baseColor = Cam.getInt(baseCam.hue, baseCam.chroma, newLuminance)
 
-/** Helper method from monet ColorUtils.java */
-private fun labInvf(ft: Float): Float {
-    val e = 216f / 24389f
-    val kappa = 24389f / 27f
-    val ft3 = ft * ft * ft
-    return if (ft3 > e) {
-        ft3
-    } else {
-        (116 * ft - 16) / kappa
-    }
-}
-
-/**
- * Helper method from monet ColorUtils.java
- *
- * Delinearizes an RGB component.
- *
- * @param rgbComponent 0.0 <= rgb_component <= 100.0, represents linear R/G/B channel
- * @return 0 <= output <= 255, color channel converted to regular RGB space
- */
-private fun delinearized(rgbComponent: Float): Int {
-    val normalized = rgbComponent / 100
-    val delinearized =
-        if (normalized <= 0.0031308) {
-            normalized * 12.92
-        } else {
-            1.055 * normalized.toDouble().pow(1.0 / 2.4) - 0.055
-        }
-    return MathUtils.clamp((delinearized * 255.0).roundToInt(), 0, 255)
+    return Color(baseColor)
 }
 
 @RequiresApi(31)
diff --git a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/ExposedDropdownMenu.android.kt b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/ExposedDropdownMenu.android.kt
index a84ebd2..146b300 100644
--- a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/ExposedDropdownMenu.android.kt
+++ b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/ExposedDropdownMenu.android.kt
@@ -152,12 +152,17 @@
     val expandedDescription = getString(Strings.MenuExpanded)
     val collapsedDescription = getString(Strings.MenuCollapsed)
     val toggleDescription = getString(Strings.ToggleDropdownMenu)
-    val anchorTypeState = remember { mutableStateOf(MenuAnchorType.PrimaryNotEditable) }
+    val anchorTypeState = remember {
+        mutableStateOf(ExposedDropdownMenuAnchorType.PrimaryNotEditable)
+    }
 
     val scope =
         remember(expanded, onExpandedChange, config, view, density) {
             object : ExposedDropdownMenuBoxScopeImpl() {
-                override fun Modifier.menuAnchor(type: MenuAnchorType, enabled: Boolean): Modifier =
+                override fun Modifier.menuAnchor(
+                    type: ExposedDropdownMenuAnchorType,
+                    enabled: Boolean
+                ): Modifier =
                     this.focusRequester(focusRequester)
                         .then(
                             if (!enabled) Modifier
@@ -176,19 +181,19 @@
                                 )
                         )
 
-                override val anchorType: MenuAnchorType
+                override val anchorType: ExposedDropdownMenuAnchorType
                     get() = anchorTypeState.value
 
-                override fun Modifier.exposedDropdownSize(matchTextFieldWidth: Boolean): Modifier =
+                override fun Modifier.exposedDropdownSize(matchAnchorWidth: Boolean): Modifier =
                     layout { measurable, constraints ->
                         val menuWidth = constraints.constrainWidth(anchorWidth)
                         val menuConstraints =
                             constraints.copy(
                                 maxHeight = constraints.constrainHeight(menuMaxHeight),
                                 minWidth =
-                                    if (matchTextFieldWidth) menuWidth else constraints.minWidth,
+                                    if (matchAnchorWidth) menuWidth else constraints.minWidth,
                                 maxWidth =
-                                    if (matchTextFieldWidth) menuWidth else constraints.maxWidth,
+                                    if (matchAnchorWidth) menuWidth else constraints.maxWidth,
                             )
                         val placeable = measurable.measure(menuConstraints)
                         layout(placeable.width, placeable.height) { placeable.place(0, 0) }
@@ -280,17 +285,21 @@
 sealed class ExposedDropdownMenuBoxScope {
     /**
      * Modifier which should be applied to an element inside the [ExposedDropdownMenuBoxScope],
-     * typically a text field or an icon within the text field. It's responsible for expanding and
-     * collapsing the menu on click, applying semantics to the component, and requesting focus.
+     * typically a text field or an icon within the text field. It's responsible for requesting
+     * focus, and if [enabled], expanding/collapsing the menu on click and applying semantics.
      *
-     * @param type the type of element that is anchoring the menu. See [MenuAnchorType].
-     * @param enabled controls the enabled state. When `false`, the component will not expand or
-     *   collapse the menu in response to user input, and menu semantics will be invisible to
-     *   accessibility services. Note that this value only controls interactions with the menu. It
-     *   does not affect the enabled state of other kinds of interactions, such as [TextField]'s
-     *   `enabled` parameter.
+     * @param type the type of element that is anchoring the menu. See
+     *   [ExposedDropdownMenuAnchorType].
+     * @param enabled whether controlling the menu via this anchor is enabled. When `false`, the
+     *   component will not expand or collapse the menu in response to user input, and menu
+     *   semantics will be invisible to accessibility services. Note that this value only controls
+     *   interactions with the menu. It does not affect the enabled state of other kinds of
+     *   interactions, such as [TextField]'s `enabled` parameter.
      */
-    abstract fun Modifier.menuAnchor(type: MenuAnchorType, enabled: Boolean = true): Modifier
+    abstract fun Modifier.menuAnchor(
+        type: ExposedDropdownMenuAnchorType,
+        enabled: Boolean = true
+    ): Modifier
 
     /**
      * Modifier which should be applied to a menu placed inside the [ExposedDropdownMenuBoxScope].
@@ -300,12 +309,12 @@
      * [ExposedDropdownMenu] applies this modifier automatically, so this is only needed when using
      * custom menu components.
      *
-     * @param matchTextFieldWidth whether the menu's width should be forcefully constrained to match
+     * @param matchAnchorWidth whether the menu's width should be forcefully constrained to match
      *   the width of the text field to which it's attached.
      */
-    abstract fun Modifier.exposedDropdownSize(matchTextFieldWidth: Boolean = true): Modifier
+    abstract fun Modifier.exposedDropdownSize(matchAnchorWidth: Boolean = true): Modifier
 
-    internal abstract val anchorType: MenuAnchorType
+    internal abstract val anchorType: ExposedDropdownMenuAnchorType
 
     /**
      * Popup which contains content for Exposed Dropdown Menu. Should be used inside the content of
@@ -316,7 +325,7 @@
      *   outside the menu's bounds
      * @param modifier the [Modifier] to be applied to this menu
      * @param scrollState a [ScrollState] used by the menu's content for items vertical scrolling
-     * @param matchTextFieldWidth whether the menu's width should be forcefully constrained to match
+     * @param matchAnchorWidth whether the menu's width should be forcefully constrained to match
      *   the width of the text field to which it's attached.
      * @param shape the shape of the menu
      * @param containerColor the container color of the menu
@@ -334,7 +343,7 @@
         onDismissRequest: () -> Unit,
         modifier: Modifier = Modifier,
         scrollState: ScrollState = rememberScrollState(),
-        matchTextFieldWidth: Boolean = true,
+        matchAnchorWidth: Boolean = true,
         shape: Shape = MenuDefaults.shape,
         containerColor: Color = MenuDefaults.containerColor,
         tonalElevation: Dp = MenuDefaults.TonalElevation,
@@ -385,7 +394,7 @@
                     tonalElevation = tonalElevation,
                     shadowElevation = shadowElevation,
                     border = border,
-                    modifier = modifier.exposedDropdownSize(matchTextFieldWidth),
+                    modifier = modifier.exposedDropdownSize(matchAnchorWidth),
                     content = content,
                 )
             }
@@ -394,16 +403,17 @@
 
     @Deprecated(
         level = DeprecationLevel.WARNING,
-        message = "Use overload that takes MenuAnchorType and enabled parameters",
+        message = "Use overload that takes ExposedDropdownMenuAnchorType and enabled parameters",
         replaceWith = ReplaceWith("menuAnchor(type, enabled)")
     )
-    fun Modifier.menuAnchor(): Modifier = menuAnchor(MenuAnchorType.PrimaryNotEditable)
+    fun Modifier.menuAnchor(): Modifier =
+        menuAnchor(ExposedDropdownMenuAnchorType.PrimaryNotEditable)
 
     @Deprecated(
         level = DeprecationLevel.WARNING,
         message =
-            "The `focusable` parameter is unused. Pass the proper MenuAnchorType to " +
-                "Modifier.menuAnchor instead, which will handle focusability automatically.",
+            "The `focusable` parameter is unused. Pass the proper ExposedDropdownMenuAnchorType " +
+                "to Modifier.menuAnchor instead, which will handle focusability automatically.",
     )
     @Suppress("DeprecatedCallableAddReplaceWith", "UNUSED_PARAMETER")
     @Composable
@@ -426,7 +436,7 @@
             onDismissRequest = onDismissRequest,
             modifier = modifier,
             scrollState = scrollState,
-            matchTextFieldWidth = matchTextFieldWidth,
+            matchAnchorWidth = matchTextFieldWidth,
             shape = shape,
             containerColor = containerColor,
             tonalElevation = tonalElevation,
@@ -435,6 +445,7 @@
             content = content,
         )
 
+    @Suppress("DEPRECATION")
     @Deprecated(
         level = DeprecationLevel.HIDDEN,
         message =
@@ -470,14 +481,14 @@
 
 /** The type of element that can serve as a dropdown menu anchor. */
 @JvmInline
-value class MenuAnchorType private constructor(private val name: String) {
+value class ExposedDropdownMenuAnchorType private constructor(private val name: String) {
     companion object {
         /**
          * A non-editable primary anchor of the dropdown menu, such as a read-only text field.
          *
          * An anchor of this type will open the menu with focus.
          */
-        val PrimaryNotEditable = MenuAnchorType("PrimaryNotEditable")
+        val PrimaryNotEditable = ExposedDropdownMenuAnchorType("PrimaryNotEditable")
 
         /**
          * An editable primary anchor of the dropdown menu, such as a text field that allows user
@@ -486,7 +497,7 @@
          * An anchor of this type will open the menu without focus in order to preserve focus on the
          * soft keyboard (IME).
          */
-        val PrimaryEditable = MenuAnchorType("PrimaryEditable")
+        val PrimaryEditable = ExposedDropdownMenuAnchorType("PrimaryEditable")
 
         /**
          * A secondary anchor of the dropdown menu that lives alongside an editable primary anchor,
@@ -496,12 +507,18 @@
          * focus. Otherwise, the menu is opened without focus in order to preserve focus on the soft
          * keyboard (IME).
          */
-        val SecondaryEditable = MenuAnchorType("SecondaryEditable")
+        val SecondaryEditable = ExposedDropdownMenuAnchorType("SecondaryEditable")
     }
 
     override fun toString(): String = name
 }
 
+@Deprecated(
+    message = "Renamed to ExposedDropdownMenuAnchorType",
+    replaceWith = ReplaceWith("ExposedDropdownMenuAnchorType"),
+)
+typealias MenuAnchorType = ExposedDropdownMenuAnchorType
+
 /** Contains default values used by Exposed Dropdown Menu. */
 @ExperimentalMaterial3Api
 object ExposedDropdownMenuDefaults {
@@ -854,10 +871,11 @@
     /**
      * Creates a [PopupProperties] used for [ExposedDropdownMenuBoxScope.ExposedDropdownMenu].
      *
-     * @param anchorType the type of element that is anchoring the menu. See [MenuAnchorType].
+     * @param anchorType the type of element that is anchoring the menu. See
+     *   [ExposedDropdownMenuAnchorType].
      */
     @Composable
-    internal fun popupProperties(anchorType: MenuAnchorType): PopupProperties {
+    internal fun popupProperties(anchorType: ExposedDropdownMenuAnchorType): PopupProperties {
         val a11yServicesEnabled by rememberAccessibilityServiceState()
         var flags =
             WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH or
@@ -871,8 +889,9 @@
         // If typing on the IME is required, the menu should not be focusable
         // in order to prevent stealing focus from the input method.
         val imeRequired =
-            anchorType == MenuAnchorType.PrimaryEditable ||
-                (anchorType == MenuAnchorType.SecondaryEditable && !a11yServicesEnabled)
+            anchorType == ExposedDropdownMenuAnchorType.PrimaryEditable ||
+                (anchorType == ExposedDropdownMenuAnchorType.SecondaryEditable &&
+                    !a11yServicesEnabled)
         if (imeRequired) {
             flags = flags or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
         }
@@ -1415,7 +1434,7 @@
 private fun Modifier.expandable(
     expanded: Boolean,
     onExpandedChange: () -> Unit,
-    anchorType: MenuAnchorType,
+    anchorType: ExposedDropdownMenuAnchorType,
     expandedDescription: String,
     collapsedDescription: String,
     toggleDescription: String,
@@ -1427,7 +1446,7 @@
                 // in the Initial pass to observe events before the text field consumes them
                 // in the Main pass.
                 val downEvent = awaitFirstDown(pass = PointerEventPass.Initial)
-                if (anchorType == MenuAnchorType.SecondaryEditable) {
+                if (anchorType == ExposedDropdownMenuAnchorType.SecondaryEditable) {
                     downEvent.consume()
                 }
                 val upEvent = waitForUpOrCancellation(pass = PointerEventPass.Initial)
@@ -1437,7 +1456,7 @@
             }
         }
         .semantics {
-            if (anchorType == MenuAnchorType.SecondaryEditable) {
+            if (anchorType == ExposedDropdownMenuAnchorType.SecondaryEditable) {
                 role = Role.Button
                 stateDescription = if (expanded) expandedDescription else collapsedDescription
                 contentDescription = toggleDescription
@@ -1446,7 +1465,7 @@
             }
             onClick {
                 onExpandedChange()
-                if (anchorType == MenuAnchorType.PrimaryEditable) {
+                if (anchorType == ExposedDropdownMenuAnchorType.PrimaryEditable) {
                     keyboardController?.show()
                 }
                 true
diff --git a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/internal/colorUtil/Cam.android.kt b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/internal/colorUtil/Cam.android.kt
new file mode 100644
index 0000000..241d3f1
--- /dev/null
+++ b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/internal/colorUtil/Cam.android.kt
@@ -0,0 +1,453 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3.internal.colorUtil
+
+import androidx.annotation.Nullable
+import androidx.compose.material3.internal.colorUtil.CamUtils.intFromLstar
+import androidx.compose.material3.internal.colorUtil.CamUtils.lstarFromInt
+import androidx.compose.material3.internal.colorUtil.CamUtils.xyzFromInt
+import androidx.compose.material3.internal.colorUtil.HctSolver.solveToInt
+import androidx.core.graphics.ColorUtils
+import kotlin.math.PI
+import kotlin.math.abs
+import kotlin.math.atan2
+import kotlin.math.cos
+import kotlin.math.ln
+import kotlin.math.max
+import kotlin.math.min
+import kotlin.math.pow
+import kotlin.math.sign
+import kotlin.math.sin
+import kotlin.math.sqrt
+
+/**
+ * NOTICE: Fork and kotlin transpilation of
+ * frameworks/base/core/java/com/android/internal/graphics/cam/Cam.java Manual changes have not and
+ * should not be implemented except for compilation purposes between kotlin and java. Unused methods
+ * were also removed.
+ *
+ * A color appearance model, based on CAM16, extended to use L* as the lightness dimension, and
+ * coupled to a gamut mapping algorithm. Creates a color system, enables a digital design system.
+ */
+internal class Cam(
+    /** Hue in CAM16 */
+    // CAM16 color dimensions, see getters for documentation.
+    val hue: Float,
+    /** Chroma in CAM16 */
+    val chroma: Float,
+    /** Lightness in CAM16 */
+    val j: Float,
+    /**
+     * Colorfulness in CAM16.
+     *
+     * Prefer chroma, colorfulness is an absolute quantity. For example, a yellow toy car is much
+     * more colorful outside than inside, but it has the same chroma in both environments.
+     */
+    val m: Float,
+    /**
+     * Saturation in CAM16.
+     *
+     * Colorfulness in proportion to brightness. Prefer chroma, saturation measures colorfulness
+     * relative to the color's own brightness, where chroma is colorfulness relative to white.
+     */
+    val s: Float,
+    /** Lightness coordinate in CAM16-UCS */
+    // Coordinates in UCS space. Used to determine color distance, like delta E equations in L*a*b*.
+    var jstar: Float,
+    /** a* coordinate in CAM16-UCS */
+    val astar: Float,
+    /** b* coordinate in CAM16-UCS */
+    val bstar: Float
+) {
+
+    /**
+     * Distance in CAM16-UCS space between two colors.
+     *
+     * Much like L*a*b* was designed to measure distance between colors, the CAM16 standard defined
+     * a color space called CAM16-UCS to measure distance between CAM16 colors.
+     */
+    fun distance(other: Cam): Float {
+        val dJ = jstar - other.jstar
+        val dA = astar - other.astar
+        val dB = bstar - other.bstar
+        val dEPrime = sqrt((dJ * dJ + dA * dA + dB * dB).toDouble())
+        val dE: Double = 1.41 * dEPrime.pow(0.63)
+        return dE.toFloat()
+    }
+
+    /** Returns perceived color as an ARGB integer, as viewed in standard sRGB frame. */
+    fun viewedInSrgb(): Int {
+        return viewed(Frame.Default)
+    }
+
+    /** Returns color perceived in a frame as an ARGB integer. */
+    fun viewed(frame: Frame): Int {
+        val alpha = if ((chroma == 0.0f || j == 0.0f)) 0.0f else chroma / sqrt(j / 100.0f)
+
+        val t = (alpha / (1.64f - 0.29f.pow(frame.n).pow(0.73f)).pow(1.0f / 0.9f))
+        val hRad = hue * PI.toFloat() / 180.0f
+
+        val eHue = 0.25f * (cos(hRad + 2.0f) + 3.8f)
+        val ac = frame.aw * (j / 100.0f).pow(1.0f / frame.c / frame.z)
+        val p1 = eHue * (50000.0f / 13.0f) * frame.nc * frame.ncb
+        val p2 = (ac / frame.nbb)
+
+        val hSin = sin(hRad)
+        val hCos = cos(hRad)
+
+        val gamma = 23.0f * (p2 + 0.305f) * t / (23.0f * p1 + 11.0f * t * hCos + 108.0f * t * hSin)
+        val a = gamma * hCos
+        val b = gamma * hSin
+        val rA = (460.0f * p2 + 451.0f * a + 288.0f * b) / 1403.0f
+        val gA = (460.0f * p2 - 891.0f * a - 261.0f * b) / 1403.0f
+        val bA = (460.0f * p2 - 220.0f * a - 6300.0f * b) / 1403.0f
+
+        val rCBase = max(0.0f, (27.13f * abs(rA)) / (400.0f - abs(rA)))
+        val rC = sign(rA) * (100.0f / frame.fl) * rCBase.pow(1.0f / 0.42f)
+        val gCBase = max(0.0f, (27.13f * abs(gA)) / (400.0f - abs(gA)))
+        val gC = sign(gA) * (100.0f / frame.fl) * gCBase.pow(1.0f / 0.42f)
+        val bCBase = max(0.0f, (27.13f * abs(bA)) / (400.0f - abs(bA)))
+        val bC = (sign(bA) * (100.0f / frame.fl) * bCBase.pow(1.0f / 0.42f))
+        val rF = rC / frame.rgbD[0]
+        val gF = gC / frame.rgbD[1]
+        val bF = bC / frame.rgbD[2]
+
+        val matrix = CamUtils.CAM16RGB_TO_XYZ
+        val x = (rF * matrix[0][0]) + (gF * matrix[0][1]) + (bF * matrix[0][2])
+        val y = (rF * matrix[1][0]) + (gF * matrix[1][1]) + (bF * matrix[1][2])
+        val z = (rF * matrix[2][0]) + (gF * matrix[2][1]) + (bF * matrix[2][2])
+
+        val argb = ColorUtils.XYZToColor(x.toDouble(), y.toDouble(), z.toDouble())
+        return argb
+    }
+
+    companion object {
+        // The maximum difference between the requested L* and the L* returned.
+        private const val DL_MAX = 0.2f
+
+        // The maximum color distance, in CAM16-UCS, between a requested color and the color
+        // returned.
+        private const val DE_MAX = 1.0f
+
+        // When the delta between the floor & ceiling of a binary search for chroma is less than
+        // this, the binary search terminates.
+        private const val CHROMA_SEARCH_ENDPOINT = 0.4f
+
+        // When the delta between the floor & ceiling of a binary search for J, lightness in CAM16,
+        // is less than this, the binary search terminates.
+        private const val LIGHTNESS_SEARCH_ENDPOINT = 0.01f
+
+        /**
+         * Given a hue & chroma in CAM16, L* in L*a*b*, return an ARGB integer. The chroma of the
+         * color returned may, and frequently will, be lower than requested. Assumes the color is
+         * viewed in the frame defined by the sRGB standard.
+         */
+        fun getInt(hue: Float, chroma: Float, lstar: Float): Int {
+            return getInt(hue, chroma, lstar, Frame.Default)
+        }
+
+        /**
+         * Create a color appearance model from a ARGB integer representing a color. It is assumed
+         * the color was viewed in the frame defined in the sRGB standard.
+         */
+        fun fromInt(argb: Int): Cam {
+            return fromIntInFrame(argb, Frame.Default)
+        }
+
+        /**
+         * Create a color appearance model from a ARGB integer representing a color, specifying the
+         * frame in which the color was viewed. Prefer Cam.fromInt.
+         */
+        private fun fromIntInFrame(argb: Int, frame: Frame): Cam {
+            // Transform ARGB int to XYZ
+            val xyz = xyzFromInt(argb)
+
+            // Transform XYZ to 'cone'/'rgb' responses
+            val matrix = CamUtils.XYZ_TO_CAM16RGB
+            val rT = (xyz[0] * matrix[0][0]) + (xyz[1] * matrix[0][1]) + (xyz[2] * matrix[0][2])
+            val gT = (xyz[0] * matrix[1][0]) + (xyz[1] * matrix[1][1]) + (xyz[2] * matrix[1][2])
+            val bT = (xyz[0] * matrix[2][0]) + (xyz[1] * matrix[2][1]) + (xyz[2] * matrix[2][2])
+
+            // Discount illuminant
+            val rD = frame.rgbD[0] * rT
+            val gD = frame.rgbD[1] * gT
+            val bD = frame.rgbD[2] * bT
+
+            // Chromatic adaptation
+            val rAF = (frame.fl * abs(rD) / 100f).pow(0.42f)
+            val gAF = (frame.fl * abs(gD) / 100f).pow(0.42f)
+            val bAF = (frame.fl * abs(bD) / 100f).pow(0.42f)
+            val rA = (sign(rD) * 400.0f * rAF / (rAF + 27.13f))
+            val gA = (sign(gD) * 400.0f * gAF / (gAF + 27.13f))
+            val bA = (sign(bD) * 400.0f * bAF / (bAF + 27.13f))
+
+            // redness-greenness
+            val a = (11f * rA + -12f * gA + bA) / 11.0f
+            // yellowness-blueness
+            val b = (rA + gA - 2f * bA) / 9.0f
+
+            // auxiliary components
+            val u = (20.0f * rA + 20.0f * gA + 21.0f * bA) / 20.0f
+            val p2 = (40.0f * rA + 20.0f * gA + bA) / 20.0f
+
+            // hue
+            val atan2 = atan2(b, a)
+            val atanDegrees = atan2 * 180.0f / PI.toFloat()
+            val hue =
+                if (atanDegrees < 0) atanDegrees + 360.0f
+                else if (atanDegrees >= 360) atanDegrees - 360.0f else atanDegrees
+            val hueRadians = hue * PI.toFloat() / 180.0f
+
+            // achromatic response to color
+            val ac = p2 * frame.nbb
+
+            // CAM16 lightness and brightness
+            val j = 100.0f * (ac / frame.aw).pow((frame.c * frame.z))
+
+            // CAM16 chroma, colorfulness, and saturation.
+            val huePrime = if ((hue < 20.14)) hue + 360 else hue
+            val eHue = 0.25f * (cos(huePrime * PI.toFloat() / 180f + 2f) + 3.8f)
+            val p1 = 50000.0f / 13.0f * eHue * frame.nc * frame.ncb
+            val t = p1 * sqrt((a * a + b * b)) / (u + 0.305f)
+            val alpha = t.pow(0.9f) * (1.64f - 0.29f.pow(frame.n)).pow(0.73f)
+            // CAM16 chroma, colorfulness, saturation
+            val c = alpha * sqrt(j / 100f)
+            val m = c * frame.flRoot
+            val s = 50.0f * sqrt(((alpha * frame.c) / (frame.aw + 4.0f)))
+
+            // CAM16-UCS components
+            val jstar = (1.0f + 100.0f * 0.007f) * j / (1.0f + 0.007f * j)
+            val mstar = 1.0f / 0.0228f * ln((1.0f + 0.0228f * m))
+            val astar = mstar * cos(hueRadians)
+            val bstar = mstar * sin(hueRadians)
+
+            return Cam(hue, c, j, m, s, jstar, astar, bstar)
+        }
+
+        /**
+         * Create a CAM from lightness, chroma, and hue coordinates. It is assumed those coordinates
+         * were measured in the sRGB standard frame.
+         */
+        private fun fromJch(j: Float, c: Float, h: Float): Cam {
+            return fromJchInFrame(j, c, h, Frame.Default)
+        }
+
+        /**
+         * Create a CAM from lightness, chroma, and hue coordinates, and also specify the frame in
+         * which the color is being viewed.
+         */
+        private fun fromJchInFrame(j: Float, c: Float, h: Float, frame: Frame): Cam {
+            val m = c * frame.flRoot
+            val alpha = c / sqrt(j / 100.0).toFloat()
+            val s = 50.0f * sqrt(((alpha * frame.c) / (frame.aw + 4.0f)))
+
+            val hueRadians = h * Math.PI.toFloat() / 180.0f
+            val jstar = (1.0f + 100.0f * 0.007f) * j / (1.0f + 0.007f * j)
+            val mstar = 1.0f / 0.0228f * ln(1.0 + 0.0228 * m).toFloat()
+            val astar = mstar * cos(hueRadians.toDouble()).toFloat()
+            val bstar = mstar * sin(hueRadians.toDouble()).toFloat()
+            return Cam(h, c, j, m, s, jstar, astar, bstar)
+        }
+
+        /**
+         * Given a hue & chroma in CAM16, L* in L*a*b*, and the frame in which the color will be
+         * viewed, return an ARGB integer.
+         *
+         * The chroma of the color returned may, and frequently will, be lower than requested. This
+         * is a fundamental property of color that cannot be worked around by engineering. For
+         * example, a red hue, with high chroma, and high L* does not exist: red hues have a maximum
+         * chroma below 10 in light shades, creating pink.
+         */
+        private fun getInt(hue: Float, chroma: Float, lstar: Float, frame: Frame): Int {
+            // This is a crucial routine for building a color system, CAM16 itself is not
+            // sufficient.
+            //
+            // * Why these dimensions?
+            // Hue and chroma from CAM16 are used because they're the most accurate measures of
+            // those quantities. L* from L*a*b* is used because it correlates with luminance,
+            // luminance is used to measure contrast for a11y purposes, thus providing a key
+            // constraint on what colors can be used.
+            //
+            // * Why is this routine required to build a color system?
+            // In all perceptually accurate color spaces (i.e. L*a*b* and later), `chroma` may be
+            // impossible for a given `hue` and `lstar`.
+            // For example, a high chroma light red does not exist - chroma is limited to below 10
+            // at light red shades, we call that pink. High chroma light green does exist, but not
+            // dark.
+            // Also, when converting from another color space to RGB, the color may not be able to
+            // be represented in RGB. In those cases, the conversion process ends with RGB values
+            // outside 0-255.
+            // The vast majority of color libraries surveyed simply round to 0 to 255. That is not
+            // an option for this library, as it distorts the expected luminance, and thus the
+            // expected contrast needed for a11y
+            //
+            // * What does this routine do?
+            // Dealing with colors in one color space not fitting inside RGB is, loosely referred to
+            // as gamut mapping or tone mapping. These algorithms are traditionally idiosyncratic,
+            // there is no universal answer. However, because the intent of this library is to build
+            // a system for digital design, and digital design uses luminance to measure
+            // contrast/a11y, we have one very important constraint that leads to an objective
+            // algorithm: the L* of the returned color _must_ match the requested L*.
+            //
+            // Intuitively, if the color must be distorted to fit into the RGB gamut, and the L*
+            // requested *must* be fulfilled, than the hue or chroma of the returned color will need
+            // to be different from the requested hue/chroma.
+            //
+            // After exploring both options, it was more intuitive that if the requested chroma
+            // could not be reached, it used the highest possible chroma. The alternative was
+            // finding the closest hue where the requested chroma could be reached, but that is not
+            // nearly as intuitive, as the requested hue is so fundamental to the color description.
+
+            // If the color doesn't have meaningful chroma, return a gray with the requested Lstar.
+            //
+            // Yellows are very chromatic at L = 100, and blues are very chromatic at L = 0. All the
+            // other hues are white at L = 100, and black at L = 0. To preserve consistency for
+            // users of this system, it is better to simply return white at L* > 99, and black and
+            // L* < 0.
+
+            var huePrime = hue
+            if (frame == Frame.Default) {
+                // If the viewing conditions are the same as the default sRGB-like viewing
+                // conditions, skip to using HctSolver: it uses geometrical insights to find the
+                // closest in-gamut match to hue/chroma/lstar.
+                return solveToInt(huePrime.toDouble(), chroma.toDouble(), lstar.toDouble())
+            }
+
+            if (chroma < 1.0 || Math.round(lstar) <= 0.0 || Math.round(lstar) >= 100.0) {
+                return intFromLstar(lstar)
+            }
+
+            huePrime = if (huePrime < 0) 0f else min(360.0f, huePrime)
+
+            // The highest chroma possible. Updated as binary search proceeds.
+            var high = chroma
+
+            // The guess for the current binary search iteration. Starts off at the highest chroma,
+            // thus, if a color is possible at the requested chroma, the search can stop after one
+            // try.
+            var mid = chroma
+            var low = 0.0f
+            var isFirstLoop = true
+
+            var answer: Cam? = null
+
+            while (abs((low - high).toDouble()) >= CHROMA_SEARCH_ENDPOINT) {
+                // Given the current chroma guess, mid, and the desired hue, find J, lightness in
+                // CAM16 color space, that creates a color with L* = `lstar` in the L*a*b* color
+                // space.
+                val possibleAnswer = findCamByJ(huePrime, mid, lstar)
+
+                if (isFirstLoop) {
+                    if (possibleAnswer != null) {
+                        return possibleAnswer.viewed(frame)
+                    } else {
+                        // If this binary search iteration was the first iteration, and this point
+                        // has been reached, it means the requested chroma was not available at the
+                        // requested hue and L*.
+                        // Proceed to a traditional binary search that starts at the midpoint
+                        // between the requested chroma and 0.
+                        isFirstLoop = false
+                        mid = low + (high - low) / 2.0f
+                        continue
+                    }
+                }
+
+                if (possibleAnswer == null) {
+                    // There isn't a CAM16 J that creates a color with L* `lstar`. Try a lower
+                    // chroma.
+                    high = mid
+                } else {
+                    answer = possibleAnswer
+                    // It is possible to create a color. Try higher chroma.
+                    low = mid
+                }
+
+                mid = low + (high - low) / 2.0f
+            }
+
+            // There was no answer: meaning, for the desired hue, there was no chroma low enough to
+            // generate a color with the desired L*.
+            // All values of L* are possible when there is 0 chroma. Return a color with 0 chroma,
+            // i.e. a shade of gray, with the desired L*.
+            if (answer == null) {
+                return intFromLstar(lstar)
+            }
+
+            return answer.viewed(frame)
+        }
+
+        // Find J, lightness in CAM16 color space, that creates a color with L* = `lstar` in the
+        // L*a*b* color space.
+        //
+        // Returns null if no J could be found that generated a color with L* `lstar`.
+        @Nullable
+        private fun findCamByJ(hue: Float, chroma: Float, lstar: Float): Cam? {
+            var low = 0.0f
+            var high = 100.0f
+            var mid: Float
+            var bestdL = 1000.0f
+            var bestdE = 1000.0f
+
+            var bestCam: Cam? = null
+            while (abs((low - high).toDouble()) > LIGHTNESS_SEARCH_ENDPOINT) {
+                mid = low + (high - low) / 2
+                // Create the intended CAM color
+                val camBeforeClip = fromJch(mid, chroma, hue)
+                // Convert the CAM color to RGB. If the color didn't fit in RGB, during the
+                // conversion, the initial RGB values will be outside 0 to 255. The final RGB values
+                // are clipped to 0 to 255, distorting the intended color.
+                val clipped = camBeforeClip.viewedInSrgb()
+                val clippedLstar = lstarFromInt(clipped)
+                val dL = abs((lstar - clippedLstar).toDouble()).toFloat()
+
+                // If the clipped color's L* is within error margin...
+                if (dL < DL_MAX) {
+                    // ...check if the CAM equivalent of the clipped color is far away from intended
+                    // CAM color. For the intended color, use lightness and chroma from the clipped
+                    // color, and the intended hue. Callers are wondering what the lightness is,
+                    // they know chroma may be distorted, so the only concern here is if the hue
+                    // slipped too far.
+                    val camClipped = fromInt(clipped)
+                    val dE = camClipped.distance(fromJch(camClipped.j, camClipped.chroma, hue))
+                    if (dE <= DE_MAX) {
+                        bestdL = dL
+                        bestdE = dE
+                        bestCam = camClipped
+                    }
+                }
+
+                // If there's no error at all, there's no need to search more.
+                //
+                // Note: this happens much more frequently than expected, but this is a very
+                // delicate property which relies on extremely precise sRGB <=> XYZ calculations, as
+                // well as fine tuning of the constants that determine error margins and when the
+                // binary search can terminate.
+                if (bestdL == 0f && bestdE == 0f) {
+                    break
+                }
+
+                if (clippedLstar < lstar) {
+                    low = mid
+                } else {
+                    high = mid
+                }
+            }
+
+            return bestCam
+        }
+    }
+}
diff --git a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/internal/colorUtil/CamUtils.android.kt b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/internal/colorUtil/CamUtils.android.kt
new file mode 100644
index 0000000..0b4e978
--- /dev/null
+++ b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/internal/colorUtil/CamUtils.android.kt
@@ -0,0 +1,289 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3.internal.colorUtil
+
+import androidx.core.graphics.ColorUtils
+import androidx.core.graphics.blue
+import androidx.core.graphics.green
+import androidx.core.graphics.red
+import kotlin.math.cbrt
+import kotlin.math.pow
+
+/**
+ * NOTICE: Fork and kotlin transpilation of
+ * frameworks/base/core/java/com/android/internal/graphics/cam/CamUtils.java Manual changes have not
+ * and should not be implemented except for compilation purposes between kotlin and java. Unused
+ * methods were also removed.
+ *
+ * Collection of methods for transforming between color spaces.
+ *
+ * Methods are named $xFrom$Y. For example, lstarFromInt() returns L* from an ARGB integer.
+ *
+ * These methods, generally, convert colors between the L*a*b*, XYZ, and sRGB spaces.
+ *
+ * L*a*b* is a perceptually accurate color space. This is particularly important in the L*
+ * dimension: it measures luminance and unlike lightness measures traditionally used in UI work via
+ * RGB or HSL, this luminance transitions smoothly, permitting creation of pleasing shades of a
+ * color, and more pleasing transitions between colors.
+ *
+ * XYZ is commonly used as an intermediate color space for converting between one color space to
+ * another. For example, to convert RGB to L*a*b*, first RGB is converted to XYZ, then XYZ is
+ * converted to L*a*b*.
+ *
+ * sRGB is a "specification originated from work in 1990s through cooperation by Hewlett-Packard and
+ * Microsoft, and it was designed to be a standard definition of RGB for the internet, which it
+ * indeed became...The standard is based on a sampling of computer monitors at the time...The whole
+ * idea of sRGB is that if everyone assumed that RGB meant the same thing, then the results would be
+ * consistent, and reasonably good. It worked." - Fairchild, Color Models and Systems: Handbook of
+ * Color Psychology, 2015
+ */
+internal object CamUtils {
+    // Transforms XYZ color space coordinates to 'cone'/'RGB' responses in CAM16.
+    val XYZ_TO_CAM16RGB: Array<FloatArray> =
+        arrayOf(
+            floatArrayOf(0.401288f, 0.650173f, -0.051461f),
+            floatArrayOf(-0.250268f, 1.204414f, 0.045854f),
+            floatArrayOf(-0.002079f, 0.048952f, 0.953127f)
+        )
+
+    // Transforms 'cone'/'RGB' responses in CAM16 to XYZ color space coordinates.
+    val CAM16RGB_TO_XYZ: Array<FloatArray> =
+        arrayOf(
+            floatArrayOf(1.86206786f, -1.01125463f, 0.14918677f),
+            floatArrayOf(0.38752654f, 0.62144744f, -0.00897398f),
+            floatArrayOf(-0.01584150f, -0.03412294f, 1.04996444f)
+        )
+
+    // Need this, XYZ coordinates in internal ColorUtils are private  sRGB specification has D65
+    // whitepoint - Stokes, Anderson, Chandrasekar, Motta - A Standard Default Color Space for the
+    // Internet: sRGB, 1996
+    val WHITE_POINT_D65: FloatArray = floatArrayOf(95.047f, 100.0f, 108.883f)
+
+    // This is a more precise sRGB to XYZ transformation matrix than traditionally used. It was
+    // derived using Schlomer's technique of transforming the xyY primaries to XYZ, then applying a
+    // correction to ensure mapping from sRGB 1, 1, 1 to the reference white point, D65.
+    private val SRGB_TO_XYZ: Array<DoubleArray> =
+        arrayOf(
+            doubleArrayOf(0.41233895, 0.35762064, 0.18051042),
+            doubleArrayOf(0.2126, 0.7152, 0.0722),
+            doubleArrayOf(0.01932141, 0.11916382, 0.95034478),
+        )
+
+    private val XYZ_TO_SRGB: Array<DoubleArray> =
+        arrayOf(
+            doubleArrayOf(
+                3.2413774792388685,
+                -1.5376652402851851,
+                -0.49885366846268053,
+            ),
+            doubleArrayOf(
+                -0.9691452513005321,
+                1.8758853451067872,
+                0.04156585616912061,
+            ),
+            doubleArrayOf(
+                0.05562093689691305,
+                -0.20395524564742123,
+                1.0571799111220335,
+            ),
+        )
+
+    /**
+     * The signum function.
+     *
+     * @return 1 if num > 0, -1 if num < 0, and 0 if num = 0
+     */
+    fun signum(num: Double): Int {
+        return if (num < 0) {
+            -1
+        } else if (num == 0.0) {
+            0
+        } else {
+            1
+        }
+    }
+
+    /**
+     * Converts an L* value to an ARGB representation.
+     *
+     * @param lstar L* in L*a*b*
+     * @return ARGB representation of grayscale color with lightness matching L*
+     */
+    fun argbFromLstar(lstar: Double): Int {
+        val fy = (lstar + 16.0) / 116.0
+        val kappa = 24389.0 / 27.0
+        val epsilon = 216.0 / 24389.0
+        val lExceedsEpsilonKappa = lstar > 8.0
+        val y = if (lExceedsEpsilonKappa) fy * fy * fy else lstar / kappa
+        val cubeExceedEpsilon = fy * fy * fy > epsilon
+        val x = if (cubeExceedEpsilon) fy * fy * fy else lstar / kappa
+        val z = if (cubeExceedEpsilon) fy * fy * fy else lstar / kappa
+        val whitePoint = WHITE_POINT_D65
+        return argbFromXyz(x * whitePoint[0], y * whitePoint[1], z * whitePoint[2])
+    }
+
+    /** Converts a color from ARGB to XYZ. */
+    private fun argbFromXyz(x: Double, y: Double, z: Double): Int {
+        val matrix = XYZ_TO_SRGB
+        val linearR = matrix[0][0] * x + matrix[0][1] * y + matrix[0][2] * z
+        val linearG = matrix[1][0] * x + matrix[1][1] * y + matrix[1][2] * z
+        val linearB = matrix[2][0] * x + matrix[2][1] * y + matrix[2][2] * z
+        val r = delinearized(linearR)
+        val g = delinearized(linearG)
+        val b = delinearized(linearB)
+        return argbFromRgb(r, g, b)
+    }
+
+    /** Converts a color from linear RGB components to ARGB format. */
+    fun argbFromLinrgbComponents(r: Double, g: Double, b: Double): Int {
+        return argbFromRgb(delinearized(r), delinearized(g), delinearized(b))
+    }
+
+    /**
+     * Delinearizes an RGB component.
+     *
+     * @param rgbComponent 0.0 <= rgb_component <= 100.0, represents linear R/G/B channel
+     * @return 0 <= output <= 255, color channel converted to regular RGB space
+     */
+    private fun delinearized(rgbComponent: Double): Int {
+        val normalized = rgbComponent / 100.0
+        val delinearized: Double =
+            if (normalized <= 0.0031308) {
+                normalized * 12.92
+            } else {
+                1.055 * normalized.pow(1.0 / 2.4) - 0.055
+            }
+        return clampInt(0, 255, Math.round(delinearized * 255.0).toInt())
+    }
+
+    /**
+     * Clamps an integer between two integers.
+     *
+     * @return input when min <= input <= max, and either min or max otherwise.
+     */
+    private fun clampInt(min: Int, max: Int, input: Int): Int {
+        if (input < min) {
+            return min
+        } else if (input > max) {
+            return max
+        }
+
+        return input
+    }
+
+    /** Converts a color from RGB components to ARGB format. */
+    private fun argbFromRgb(red: Int, green: Int, blue: Int): Int {
+        return (255 shl 24) or ((red and 255) shl 16) or ((green and 255) shl 8) or (blue and 255)
+    }
+
+    fun intFromLstar(lstar: Float): Int {
+        if (lstar < 1) {
+            return -0x1000000
+        } else if (lstar > 99) {
+            return -0x1
+        }
+
+        // XYZ to LAB conversion routine, assume a and b are 0.
+        val fy = (lstar + 16.0f) / 116.0f
+
+        // fz = fx = fy because a and b are 0
+        val fz = fy
+
+        val kappa = 24389f / 27f
+        val epsilon = 216f / 24389f
+        val lExceedsEpsilonKappa = (lstar > 8.0f)
+        val yT = if (lExceedsEpsilonKappa) fy * fy * fy else lstar / kappa
+        val cubeExceedEpsilon = (fy * fy * fy) > epsilon
+        val xT = if (cubeExceedEpsilon) fy * fy * fy else (116f * fy - 16f) / kappa
+        val zT = if (cubeExceedEpsilon) fz * fz * fz else (116f * fy - 16f) / kappa
+
+        return ColorUtils.XYZToColor(
+            (xT * WHITE_POINT_D65[0]).toDouble(),
+            (yT * WHITE_POINT_D65[1]).toDouble(),
+            (zT * WHITE_POINT_D65[2]).toDouble()
+        )
+    }
+
+    /** Returns L* from L*a*b*, perceptual luminance, from an ARGB integer (ColorInt). */
+    fun lstarFromInt(argb: Int): Float {
+        return lstarFromY(yFromInt(argb))
+    }
+
+    private fun lstarFromY(y: Float): Float {
+        var yPrime = y
+        yPrime /= 100.0f
+        val e = 216f / 24389f
+        val yIntermediate: Float
+        if (yPrime <= e) {
+            return ((24389f / 27f) * yPrime)
+        } else {
+            yIntermediate = cbrt(yPrime.toDouble()).toFloat()
+        }
+        return 116f * yIntermediate - 16f
+    }
+
+    private fun yFromInt(argb: Int): Float {
+        val r = linearized(argb.red)
+        val g = linearized(argb.green)
+        val b = linearized(argb.blue)
+        val matrix = SRGB_TO_XYZ
+        val y = (r * matrix[1][0]) + (g * matrix[1][1]) + (b * matrix[1][2])
+        return y.toFloat()
+    }
+
+    fun xyzFromInt(argb: Int): FloatArray {
+        val r = linearized(argb.red)
+        val g = linearized(argb.green)
+        val b = linearized(argb.blue)
+
+        val matrix = SRGB_TO_XYZ
+        val x = (r * matrix[0][0]) + (g * matrix[0][1]) + (b * matrix[0][2])
+        val y = (r * matrix[1][0]) + (g * matrix[1][1]) + (b * matrix[1][2])
+        val z = (r * matrix[2][0]) + (g * matrix[2][1]) + (b * matrix[2][2])
+        return floatArrayOf(x.toFloat(), y.toFloat(), z.toFloat())
+    }
+
+    /**
+     * Converts an L* value to a Y value.
+     *
+     * L* in L*a*b* and Y in XYZ measure the same quantity, luminance.
+     *
+     * L* measures perceptual luminance, a linear scale. Y in XYZ measures relative luminance, a
+     * logarithmic scale.
+     *
+     * @param lstar L* in L*a*b*
+     * @return Y in XYZ
+     */
+    fun yFromLstar(lstar: Double): Double {
+        val ke = 8.0
+        return if (lstar > ke) {
+            ((lstar + 16.0) / 116.0).pow(3.0) * 100.0
+        } else {
+            lstar / (24389.0 / 27.0) * 100.0
+        }
+    }
+
+    private fun linearized(rgbComponent: Int): Float {
+        val normalized = rgbComponent.toFloat() / 255.0f
+
+        return if (normalized <= 0.04045f) {
+            normalized / 12.92f * 100.0f
+        } else {
+            ((normalized + 0.055f) / 1.055f).pow(2.4f) * 100.0f
+        }
+    }
+}
diff --git a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/internal/colorUtil/Frame.android.kt b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/internal/colorUtil/Frame.android.kt
new file mode 100644
index 0000000..4ae23a7
--- /dev/null
+++ b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/internal/colorUtil/Frame.android.kt
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3.internal.colorUtil
+
+import androidx.annotation.VisibleForTesting
+import androidx.compose.material3.internal.colorUtil.CamUtils.yFromLstar
+import kotlin.math.PI
+import kotlin.math.cbrt
+import kotlin.math.exp
+import kotlin.math.pow
+import kotlin.math.sqrt
+
+/**
+ * NOTICE: Fork and kotlin transpilation of
+ * frameworks/base/core/java/com/android/internal/graphics/cam/Frame.java Manual changes have not
+ * and should not be implemented except for compilation purposes between kotlin and java. Unused
+ * methods were also removed.
+ *
+ * The frame, or viewing conditions, where a color was seen. Used, along with a color, to create a
+ * color appearance model representing the color.
+ *
+ * To convert a traditional color to a color appearance model, it requires knowing what conditions
+ * the color was observed in. Our perception of color depends on, for example, the tone of the light
+ * illuminating the color, how bright that light was, etc.
+ *
+ * This class is modelled separately from the color appearance model itself because there are a
+ * number of calculations during the color => CAM conversion process that depend only on the viewing
+ * conditions. Caching those calculations in a Frame instance saves a significant amount of time.
+ */
+internal class Frame
+private constructor(
+    @get:VisibleForTesting val n: Float,
+    @get:VisibleForTesting val aw: Float,
+    @get:VisibleForTesting val nbb: Float,
+    val ncb: Float,
+    val c: Float,
+    val nc: Float,
+    @get:VisibleForTesting val rgbD: FloatArray,
+    val fl: Float,
+    @get:VisibleForTesting val flRoot: Float,
+    val z: Float
+) {
+    companion object {
+        // Standard viewing conditions assumed in RGB specification - Stokes, Anderson,
+        // Chandrasekar, Motta - A Standard Default Color Space for the Internet: sRGB, 1996.
+        //
+        // White point = D65
+        //
+        // Luminance of adapting field: 200 / Pi / 5, units are cd/m^2.
+        //
+        // sRGB ambient illuminance = 64 lux (per sRGB spec). However, the spec notes this is
+        // artificially low and based on monitors in 1990s. Use 200, the sRGB spec says this is the
+        // real average, and a survey of lux values on Wikipedia confirms this is a comfortable
+        // default: somewhere between a very dark overcast day and office lighting.
+        //
+        // Per CAM16 introduction paper (Li et al, 2017) Ew = pi * lw, and La = lw * Yb/Yw
+        // Ew = ambient environment luminance, in lux.
+        // Yb/Yw is taken to be midgray, ~20% relative luminance (XYZ Y 18.4, CIELAB L* 50).
+        // Therefore La = (Ew / pi) * .184
+        // La = 200 / pi * .184
+        // Image surround to 10 degrees = ~20% relative luminance = CIELAB L* 50
+        //
+        // Not from sRGB standard:
+        // Surround = average, 2.0.
+        // Discounting illuminant = false, doesn't occur for self-luminous displays
+        val Default: Frame =
+            make(
+                CamUtils.WHITE_POINT_D65,
+                (200.0f / PI * yFromLstar(50.0) / 100.0).toFloat(),
+                50.0f,
+                2.0f,
+                false
+            )
+
+        /** Create a custom frame. */
+        fun make(
+            whitepoint: FloatArray,
+            adaptingLuminance: Float,
+            backgroundLstar: Float,
+            surround: Float,
+            discountingIlluminant: Boolean
+        ): Frame {
+            // Transform white point XYZ to 'cone'/'rgb' responses
+            val matrix = CamUtils.XYZ_TO_CAM16RGB
+            val rW =
+                (whitepoint[0] * matrix[0][0]) +
+                    (whitepoint[1] * matrix[0][1]) +
+                    (whitepoint[2] * matrix[0][2])
+            val gW =
+                (whitepoint[0] * matrix[1][0]) +
+                    (whitepoint[1] * matrix[1][1]) +
+                    (whitepoint[2] * matrix[1][2])
+            val bW =
+                (whitepoint[0] * matrix[2][0]) +
+                    (whitepoint[1] * matrix[2][1]) +
+                    (whitepoint[2] * matrix[2][2])
+
+            // Scale input surround, domain (0, 2), to CAM16 surround, domain (0.8, 1.0)
+            val f = 0.8f + (surround / 10.0f)
+            // "Exponential non-linearity"
+            val c: Float =
+                if ((f >= 0.9)) lerp(0.59f, 0.69f, ((f - 0.9f) * 10.0f))
+                else lerp(0.525f, 0.59f, ((f - 0.8f) * 10.0f))
+            // Calculate degree of adaptation to illuminant
+            var d =
+                if (discountingIlluminant) 1.0f
+                else
+                    f *
+                        (1.0f -
+                            ((1.0f / 3.6f) *
+                                exp(((-adaptingLuminance - 42.0f) / 92.0f).toDouble()).toFloat()))
+            // Per Li et al, if D is greater than 1 or less than 0, set it to 1 or 0.
+            d = if ((d > 1.0)) 1.0f else if ((d < 0.0)) 0.0f else d
+            // Chromatic induction factor
+            val nc = f
+
+            // Cone responses to the whitepoint, adjusted for illuminant discounting.
+            //
+            // Why use 100.0 instead of the white point's relative luminance?
+            //
+            // Some papers and implementations, for both CAM02 and CAM16, use the Y value of the
+            // reference white instead of 100. Fairchild's Color Appearance Models (3rd edition)
+            // notes that this is in error: it was included in the CIE 2004a report on CIECAM02,
+            // but, later parts of the conversion process account for scaling of appearance relative
+            // to the white point relative luminance. This part should simply use 100 as luminance.
+            val rgbD =
+                floatArrayOf(
+                    d * (100.0f / rW) + 1.0f - d,
+                    d * (100.0f / gW) + 1.0f - d,
+                    d * (100.0f / bW) + 1.0f - d,
+                )
+            // Luminance-level adaptation factor
+            val k = 1.0f / (5.0f * adaptingLuminance + 1.0f)
+            val k4 = k * k * k * k
+            val k4F = 1.0f - k4
+            val fl =
+                (k4 * adaptingLuminance) +
+                    (0.1f * k4F * k4F * cbrt(5.0 * adaptingLuminance).toFloat())
+
+            // Intermediate factor, ratio of background relative luminance to white relative
+            // luminance
+            val n = yFromLstar(backgroundLstar.toDouble()).toFloat() / whitepoint[1]
+
+            // Base exponential nonlinearity note Schlomer 2018 has a typo and uses 1.58, the
+            // correct factor is 1.48
+            val z = 1.48f + sqrt(n)
+
+            // Luminance-level induction factors
+            val nbb = 0.725f / n.pow(0.2f)
+
+            // Discounted cone responses to the white point, adjusted for post-chromatic adaptation
+            // perceptual nonlinearities.
+            val rgbAFactors =
+                floatArrayOf(
+                    (fl * rgbD[0] * rW / 100f).pow(0.42f),
+                    (fl * rgbD[1] * gW / 100f).pow(0.42f),
+                    (fl * rgbD[2] * bW / 100f).pow(0.42f)
+                )
+
+            val rgbA =
+                floatArrayOf(
+                    (400.0f * rgbAFactors[0]) / (rgbAFactors[0] + 27.13f),
+                    (400.0f * rgbAFactors[1]) / (rgbAFactors[1] + 27.13f),
+                    (400.0f * rgbAFactors[2]) / (rgbAFactors[2] + 27.13f),
+                )
+
+            val aw = ((2.0f * rgbA[0]) + rgbA[1] + (0.05f * rgbA[2])) * nbb
+
+            return Frame(n, aw, nbb, nbb, c, nc, rgbD, fl, fl.pow(0.25f), z)
+        }
+    }
+}
+
+/**
+ * The linear interpolation function.
+ *
+ * @return start if amount = 0 and stop if amount = 1
+ */
+private fun lerp(start: Float, stop: Float, amount: Float): Float {
+    return (1.0f - amount) * start + amount * stop
+}
diff --git a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/internal/colorUtil/HCTSolver.android.kt b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/internal/colorUtil/HCTSolver.android.kt
new file mode 100644
index 0000000..d72f41d
--- /dev/null
+++ b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/internal/colorUtil/HCTSolver.android.kt
@@ -0,0 +1,735 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3.internal.colorUtil
+
+import kotlin.math.abs
+import kotlin.math.atan2
+import kotlin.math.ceil
+import kotlin.math.cos
+import kotlin.math.floor
+import kotlin.math.max
+import kotlin.math.pow
+import kotlin.math.sin
+import kotlin.math.sqrt
+
+/**
+ * NOTICE: Fork and kotlin transpilation of
+ * frameworks/base/core/java/com/android/internal/graphics/cam/HctSolver.java Manual changes have
+ * not and should not be implemented except for compilation purposes between kotlin and java. Unused
+ * methods were also removed.
+ *
+ * An efficient algorithm for determining the closest sRGB color to a set of HCT coordinates, based
+ * on geometrical insights for finding intersections in linear RGB, CAM16, and L*a*b*.
+ *
+ * Algorithm identified and implemented by Tianguang Zhang. Copied from
+ * //java/com/google/ux/material/libmonet/hct on May 22 2022. ColorUtils/MathUtils functions that
+ * were required were added to CamUtils.
+ */
+internal object HctSolver {
+    // Matrix used when converting from linear RGB to CAM16.
+    private val SCALED_DISCOUNT_FROM_LINRGB: Array<DoubleArray> =
+        arrayOf(
+            doubleArrayOf(
+                0.001200833568784504,
+                0.002389694492170889,
+                0.0002795742885861124,
+            ),
+            doubleArrayOf(
+                0.0005891086651375999,
+                0.0029785502573438758,
+                0.0003270666104008398,
+            ),
+            doubleArrayOf(
+                0.00010146692491640572,
+                0.0005364214359186694,
+                0.0032979401770712076,
+            ),
+        )
+
+    // Matrix used when converting from CAM16 to linear RGB.
+    private val LINRGB_FROM_SCALED_DISCOUNT: Array<DoubleArray> =
+        arrayOf(
+            doubleArrayOf(
+                1373.2198709594231,
+                -1100.4251190754821,
+                -7.278681089101213,
+            ),
+            doubleArrayOf(
+                -271.815969077903,
+                559.6580465940733,
+                -32.46047482791194,
+            ),
+            doubleArrayOf(
+                1.9622899599665666,
+                -57.173814538844006,
+                308.7233197812385,
+            ),
+        )
+
+    // Weights for transforming a set of linear RGB coordinates to Y in XYZ.
+    private val Y_FROM_LINRGB: DoubleArray = doubleArrayOf(0.2126, 0.7152, 0.0722)
+
+    // Lookup table for plane in XYZ's Y axis (relative luminance) that corresponds to a given
+    // L* in L*a*b*. HCT's T is L*, and XYZ's Y is directly correlated to linear RGB, this table
+    // allows us to thus find the intersection between HCT and RGB, giving a solution to the
+    // RGB coordinates that correspond to a given set of HCT coordinates.
+    private val CRITICAL_PLANES: DoubleArray =
+        doubleArrayOf(
+            0.015176349177441876,
+            0.045529047532325624,
+            0.07588174588720938,
+            0.10623444424209313,
+            0.13658714259697685,
+            0.16693984095186062,
+            0.19729253930674434,
+            0.2276452376616281,
+            0.2579979360165119,
+            0.28835063437139563,
+            0.3188300904430532,
+            0.350925934958123,
+            0.3848314933096426,
+            0.42057480301049466,
+            0.458183274052838,
+            0.4976837250274023,
+            0.5391024159806381,
+            0.5824650784040898,
+            0.6277969426914107,
+            0.6751227633498623,
+            0.7244668422128921,
+            0.775853049866786,
+            0.829304845476233,
+            0.8848452951698498,
+            0.942497089126609,
+            1.0022825574869039,
+            1.0642236851973577,
+            1.1283421258858297,
+            1.1946592148522128,
+            1.2631959812511864,
+            1.3339731595349034,
+            1.407011200216447,
+            1.4823302800086415,
+            1.5599503113873272,
+            1.6398909516233677,
+            1.7221716113234105,
+            1.8068114625156377,
+            1.8938294463134073,
+            1.9832442801866852,
+            2.075074464868551,
+            2.1693382909216234,
+            2.2660538449872063,
+            2.36523901573795,
+            2.4669114995532007,
+            2.5710888059345764,
+            2.6777882626779785,
+            2.7870270208169257,
+            2.898822059350997,
+            3.0131901897720907,
+            3.1301480604002863,
+            3.2497121605402226,
+            3.3718988244681087,
+            3.4967242352587946,
+            3.624204428461639,
+            3.754355295633311,
+            3.887192587735158,
+            4.022731918402185,
+            4.160988767090289,
+            4.301978482107941,
+            4.445716283538092,
+            4.592217266055746,
+            4.741496401646282,
+            4.893568542229298,
+            5.048448422192488,
+            5.20615066083972,
+            5.3666897647573375,
+            5.5300801301023865,
+            5.696336044816294,
+            5.865471690767354,
+            6.037501145825082,
+            6.212438385869475,
+            6.390297286737924,
+            6.571091626112461,
+            6.7548350853498045,
+            6.941541251256611,
+            7.131223617812143,
+            7.323895587840543,
+            7.5195704746346665,
+            7.7182615035334345,
+            7.919981813454504,
+            8.124744458384042,
+            8.332562408825165,
+            8.543448553206703,
+            8.757415699253682,
+            8.974476575321063,
+            9.194643831691977,
+            9.417930041841839,
+            9.644347703669503,
+            9.873909240696694,
+            10.106627003236781,
+            10.342513269534024,
+            10.58158024687427,
+            10.8238400726681,
+            11.069304815507364,
+            11.317986476196008,
+            11.569896988756009,
+            11.825048221409341,
+            12.083451977536606,
+            12.345119996613247,
+            12.610063955123938,
+            12.878295467455942,
+            13.149826086772048,
+            13.42466730586372,
+            13.702830557985108,
+            13.984327217668513,
+            14.269168601521828,
+            14.55736596900856,
+            14.848930523210871,
+            15.143873411576273,
+            15.44220572664832,
+            15.743938506781891,
+            16.04908273684337,
+            16.35764934889634,
+            16.66964922287304,
+            16.985093187232053,
+            17.30399201960269,
+            17.62635644741625,
+            17.95219714852476,
+            18.281524751807332,
+            18.614349837764564,
+            18.95068293910138,
+            19.290534541298456,
+            19.633915083172692,
+            19.98083495742689,
+            20.331304511189067,
+            20.685334046541502,
+            21.042933821039977,
+            21.404114048223256,
+            21.76888489811322,
+            22.137256497705877,
+            22.50923893145328,
+            22.884842241736916,
+            23.264076429332462,
+            23.6469514538663,
+            24.033477234264016,
+            24.42366364919083,
+            24.817520537484558,
+            25.21505769858089,
+            25.61628489293138,
+            26.021211842414342,
+            26.429848230738664,
+            26.842203703840827,
+            27.258287870275353,
+            27.678110301598522,
+            28.10168053274597,
+            28.529008062403893,
+            28.96010235337422,
+            29.39497283293396,
+            29.83362889318845,
+            30.276079891419332,
+            30.722335150426627,
+            31.172403958865512,
+            31.62629557157785,
+            32.08401920991837,
+            32.54558406207592,
+            33.010999283389665,
+            33.4802739966603,
+            33.953417292456834,
+            34.430438229418264,
+            34.911345834551085,
+            35.39614910352207,
+            35.88485700094671,
+            36.37747846067349,
+            36.87402238606382,
+            37.37449765026789,
+            37.87891309649659,
+            38.38727753828926,
+            38.89959975977785,
+            39.41588851594697,
+            39.93615253289054,
+            40.460400508064545,
+            40.98864111053629,
+            41.520882981230194,
+            42.05713473317016,
+            42.597404951718396,
+            43.141702194811224,
+            43.6900349931913,
+            44.24241185063697,
+            44.798841244188324,
+            45.35933162437017,
+            45.92389141541209,
+            46.49252901546552,
+            47.065252796817916,
+            47.64207110610409,
+            48.22299226451468,
+            48.808024568002054,
+            49.3971762874833,
+            49.9904556690408,
+            50.587870934119984,
+            51.189430279724725,
+            51.79514187861014,
+            52.40501387947288,
+            53.0190544071392,
+            53.637271562750364,
+            54.259673423945976,
+            54.88626804504493,
+            55.517063457223934,
+            56.15206766869424,
+            56.79128866487574,
+            57.43473440856916,
+            58.08241284012621,
+            58.734331877617365,
+            59.39049941699807,
+            60.05092333227251,
+            60.715611475655585,
+            61.38457167773311,
+            62.057811747619894,
+            62.7353394731159,
+            63.417162620860914,
+            64.10328893648692,
+            64.79372614476921,
+            65.48848194977529,
+            66.18756403501224,
+            66.89098006357258,
+            67.59873767827808,
+            68.31084450182222,
+            69.02730813691093,
+            69.74813616640164,
+            70.47333615344107,
+            71.20291564160104,
+            71.93688215501312,
+            72.67524319850172,
+            73.41800625771542,
+            74.16517879925733,
+            74.9167682708136,
+            75.67278210128072,
+            76.43322770089146,
+            77.1981124613393,
+            77.96744375590167,
+            78.74122893956174,
+            79.51947534912904,
+            80.30219030335869,
+            81.08938110306934,
+            81.88105503125999,
+            82.67721935322541,
+            83.4778813166706,
+            84.28304815182372,
+            85.09272707154808,
+            85.90692527145302,
+            86.72564993000343,
+            87.54890820862819,
+            88.3767072518277,
+            89.2090541872801,
+            90.04595612594655,
+            90.88742016217518,
+            91.73345337380438,
+            92.58406282226491,
+            93.43925555268066,
+            94.29903859396902,
+            95.16341895893969,
+            96.03240364439274,
+            96.9059996312159,
+            97.78421388448044,
+            98.6670533535366,
+            99.55452497210776,
+        )
+
+    /**
+     * Sanitizes a small enough angle in radians.
+     *
+     * @param angle An angle in radians; must not deviate too much from 0.
+     * @return A coterminal angle between 0 and 2pi.
+     */
+    private fun sanitizeRadians(angle: Double): Double {
+        return (angle + Math.PI * 8) % (Math.PI * 2)
+    }
+
+    /**
+     * Delinearizes an RGB component, returning a floating-point number.
+     *
+     * @param rgbComponent 0.0 <= rgb_component <= 100.0, represents linear R/G/B channel
+     * @return 0.0 <= output <= 255.0, color channel converted to regular RGB space
+     */
+    private fun trueDelinearized(rgbComponent: Double): Double {
+        val normalized = rgbComponent / 100.0
+        val delinearized =
+            if (normalized <= 0.0031308) {
+                normalized * 12.92
+            } else {
+                1.055 * normalized.pow(1.0 / 2.4) - 0.055
+            }
+        return delinearized * 255
+    }
+
+    private fun chromaticAdaptation(component: Double): Double {
+        val af: Double = abs(component).pow(0.42)
+        return CamUtils.signum(component) * 400.0 * af / (af + 27.13)
+    }
+
+    /**
+     * Returns the hue of a linear RGB color in CAM16.
+     *
+     * @param linrgb The linear RGB coordinates of a color.
+     * @return The hue of the color in CAM16, in radians.
+     */
+    private fun hueOf(linrgb: DoubleArray): Double {
+        // Calculate scaled discount components using in-lined matrix multiplication to avoid an
+        // array allocation.
+        val matrix = SCALED_DISCOUNT_FROM_LINRGB
+        val rD = linrgb[0] * matrix[0][0] + linrgb[1] * matrix[0][1] + linrgb[2] * matrix[0][2]
+        val gD = linrgb[0] * matrix[1][0] + linrgb[1] * matrix[1][1] + linrgb[2] * matrix[1][2]
+        val bD = linrgb[0] * matrix[2][0] + linrgb[1] * matrix[2][1] + linrgb[2] * matrix[2][2]
+
+        val rA = chromaticAdaptation(rD)
+        val gA = chromaticAdaptation(gD)
+        val bA = chromaticAdaptation(bD)
+        // redness-greenness
+        val a = (11.0 * rA + -12.0 * gA + bA) / 11.0
+        // yellowness-blueness
+        val b = (rA + gA - 2.0 * bA) / 9.0
+        return atan2(b, a)
+    }
+
+    /**
+     * Cyclic order is the idea that 330° → 5° → 200° is in order, but, 180° → 270° → 210° is not.
+     * Visually, A B and C are angles, and they are in cyclic order if travelling from A to C in a
+     * way that increases angle (ex. counter-clockwise if +x axis = 0 degrees and +y = 90) means you
+     * must cross B.
+     *
+     * @param a first angle in possibly cyclic triplet
+     * @param b second angle in possibly cyclic triplet
+     * @param c third angle in possibly cyclic triplet
+     * @return true if B is between A and C
+     */
+    private fun areInCyclicOrder(a: Double, b: Double, c: Double): Boolean {
+        val deltaAB = sanitizeRadians(b - a)
+        val deltaAC = sanitizeRadians(c - a)
+        return deltaAB < deltaAC
+    }
+
+    /**
+     * Find an intercept using linear interpolation.
+     *
+     * @param source The starting number.
+     * @param mid The number in the middle.
+     * @param target The ending number.
+     * @return A number t such that lerp(source, target, t) = mid.
+     */
+    private fun intercept(source: Double, mid: Double, target: Double): Double {
+        if (target == source) {
+            return target
+        }
+        return (mid - source) / (target - source)
+    }
+
+    /**
+     * Linearly interpolate between two points in three dimensions.
+     *
+     * @param source three dimensions representing the starting point
+     * @param t the percentage to travel between source and target, from 0 to 1
+     * @param target three dimensions representing the end point
+     * @return three dimensions representing the point t percent from source to target.
+     */
+    private fun lerpPoint(source: DoubleArray, t: Double, target: DoubleArray): DoubleArray {
+        return doubleArrayOf(
+            source[0] + (target[0] - source[0]) * t,
+            source[1] + (target[1] - source[1]) * t,
+            source[2] + (target[2] - source[2]) * t,
+        )
+    }
+
+    /**
+     * Intersects a segment with a plane.
+     *
+     * @param source The coordinates of point A.
+     * @param coordinate The R-, G-, or B-coordinate of the plane.
+     * @param target The coordinates of point B.
+     * @param axis The axis the plane is perpendicular with. (0: R, 1: G, 2: B)
+     * @return The intersection point of the segment AB with the plane R=coordinate, G=coordinate,
+     *   or B=coordinate
+     */
+    private fun setCoordinate(
+        source: DoubleArray,
+        coordinate: Double,
+        target: DoubleArray,
+        axis: Int
+    ): DoubleArray {
+        val t = intercept(source[axis], coordinate, target[axis])
+        return lerpPoint(source, t, target)
+    }
+
+    /** Ensure X is between 0 and 100. */
+    private fun isBounded(x: Double): Boolean {
+        return x in 0.0..100.0
+    }
+
+    /**
+     * Returns the nth possible vertex of the polygonal intersection.
+     *
+     * @param y The Y value of the plane.
+     * @param n The zero-based index of the point. 0 <= n <= 11.
+     * @return The nth possible vertex of the polygonal intersection of the y plane and the RGB cube
+     *   in linear RGB coordinates, if it exists. If the possible vertex lies outside of the cube,
+     *   [-1.0, -1.0, -1.0] is returned.
+     */
+    private fun nthVertex(y: Double, n: Int): DoubleArray {
+        val kR = Y_FROM_LINRGB[0]
+        val kG = Y_FROM_LINRGB[1]
+        val kB = Y_FROM_LINRGB[2]
+        val coordA = if (n % 4 <= 1) 0.0 else 100.0
+        val coordB = if (n % 2 == 0) 0.0 else 100.0
+        if (n < 4) {
+            val r = (y - coordA * kG - coordB * kB) / kR
+            return if (isBounded(r)) {
+                doubleArrayOf(r, coordA, coordB)
+            } else {
+                doubleArrayOf(-1.0, -1.0, -1.0)
+            }
+        } else if (n < 8) {
+            val g = (y - coordB * kR - coordA * kB) / kG
+            return if (isBounded(g)) {
+                doubleArrayOf(coordB, g, coordA)
+            } else {
+                doubleArrayOf(-1.0, -1.0, -1.0)
+            }
+        } else {
+            val b = (y - coordA * kR - coordB * kG) / kB
+            return if (isBounded(b)) {
+                doubleArrayOf(coordA, coordB, b)
+            } else {
+                doubleArrayOf(-1.0, -1.0, -1.0)
+            }
+        }
+    }
+
+    /**
+     * Finds the segment containing the desired color.
+     *
+     * @param y The Y value of the color.
+     * @param targetHue The hue of the color.
+     * @return A list of two sets of linear RGB coordinates, each corresponding to an endpoint of
+     *   the segment containing the desired color.
+     */
+    private fun bisectToSegment(y: Double, targetHue: Double): Array<DoubleArray> {
+        var left = doubleArrayOf(-1.0, -1.0, -1.0)
+        var right = left
+        var leftHue = 0.0
+        var rightHue = 0.0
+        var initialized = false
+        var uncut = true
+        for (n in 0..11) {
+            val mid = nthVertex(y, n)
+            if (mid[0] < 0) {
+                continue
+            }
+            val midHue = hueOf(mid)
+            if (!initialized) {
+                left = mid
+                right = mid
+                leftHue = midHue
+                rightHue = midHue
+                initialized = true
+                continue
+            }
+            if (uncut || areInCyclicOrder(leftHue, midHue, rightHue)) {
+                uncut = false
+                if (areInCyclicOrder(leftHue, targetHue, midHue)) {
+                    right = mid
+                    rightHue = midHue
+                } else {
+                    left = mid
+                    leftHue = midHue
+                }
+            }
+        }
+        return arrayOf(left, right)
+    }
+
+    private fun criticalPlaneBelow(x: Double): Int {
+        return floor(x - 0.5).toInt()
+    }
+
+    private fun criticalPlaneAbove(x: Double): Int {
+        return ceil(x - 0.5).toInt()
+    }
+
+    /**
+     * Finds a color with the given Y and hue on the boundary of the cube.
+     *
+     * @param y The Y value of the color.
+     * @param targetHue The hue of the color.
+     * @return The desired color, in linear RGB coordinates.
+     */
+    private fun bisectToLimit(y: Double, targetHue: Double): Int {
+        val segment = bisectToSegment(y, targetHue)
+        var left = segment[0]
+        var leftHue = hueOf(left)
+        var right = segment[1]
+        for (axis in 0..2) {
+            if (left[axis] != right[axis]) {
+                var lPlane: Int
+                var rPlane: Int
+                if (left[axis] < right[axis]) {
+                    lPlane = criticalPlaneBelow(trueDelinearized(left[axis]))
+                    rPlane = criticalPlaneAbove(trueDelinearized(right[axis]))
+                } else {
+                    lPlane = criticalPlaneAbove(trueDelinearized(left[axis]))
+                    rPlane = criticalPlaneBelow(trueDelinearized(right[axis]))
+                }
+                for (i in 0..7) {
+                    if (abs((rPlane - lPlane).toDouble()) <= 1) {
+                        break
+                    } else {
+                        val mPlane = floor((lPlane + rPlane) / 2.0).toInt()
+                        val midPlaneCoordinate = CRITICAL_PLANES[mPlane]
+                        val mid = setCoordinate(left, midPlaneCoordinate, right, axis)
+                        val midHue = hueOf(mid)
+                        if (areInCyclicOrder(leftHue, targetHue, midHue)) {
+                            right = mid
+                            rPlane = mPlane
+                        } else {
+                            left = mid
+                            leftHue = midHue
+                            lPlane = mPlane
+                        }
+                    }
+                }
+            }
+        }
+        return CamUtils.argbFromLinrgbComponents(
+            (left[0] + right[0]) / 2,
+            (left[1] + right[1]) / 2,
+            (left[2] + right[2]) / 2
+        )
+    }
+
+    /** Equation used in CAM16 conversion that removes the effect of chromatic adaptation. */
+    private fun inverseChromaticAdaptation(adapted: Double): Double {
+        val adaptedAbs = abs(adapted)
+        val base = max(0.0, 27.13 * adaptedAbs / (400.0 - adaptedAbs))
+        return CamUtils.signum(adapted) * base.pow(1.0 / 0.42)
+    }
+
+    /**
+     * Finds a color with the given hue, chroma, and Y.
+     *
+     * @param hueRadians The desired hue in radians.
+     * @param chroma The desired chroma.
+     * @param y The desired Y.
+     * @return The desired color as a hexadecimal integer, if found; 0 otherwise.
+     */
+    private fun findResultByJ(hueRadians: Double, chroma: Double, y: Double): Int {
+        // Initial estimate of j.
+        var j = sqrt(y) * 11.0
+        // ===========================================================
+        // Operations inlined from Cam16 to avoid repeated calculation
+        // ===========================================================
+        val viewingConditions: Frame = Frame.Default
+        val tInnerCoeff: Double = 1 / (1.64 - 0.29.pow(viewingConditions.n.toDouble())).pow(0.73)
+        val eHue = 0.25 * (cos(hueRadians + 2.0) + 3.8)
+        val p1: Double = (eHue * (50000.0 / 13.0) * viewingConditions.nc * viewingConditions.ncb)
+        val hSin = sin(hueRadians)
+        val hCos = cos(hueRadians)
+        for (iterationRound in 0..4) {
+            // ===========================================================
+            // Operations inlined from Cam16 to avoid repeated calculation
+            // ===========================================================
+            val jNormalized = j / 100.0
+            val alpha = if (chroma == 0.0 || j == 0.0) 0.0 else chroma / sqrt(jNormalized)
+            val t: Double = (alpha * tInnerCoeff).pow(1.0 / 0.9)
+            val acExponent: Double = 1.0 / viewingConditions.c / viewingConditions.z
+            val ac: Double = viewingConditions.aw * jNormalized.pow(acExponent)
+            val p2: Double = ac / viewingConditions.nbb
+            val gamma = 23.0 * (p2 + 0.305) * t / (23.0 * p1 + 11 * t * hCos + 108.0 * t * hSin)
+            val a = gamma * hCos
+            val b = gamma * hSin
+            val rA = (460.0 * p2 + 451.0 * a + 288.0 * b) / 1403.0
+            val gA = (460.0 * p2 - 891.0 * a - 261.0 * b) / 1403.0
+            val bA = (460.0 * p2 - 220.0 * a - 6300.0 * b) / 1403.0
+            val rCScaled = inverseChromaticAdaptation(rA)
+            val gCScaled = inverseChromaticAdaptation(gA)
+            val bCScaled = inverseChromaticAdaptation(bA)
+            val matrix = LINRGB_FROM_SCALED_DISCOUNT
+            val linrgbR =
+                rCScaled * matrix[0][0] + gCScaled * matrix[0][1] + bCScaled * matrix[0][2]
+            val linrgbG =
+                rCScaled * matrix[1][0] + gCScaled * matrix[1][1] + bCScaled * matrix[1][2]
+            val linrgbB =
+                rCScaled * matrix[2][0] + gCScaled * matrix[2][1] + bCScaled * matrix[2][2]
+            // ===========================================================
+            // Operations inlined from Cam16 to avoid repeated calculation
+            // ===========================================================
+            if (linrgbR < 0 || linrgbG < 0 || linrgbB < 0) {
+                return 0
+            }
+            val kR = Y_FROM_LINRGB[0]
+            val kG = Y_FROM_LINRGB[1]
+            val kB = Y_FROM_LINRGB[2]
+            val fnj = kR * linrgbR + kG * linrgbG + kB * linrgbB
+            if (fnj <= 0) {
+                return 0
+            }
+            if (iterationRound == 4 || abs(fnj - y) < 0.002) {
+                if (linrgbR > 100.01 || linrgbG > 100.01 || linrgbB > 100.01) {
+                    return 0
+                }
+                return CamUtils.argbFromLinrgbComponents(linrgbR, linrgbG, linrgbB)
+            }
+            // Iterates with Newton method,
+            // Using 2 * fn(j) / j as the approximation of fn'(j)
+            j -= (fnj - y) * j / (2 * fnj)
+        }
+        return 0
+    }
+
+    /**
+     * Finds an sRGB color with the given hue, chroma, and L*, if possible.
+     *
+     * @param hueDegrees The desired hue, in degrees.
+     * @param chroma The desired chroma.
+     * @param lstar The desired L*.
+     * @return A hexadecimal representing the sRGB color. The color has sufficiently close hue,
+     *   chroma, and L* to the desired values, if possible; otherwise, the hue and L* will be
+     *   sufficiently close, and chroma will be maximized.
+     */
+    fun solveToInt(hueDegrees: Double, chroma: Double, lstar: Double): Int {
+        var hueDegreesPrime = hueDegrees
+        if (chroma < 0.0001 || lstar < 0.0001 || lstar > 99.9999) {
+            return CamUtils.argbFromLstar(lstar)
+        }
+        hueDegreesPrime = sanitizeDegreesDouble(hueDegreesPrime)
+        val hueRadians = Math.toRadians(hueDegreesPrime)
+        val y: Double = CamUtils.yFromLstar(lstar)
+        val exactAnswer = findResultByJ(hueRadians, chroma, y)
+        if (exactAnswer != 0) {
+            return exactAnswer
+        }
+        return bisectToLimit(y, hueRadians)
+    }
+
+    /**
+     * Sanitizes a degree measure as a floating-point number.
+     *
+     * @return a degree measure between 0.0 (inclusive) and 360.0 (exclusive).
+     */
+    private fun sanitizeDegreesDouble(degrees: Double): Double {
+        var degreesPrime = degrees
+        degreesPrime %= 360.0
+        if (degreesPrime < 0) {
+            degreesPrime += 360.0
+        }
+        return degreesPrime
+    }
+}
diff --git a/compose/material3/material3/src/androidMain/res/values-fa/strings.xml b/compose/material3/material3/src/androidMain/res/values-fa/strings.xml
index 3e95387..e31081f 100644
--- a/compose/material3/material3/src/androidMain/res/values-fa/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-fa/strings.xml
@@ -27,7 +27,7 @@
     <string name="m3c_date_picker_title" msgid="7430790972741451689">"انتخاب تاریخ"</string>
     <string name="m3c_date_picker_headline" msgid="7605002211875882969">"تاریخ انتخابی"</string>
     <string name="m3c_date_picker_switch_to_year_selection" msgid="791651718641787594">"رفتن به انتخاب سال"</string>
-    <string name="m3c_date_picker_switch_to_day_selection" msgid="395627960681594326">"برای انتخاب سال، تند بکشید یا برای برگشتن به انتخاب روز، ضربه بزنید"</string>
+    <string name="m3c_date_picker_switch_to_day_selection" msgid="395627960681594326">"برای انتخاب سال، تند بکشید یا برای برگشتن به انتخاب روز، تک‌ضرب بزنید"</string>
     <string name="m3c_date_picker_switch_to_next_month" msgid="7142101321095356500">"تغییر به ماه بعدی"</string>
     <string name="m3c_date_picker_switch_to_previous_month" msgid="228438865139394590">"تغییر به ماه قبلی"</string>
     <string name="m3c_date_picker_navigate_to_year_description" msgid="8436650776581492840">"‏پیمایش به سال %1$s"</string>
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/AppBar.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/AppBar.kt
index accd46e..1018ffb 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/AppBar.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/AppBar.kt
@@ -53,6 +53,7 @@
 import androidx.compose.material3.tokens.TopAppBarMediumTokens
 import androidx.compose.material3.tokens.TopAppBarSmallCenteredTokens
 import androidx.compose.material3.tokens.TopAppBarSmallTokens
+import androidx.compose.material3.tokens.TypographyKeyTokens
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.Stable
@@ -191,6 +192,7 @@
  *   work in conjunction with a scrolled content to change the top app bar appearance as the content
  *   scrolls. See [TopAppBarScrollBehavior.nestedScrollConnection].
  */
+@OptIn(ExperimentalMaterial3ExpressiveApi::class)
 @ExperimentalMaterial3Api
 @Composable
 fun TopAppBar(
@@ -207,7 +209,9 @@
         modifier = modifier,
         title = title,
         titleTextStyle = TopAppBarSmallTokens.HeadlineFont.value,
-        centeredTitle = false,
+        subtitle = {},
+        subtitleTextStyle = TextStyle.Default,
+        titleHorizontalAlignment = TopAppBarTitleAlignment.Start,
         navigationIcon = navigationIcon,
         actions = actions,
         expandedHeight =
@@ -313,6 +317,7 @@
  *   work in conjunction with a scrolled content to change the top app bar appearance as the content
  *   scrolls. See [TopAppBarScrollBehavior.nestedScrollConnection].
  */
+@OptIn(ExperimentalMaterial3ExpressiveApi::class)
 @ExperimentalMaterial3Api
 @Composable
 fun CenterAlignedTopAppBar(
@@ -329,7 +334,80 @@
         modifier = modifier,
         title = title,
         titleTextStyle = TopAppBarSmallTokens.HeadlineFont.value,
-        centeredTitle = true,
+        subtitle = {},
+        subtitleTextStyle = TextStyle.Default,
+        titleHorizontalAlignment = TopAppBarTitleAlignment.Center,
+        navigationIcon = navigationIcon,
+        actions = actions,
+        expandedHeight =
+            if (expandedHeight == Dp.Unspecified || expandedHeight == Dp.Infinity) {
+                TopAppBarDefaults.TopAppBarExpandedHeight
+            } else {
+                expandedHeight
+            },
+        windowInsets = windowInsets,
+        colors = colors,
+        scrollBehavior = scrollBehavior
+    )
+
+/**
+ * <a href="https://m3.material.io/components/top-app-bar/overview" class="external"
+ * target="_blank">Material Design small top app bar</a>.
+ *
+ * Top app bars display information and actions at the top of a screen.
+ *
+ * This small TopAppBar has slots for a title, subtitle, navigation icon, and actions.
+ *
+ * ![Small top app bar
+ * image](https://developer.android.com/images/reference/androidx/compose/material3/small-top-app-bar.png)
+ *
+ * A top app bar that uses a [scrollBehavior] to customize its nested scrolling behavior when
+ * working in conjunction with a scrolling content looks like:
+ *
+ * @sample androidx.compose.material3.samples.SimpleTopAppBarWithSubtitle
+ * @sample androidx.compose.material3.samples.SimpleCenterAlignedTopAppBarWithSubtitle
+ * @param title the title to be displayed in the top app bar
+ * @param subtitle the subtitle to be displayed in the top app bar
+ * @param modifier the [Modifier] to be applied to this top app bar
+ * @param navigationIcon the navigation icon displayed at the start of the top app bar. This should
+ *   typically be an [IconButton] or [IconToggleButton].
+ * @param actions the actions displayed at the end of the top app bar. This should typically be
+ *   [IconButton]s. The default layout here is a [Row], so icons inside will be placed horizontally.
+ * @param titleHorizontalAlignment the horizontal alignment of the title and subtitle
+ * @param expandedHeight this app bar's height. When a specified [scrollBehavior] causes the app bar
+ *   to collapse or expand, this value will represent the maximum height that the bar will be
+ *   allowed to expand. This value must be specified and finite, otherwise it will be ignored and
+ *   replaced with [TopAppBarDefaults.TopAppBarExpandedHeight].
+ * @param windowInsets a window insets that app bar will respect.
+ * @param colors [TopAppBarColors] that will be used to resolve the colors used for this top app bar
+ *   in different states. See [TopAppBarDefaults.topAppBarColors].
+ * @param scrollBehavior a [TopAppBarScrollBehavior] which holds various offset values that will be
+ *   applied by this top app bar to set up its height and colors. A scroll behavior is designed to
+ *   work in conjunction with a scrolled content to change the top app bar appearance as the content
+ *   scrolls. See [TopAppBarScrollBehavior.nestedScrollConnection].
+ */
+@OptIn(ExperimentalMaterial3Api::class)
+@ExperimentalMaterial3ExpressiveApi
+@Composable
+fun TopAppBar(
+    title: @Composable () -> Unit,
+    subtitle: @Composable () -> Unit,
+    modifier: Modifier = Modifier,
+    navigationIcon: @Composable () -> Unit = {},
+    actions: @Composable RowScope.() -> Unit = {},
+    titleHorizontalAlignment: TopAppBarTitleAlignment = TopAppBarTitleAlignment.Start,
+    expandedHeight: Dp = TopAppBarDefaults.TopAppBarExpandedHeight,
+    windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
+    colors: TopAppBarColors = TopAppBarDefaults.topAppBarColors(),
+    scrollBehavior: TopAppBarScrollBehavior? = null
+) =
+    SingleRowTopAppBar(
+        modifier = modifier,
+        title = title,
+        titleTextStyle = TopAppBarSmallTokens.HeadlineFont.value,
+        subtitle = subtitle,
+        subtitleTextStyle = TypographyKeyTokens.LabelMedium.value, // TODO tokens
+        titleHorizontalAlignment = titleHorizontalAlignment,
         navigationIcon = navigationIcon,
         actions = actions,
         expandedHeight =
@@ -447,6 +525,7 @@
  * @throws IllegalArgumentException if the provided [expandedHeight] is smaller than the
  *   [collapsedHeight]
  */
+@OptIn(ExperimentalMaterial3ExpressiveApi::class)
 @ExperimentalMaterial3Api
 @Composable
 fun MediumTopAppBar(
@@ -467,6 +546,11 @@
         smallTitleTextStyle = TopAppBarSmallTokens.HeadlineFont.value,
         titleBottomPadding = MediumTitleBottomPadding,
         smallTitle = title,
+        subtitle = {},
+        subtitleTextStyle = TextStyle.Default,
+        smallSubtitle = {},
+        smallSubtitleTextStyle = TextStyle.Default,
+        titleHorizontalAlignment = TopAppBarTitleAlignment.Start,
         navigationIcon = navigationIcon,
         actions = actions,
         collapsedHeight =
@@ -488,6 +572,109 @@
 
 /**
  * <a href="https://m3.material.io/components/top-app-bar/overview" class="external"
+ * target="_blank">Material Design medium top app bar</a>.
+ *
+ * Top app bars display information and actions at the top of a screen.
+ *
+ * ![Medium top app bar
+ * image](https://developer.android.com/images/reference/androidx/compose/material3/medium-top-app-bar.png)
+ *
+ * This MediumTopAppBar has slots for a title, subtitle, navigation icon, and actions. In its
+ * default expanded state, the title and subtitle are displayed in a second row under the navigation
+ * and actions.
+ *
+ * A medium top app bar that uses a [scrollBehavior] to customize its nested scrolling behavior when
+ * working in conjunction with scrolling content looks like:
+ *
+ * @sample androidx.compose.material3.samples.ExitUntilCollapsedCenterAlignedMediumTopAppBarWithSubtitle
+ * @param title the title to be displayed in the top app bar. This title will be used in the app
+ *   bar's expanded and collapsed states, although in its collapsed state it will be composed with a
+ *   smaller sized [TextStyle]
+ * @param subtitle the subtitle to be displayed in the top app bar. This subtitle will be used in
+ *   the app bar's expanded and collapsed states
+ * @param modifier the [Modifier] to be applied to this top app bar
+ * @param navigationIcon the navigation icon displayed at the start of the top app bar. This should
+ *   typically be an [IconButton] or [IconToggleButton].
+ * @param actions the actions displayed at the end of the top app bar. This should typically be
+ *   [IconButton]s. The default layout here is a [Row], so icons inside will be placed horizontally.
+ * @param titleHorizontalAlignment the horizontal alignment of the title and subtitle
+ * @param collapsedHeight this app bar height when collapsed by a provided [scrollBehavior]. This
+ *   value must be specified and finite, otherwise it will be ignored and replaced with
+ *   [TopAppBarDefaults.MediumAppBarCollapsedHeight].
+ * @param expandedHeight this app bar's maximum height. When a specified [scrollBehavior] causes the
+ *   app bar to collapse or expand, this value will represent the maximum height that the app-bar
+ *   will be allowed to expand. The expanded height is expected to be greater or equal to the
+ *   [collapsedHeight], and the function will throw an [IllegalArgumentException] otherwise. Also,
+ *   this value must be specified and finite, otherwise it will be ignored and replaced with
+ *   [TopAppBarDefaults.MediumAppBarExpandedHeight].
+ * @param windowInsets a window insets that app bar will respect.
+ * @param colors [TopAppBarColors] that will be used to resolve the colors used for this top app bar
+ *   in different states. See [TopAppBarDefaults.mediumTopAppBarColors].
+ * @param scrollBehavior a [TopAppBarScrollBehavior] which holds various offset values that will be
+ *   applied by this top app bar to set up its height and colors. A scroll behavior is designed to
+ *   work in conjunction with a scrolled content to change the top app bar appearance as the content
+ *   scrolls. See [TopAppBarScrollBehavior.nestedScrollConnection].
+ * @throws IllegalArgumentException if the provided [expandedHeight] is smaller than the
+ *   [collapsedHeight]
+ */
+@OptIn(ExperimentalMaterial3Api::class)
+@ExperimentalMaterial3ExpressiveApi
+@Composable
+fun MediumTopAppBar(
+    title: @Composable () -> Unit,
+    subtitle: (@Composable () -> Unit)?,
+    modifier: Modifier = Modifier,
+    navigationIcon: @Composable () -> Unit = {},
+    actions: @Composable RowScope.() -> Unit = {},
+    titleHorizontalAlignment: TopAppBarTitleAlignment = TopAppBarTitleAlignment.Start,
+    collapsedHeight: Dp = TopAppBarDefaults.MediumAppBarCollapsedHeight,
+    expandedHeight: Dp =
+        if (subtitle != null) {
+            TopAppBarDefaults.MediumAppBarWithSubtitleExpandedHeight
+        } else {
+            TopAppBarDefaults.MediumAppBarWithoutSubtitleExpandedHeight
+        },
+    windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
+    colors: TopAppBarColors = TopAppBarDefaults.mediumTopAppBarColors(),
+    scrollBehavior: TopAppBarScrollBehavior? = null
+) =
+    TwoRowsTopAppBar(
+        modifier = modifier,
+        title = title,
+        titleTextStyle = TypographyKeyTokens.HeadlineMedium.value, // TODO tokens
+        smallTitleTextStyle = TopAppBarSmallTokens.HeadlineFont.value,
+        titleBottomPadding = MediumTitleBottomPadding,
+        smallTitle = title,
+        subtitle = subtitle ?: {},
+        subtitleTextStyle = TypographyKeyTokens.LabelLarge.value, // TODO tokens
+        smallSubtitle = subtitle ?: {},
+        smallSubtitleTextStyle = TypographyKeyTokens.LabelMedium.value, // TODO tokens
+        titleHorizontalAlignment = titleHorizontalAlignment,
+        navigationIcon = navigationIcon,
+        actions = actions,
+        collapsedHeight =
+            if (collapsedHeight == Dp.Unspecified || collapsedHeight == Dp.Infinity) {
+                TopAppBarDefaults.MediumAppBarCollapsedHeight
+            } else {
+                collapsedHeight
+            },
+        expandedHeight =
+            if (expandedHeight == Dp.Unspecified || expandedHeight == Dp.Infinity) {
+                if (subtitle != null) {
+                    TopAppBarDefaults.MediumAppBarWithSubtitleExpandedHeight
+                } else {
+                    TopAppBarDefaults.MediumAppBarWithoutSubtitleExpandedHeight
+                }
+            } else {
+                expandedHeight
+            },
+        windowInsets = windowInsets,
+        colors = colors,
+        scrollBehavior = scrollBehavior
+    )
+
+/**
+ * <a href="https://m3.material.io/components/top-app-bar/overview" class="external"
  * target="_blank">Material Design large top app bar</a>.
  *
  * Top app bars display information and actions at the top of a screen.
@@ -590,6 +777,7 @@
  * @throws IllegalArgumentException if the provided [expandedHeight] is smaller to the
  *   [collapsedHeight]
  */
+@OptIn(ExperimentalMaterial3ExpressiveApi::class)
 @ExperimentalMaterial3Api
 @Composable
 fun LargeTopAppBar(
@@ -610,6 +798,11 @@
         titleBottomPadding = LargeTitleBottomPadding,
         smallTitle = title,
         modifier = modifier,
+        subtitle = {},
+        subtitleTextStyle = TextStyle.Default,
+        smallSubtitle = {},
+        smallSubtitleTextStyle = TextStyle.Default,
+        titleHorizontalAlignment = TopAppBarTitleAlignment.Start,
         navigationIcon = navigationIcon,
         actions = actions,
         collapsedHeight =
@@ -630,6 +823,109 @@
     )
 
 /**
+ * <a href="https://m3.material.io/components/top-app-bar/overview" class="external"
+ * target="_blank">Material Design large top app bar</a>.
+ *
+ * Top app bars display information and actions at the top of a screen.
+ *
+ * ![Large top app bar
+ * image](https://developer.android.com/images/reference/androidx/compose/material3/large-top-app-bar.png)
+ *
+ * This LargeTopAppBar has slots for a title, subtitle, navigation icon, and actions. In its default
+ * expanded state, the title and subtitle are displayed in a second row under the navigation and
+ * actions.
+ *
+ * A large top app bar that uses a [scrollBehavior] to customize its nested scrolling behavior when
+ * working in conjunction with scrolling content looks like:
+ *
+ * @sample androidx.compose.material3.samples.ExitUntilCollapsedCenterAlignedLargeTopAppBarWithSubtitle
+ * @param title the title to be displayed in the top app bar. This title will be used in the app
+ *   bar's expanded and collapsed states, although in its collapsed state it will be composed with a
+ *   smaller sized [TextStyle]
+ * @param subtitle the subtitle to be displayed in the top app bar. This subtitle will be used in
+ *   the app bar's expanded and collapsed states
+ * @param modifier the [Modifier] to be applied to this top app bar
+ * @param navigationIcon the navigation icon displayed at the start of the top app bar. This should
+ *   typically be an [IconButton] or [IconToggleButton].
+ * @param actions the actions displayed at the end of the top app bar. This should typically be
+ *   [IconButton]s. The default layout here is a [Row], so icons inside will be placed horizontally.
+ * @param titleHorizontalAlignment the horizontal alignment of the title and subtitle
+ * @param collapsedHeight this app bar height when collapsed by a provided [scrollBehavior]. This
+ *   value must be specified and finite, otherwise it will be ignored and replaced with
+ *   [TopAppBarDefaults.LargeAppBarCollapsedHeight].
+ * @param expandedHeight this app bar's maximum height. When a specified [scrollBehavior] causes the
+ *   app bar to collapse or expand, this value will represent the maximum height that the app-bar
+ *   will be allowed to expand. The expanded height is expected to be greater or equal to the
+ *   [collapsedHeight], and the function will throw an [IllegalArgumentException] otherwise. Also,
+ *   this value must be specified and finite, otherwise it will be ignored and replaced with
+ *   [TopAppBarDefaults.LargeAppBarExpandedHeight].
+ * @param windowInsets a window insets that app bar will respect.
+ * @param colors [TopAppBarColors] that will be used to resolve the colors used for this top app bar
+ *   in different states. See [TopAppBarDefaults.largeTopAppBarColors].
+ * @param scrollBehavior a [TopAppBarScrollBehavior] which holds various offset values that will be
+ *   applied by this top app bar to set up its height and colors. A scroll behavior is designed to
+ *   work in conjunction with a scrolled content to change the top app bar appearance as the content
+ *   scrolls. See [TopAppBarScrollBehavior.nestedScrollConnection].
+ * @throws IllegalArgumentException if the provided [expandedHeight] is smaller to the
+ *   [collapsedHeight]
+ */
+@OptIn(ExperimentalMaterial3Api::class)
+@ExperimentalMaterial3ExpressiveApi
+@Composable
+fun LargeTopAppBar(
+    title: @Composable () -> Unit,
+    subtitle: (@Composable () -> Unit)?,
+    modifier: Modifier = Modifier,
+    navigationIcon: @Composable () -> Unit = {},
+    actions: @Composable RowScope.() -> Unit = {},
+    titleHorizontalAlignment: TopAppBarTitleAlignment = TopAppBarTitleAlignment.Start,
+    collapsedHeight: Dp = TopAppBarDefaults.LargeAppBarCollapsedHeight,
+    expandedHeight: Dp =
+        if (subtitle != null) {
+            TopAppBarDefaults.LargeAppBarWithSubtitleExpandedHeight
+        } else {
+            TopAppBarDefaults.LargeAppBarWithoutSubtitleExpandedHeight
+        },
+    windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
+    colors: TopAppBarColors = TopAppBarDefaults.largeTopAppBarColors(),
+    scrollBehavior: TopAppBarScrollBehavior? = null
+) =
+    TwoRowsTopAppBar(
+        title = title,
+        titleTextStyle = TypographyKeyTokens.DisplaySmall.value, // TODO tokens
+        smallTitleTextStyle = TopAppBarSmallTokens.HeadlineFont.value,
+        titleBottomPadding = LargeTitleBottomPadding,
+        smallTitle = title,
+        modifier = modifier,
+        subtitle = subtitle ?: {},
+        subtitleTextStyle = TypographyKeyTokens.TitleMedium.value, // TODO tokens
+        smallSubtitle = subtitle ?: {},
+        smallSubtitleTextStyle = TypographyKeyTokens.LabelMedium.value, // TODO tokens
+        titleHorizontalAlignment = titleHorizontalAlignment,
+        navigationIcon = navigationIcon,
+        actions = actions,
+        collapsedHeight =
+            if (collapsedHeight == Dp.Unspecified || collapsedHeight == Dp.Infinity) {
+                TopAppBarDefaults.LargeAppBarCollapsedHeight
+            } else {
+                collapsedHeight
+            },
+        expandedHeight =
+            if (expandedHeight == Dp.Unspecified || expandedHeight == Dp.Infinity) {
+                if (subtitle != null) {
+                    TopAppBarDefaults.LargeAppBarWithSubtitleExpandedHeight
+                } else {
+                    TopAppBarDefaults.LargeAppBarWithoutSubtitleExpandedHeight
+                }
+            } else {
+                expandedHeight
+            },
+        windowInsets = windowInsets,
+        colors = colors,
+        scrollBehavior = scrollBehavior
+    )
+
+/**
  * <a href="https://m3.material.io/components/bottom-app-bar/overview" class="external"
  * target="_blank">Material Design bottom app bar</a>.
  *
@@ -1259,11 +1555,23 @@
     /** The default expanded height of a [MediumTopAppBar]. */
     val MediumAppBarExpandedHeight: Dp = TopAppBarMediumTokens.ContainerHeight
 
+    /** The default expanded height of a [MediumTopAppBar] without subtitle. */
+    val MediumAppBarWithoutSubtitleExpandedHeight: Dp = 104.dp // TODO tokens
+
+    /** The default expanded height of a [MediumTopAppBar] with subtitle. */
+    val MediumAppBarWithSubtitleExpandedHeight: Dp = 124.dp // TODO tokens
+
     /** The default height of a [LargeTopAppBar] when collapsed by a [TopAppBarScrollBehavior]. */
     val LargeAppBarCollapsedHeight: Dp = TopAppBarSmallTokens.ContainerHeight
 
     /** The default expanded height of a [LargeTopAppBar]. */
     val LargeAppBarExpandedHeight: Dp = TopAppBarLargeTokens.ContainerHeight
+
+    /** The default expanded height of a [LargeTopAppBar] without subtitle. */
+    val LargeAppBarWithoutSubtitleExpandedHeight: Dp = 120.dp // TODO tokens
+
+    /** The default expanded height of a [LargeTopAppBar] with subtitle. */
+    val LargeAppBarWithSubtitleExpandedHeight: Dp = 144.dp // TODO tokens
 }
 
 /**
@@ -1476,6 +1784,22 @@
     }
 }
 
+/** This class defines ways title and subtitle can be aligned along a TopAppBar's main axis. */
+@ExperimentalMaterial3ExpressiveApi
+@JvmInline
+value class TopAppBarTitleAlignment private constructor(internal val value: Int) {
+    companion object {
+        /** Start align the title and subtitle if present */
+        val Start = TopAppBarTitleAlignment(-1)
+
+        /** Center align the title and subtitle if present */
+        val Center = TopAppBarTitleAlignment(0)
+
+        /** End align the title and subtitle if present */
+        val End = TopAppBarTitleAlignment(1)
+    }
+}
+
 /**
  * A BottomAppBarScrollBehavior defines how a bottom app bar should behave when the content under it
  * is scrolled.
@@ -1835,17 +2159,17 @@
  * A single-row top app bar that is designed to be called by the small and center aligned top app
  * bar composables.
  *
- * This SingleRowTopAppBar has slots for a title, navigation icon, and actions. When the
- * [centeredTitle] flag is true, the title will be horizontally aligned to the center of the top app
- * bar width.
+ * This SingleRowTopAppBar has slots for a title, subtitle, navigation icon, and actions.
  */
-@OptIn(ExperimentalMaterial3Api::class)
+@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
 @Composable
 private fun SingleRowTopAppBar(
     modifier: Modifier = Modifier,
     title: @Composable () -> Unit,
     titleTextStyle: TextStyle,
-    centeredTitle: Boolean,
+    subtitle: @Composable () -> Unit,
+    subtitleTextStyle: TextStyle,
+    titleHorizontalAlignment: TopAppBarTitleAlignment,
     navigationIcon: @Composable () -> Unit,
     actions: @Composable RowScope.() -> Unit,
     expandedHeight: Dp,
@@ -1938,10 +2262,11 @@
             actionIconContentColor = colors.actionIconContentColor,
             title = title,
             titleTextStyle = titleTextStyle,
+            subtitle = subtitle,
+            subtitleTextStyle = subtitleTextStyle,
             titleAlpha = { 1f },
             titleVerticalArrangement = Arrangement.Center,
-            titleHorizontalArrangement =
-                if (centeredTitle) Arrangement.Center else Arrangement.Start,
+            titleHorizontalAlignment = titleHorizontalAlignment,
             titleBottomPadding = 0,
             hideTitleSemantics = false,
             navigationIcon = navigationIcon,
@@ -1954,7 +2279,7 @@
  * A two-rows top app bar that is designed to be called by the Large and Medium top app bar
  * composables.
  */
-@OptIn(ExperimentalMaterial3Api::class)
+@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
 @Composable
 private fun TwoRowsTopAppBar(
     modifier: Modifier = Modifier,
@@ -1963,6 +2288,11 @@
     titleBottomPadding: Dp,
     smallTitle: @Composable () -> Unit,
     smallTitleTextStyle: TextStyle,
+    subtitle: @Composable () -> Unit,
+    subtitleTextStyle: TextStyle,
+    smallSubtitle: @Composable () -> Unit,
+    smallSubtitleTextStyle: TextStyle,
+    titleHorizontalAlignment: TopAppBarTitleAlignment,
     navigationIcon: @Composable () -> Unit,
     actions: @Composable RowScope.() -> Unit,
     collapsedHeight: Dp,
@@ -2059,9 +2389,11 @@
                 actionIconContentColor = colors.actionIconContentColor,
                 title = smallTitle,
                 titleTextStyle = smallTitleTextStyle,
+                subtitle = smallSubtitle,
+                subtitleTextStyle = smallSubtitleTextStyle,
                 titleAlpha = topTitleAlpha,
                 titleVerticalArrangement = Arrangement.Center,
-                titleHorizontalArrangement = Arrangement.Start,
+                titleHorizontalAlignment = titleHorizontalAlignment,
                 titleBottomPadding = 0,
                 hideTitleSemantics = hideTopRowSemantics,
                 navigationIcon = navigationIcon,
@@ -2082,9 +2414,11 @@
                 actionIconContentColor = colors.actionIconContentColor,
                 title = title,
                 titleTextStyle = titleTextStyle,
+                subtitle = subtitle,
+                subtitleTextStyle = subtitleTextStyle,
                 titleAlpha = bottomTitleAlpha,
                 titleVerticalArrangement = Arrangement.Bottom,
-                titleHorizontalArrangement = Arrangement.Start,
+                titleHorizontalAlignment = titleHorizontalAlignment,
                 titleBottomPadding = titleBottomPaddingPx,
                 hideTitleSemantics = hideBottomRowSemantics,
                 navigationIcon = {},
@@ -2112,7 +2446,7 @@
  * @param titleTextStyle the title's text style
  * @param titleAlpha the title's alpha
  * @param titleVerticalArrangement the title's vertical arrangement
- * @param titleHorizontalArrangement the title's horizontal arrangement
+ * @param titleHorizontalAlignment the title's horizontal alignment
  * @param titleBottomPadding the title's bottom padding
  * @param hideTitleSemantics hides the title node from the semantic tree. Apply this boolean when
  *   this layout is part of a [TwoRowsTopAppBar] to hide the title's semantics from accessibility
@@ -2121,6 +2455,7 @@
  * @param navigationIcon a navigation icon [Composable]
  * @param actions actions [Composable]
  */
+@OptIn(ExperimentalMaterial3ExpressiveApi::class)
 @Composable
 private fun TopAppBarLayout(
     modifier: Modifier,
@@ -2130,9 +2465,11 @@
     actionIconContentColor: Color,
     title: @Composable () -> Unit,
     titleTextStyle: TextStyle,
+    subtitle: @Composable () -> Unit,
+    subtitleTextStyle: TextStyle,
     titleAlpha: () -> Float,
     titleVerticalArrangement: Arrangement.Vertical,
-    titleHorizontalArrangement: Arrangement.Horizontal,
+    titleHorizontalAlignment: TopAppBarTitleAlignment,
     titleBottomPadding: Int,
     hideTitleSemantics: Boolean,
     navigationIcon: @Composable () -> Unit,
@@ -2146,17 +2483,31 @@
                     content = navigationIcon
                 )
             }
-            Box(
-                Modifier.layoutId("title")
-                    .padding(horizontal = TopAppBarHorizontalPadding)
-                    .then(if (hideTitleSemantics) Modifier.clearAndSetSemantics {} else Modifier)
-                    .graphicsLayer { alpha = titleAlpha() }
+            Column(
+                modifier =
+                    Modifier.layoutId("title")
+                        .padding(horizontal = TopAppBarHorizontalPadding)
+                        .then(
+                            if (hideTitleSemantics) Modifier.clearAndSetSemantics {} else Modifier
+                        )
+                        .graphicsLayer { alpha = titleAlpha() },
+                horizontalAlignment =
+                    when (titleHorizontalAlignment) {
+                        TopAppBarTitleAlignment.Start -> Alignment.Start
+                        TopAppBarTitleAlignment.Center -> Alignment.CenterHorizontally
+                        else -> Alignment.End
+                    }
             ) {
                 ProvideContentColorTextStyle(
                     contentColor = titleContentColor,
                     textStyle = titleTextStyle,
                     content = title
                 )
+                ProvideContentColorTextStyle(
+                    contentColor = titleContentColor,
+                    textStyle = subtitleTextStyle,
+                    content = subtitle
+                )
             }
             Box(Modifier.layoutId("actionIcons").padding(end = TopAppBarHorizontalPadding)) {
                 CompositionLocalProvider(
@@ -2218,31 +2569,29 @@
             // Title
             titlePlaceable.placeRelative(
                 x =
-                    when (titleHorizontalArrangement) {
-                        Arrangement.Center -> {
+                    when (titleHorizontalAlignment) {
+                        TopAppBarTitleAlignment.Center -> {
                             var baseX = (constraints.maxWidth - titlePlaceable.width) / 2
                             if (baseX < navigationIconPlaceable.width) {
                                 // May happen if the navigation is wider than the actions and the
                                 // title is long. In this case, prioritize showing more of the title
-                                // by
-                                // offsetting it to the right.
+                                // by offsetting it to the right.
                                 baseX += (navigationIconPlaceable.width - baseX)
                             } else if (
                                 baseX + titlePlaceable.width >
                                     constraints.maxWidth - actionIconsPlaceable.width
                             ) {
                                 // May happen if the actions are wider than the navigation and the
-                                // title
-                                // is long. In this case, offset to the left.
+                                // title is long. In this case, offset to the left.
                                 baseX +=
                                     ((constraints.maxWidth - actionIconsPlaceable.width) -
                                         (baseX + titlePlaceable.width))
                             }
                             baseX
                         }
-                        Arrangement.End ->
+                        TopAppBarTitleAlignment.End ->
                             constraints.maxWidth - titlePlaceable.width - actionIconsPlaceable.width
-                        // Arrangement.Start.
+                        // TopAppBarTitleAlignment.Start
                         // An TopAppBarTitleInset will make sure the title is offset in case the
                         // navigation icon is missing.
                         else -> max(TopAppBarTitleInset.roundToPx(), navigationIconPlaceable.width)
@@ -2251,8 +2600,7 @@
                     when (titleVerticalArrangement) {
                         Arrangement.Center -> (layoutHeight - titlePlaceable.height) / 2
                         // Apply bottom padding from the title's baseline only when the Arrangement
-                        // is
-                        // "Bottom".
+                        // is "Bottom".
                         Arrangement.Bottom ->
                             if (titleBottomPadding == 0) {
                                 layoutHeight - titlePlaceable.height
@@ -2262,8 +2610,7 @@
                                 val paddingFromBottom =
                                     titleBottomPadding - (titlePlaceable.height - titleBaseline)
                                 // Adjust the bottom padding to a smaller number if there is no room
-                                // to
-                                // fit the title.
+                                // to fit the title.
                                 val heightWithPadding = paddingFromBottom + titlePlaceable.height
                                 val adjustedBottomPadding =
                                     if (heightWithPadding > constraints.maxHeight) {
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Button.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Button.kt
index ad1c991..9cdf1d5 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Button.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Button.kt
@@ -77,7 +77,7 @@
  * Choose the best button for an action based on the amount of emphasis it needs. The more important
  * an action is, the higher emphasis its button should be.
  * - See [OutlinedButton] for a medium-emphasis button with a border.
- * - See [ElevatedButton] for an [OutlinedButton] with a shadow.
+ * - See [ElevatedButton] for an [FilledTonalButton] with a shadow.
  * - See [TextButton] for a low-emphasis button with no border.
  * - See [FilledTonalButton] for a middle ground between [OutlinedButton] and [Button].
  *
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/ColorScheme.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/ColorScheme.kt
index 56955e4..e03736e 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/ColorScheme.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/ColorScheme.kt
@@ -931,6 +931,7 @@
         onPrimaryContainer = PaletteTokens.Primary30,
         onSecondaryContainer = PaletteTokens.Secondary30,
         onTertiaryContainer = PaletteTokens.Secondary30,
+        onErrorContainer = PaletteTokens.Error30
     )
 
 /**
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/IconButton.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/IconButton.kt
index 07dfb9d..3dae87d 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/IconButton.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/IconButton.kt
@@ -26,6 +26,7 @@
 import androidx.compose.material3.internal.childSemantics
 import androidx.compose.material3.tokens.FilledIconButtonTokens
 import androidx.compose.material3.tokens.FilledTonalIconButtonTokens
+import androidx.compose.material3.tokens.IconButtonSmallTokens
 import androidx.compose.material3.tokens.IconButtonTokens
 import androidx.compose.material3.tokens.OutlinedIconButtonTokens
 import androidx.compose.runtime.Composable
@@ -44,6 +45,8 @@
 import androidx.compose.ui.semantics.Role
 import androidx.compose.ui.semantics.role
 import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.DpSize
 
 /**
  * <a href="https://m3.material.io/components/icon-button/overview" class="external"
@@ -76,6 +79,14 @@
  *   interactions will still happen internally.
  * @param content the content of this icon button, typically an [Icon]
  */
+@Deprecated(
+    message = "Use overload with `shape`",
+    replaceWith =
+        ReplaceWith(
+            "IconButton(onClick, modifier, enabled, colors, interactionSource, shape, content)"
+        ),
+    level = DeprecationLevel.HIDDEN
+)
 @Composable
 fun IconButton(
     onClick: () -> Unit,
@@ -85,20 +96,83 @@
     interactionSource: MutableInteractionSource? = null,
     content: @Composable () -> Unit
 ) {
+    IconButton(
+        onClick,
+        modifier,
+        enabled,
+        colors,
+        interactionSource,
+        IconButtonTokens.StateLayerShape.value,
+        content
+    )
+}
+
+/**
+ * <a href="https://m3.material.io/components/icon-button/overview" class="external"
+ * target="_blank">Material Design standard icon button</a>.
+ *
+ * Icon buttons help people take supplementary actions with a single tap. They’re used when a
+ * compact button is required, such as in a toolbar or image list.
+ *
+ * ![Standard icon button
+ * image](https://developer.android.com/images/reference/androidx/compose/material3/standard-icon-button.png)
+ *
+ * [content] should typically be an [Icon] (see [androidx.compose.material.icons.Icons]). If using a
+ * custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has
+ * an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.
+ *
+ * Simple Usage
+ *
+ * @sample androidx.compose.material3.samples.IconButtonSample
+ *
+ * IconButton with a color tint
+ *
+ * @sample androidx.compose.material3.samples.TintedIconButtonSample
+ *
+ * IconButton with smaller square narrow shape
+ *
+ * @sample androidx.compose.material3.samples.SmallSquareNarrowIconButtonSample
+ *
+ * IconButton with smaller square narrow shape
+ *
+ * @sample androidx.compose.material3.samples.SmallRoundWideIconButtonSample
+ * @param onClick called when this icon button is clicked
+ * @param modifier the [Modifier] to be applied to this icon button
+ * @param enabled controls the enabled state of this icon button. When `false`, this component will
+ *   not respond to user input, and it will appear visually disabled and disabled to accessibility
+ *   services.
+ * @param colors [IconButtonColors] that will be used to resolve the colors used for this icon
+ *   button in different states. See [IconButtonDefaults.iconButtonColors].
+ * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
+ *   emitting [Interaction]s for this icon button. You can use this to change the icon button's
+ *   appearance or preview the icon button in different states. Note that if `null` is provided,
+ *   interactions will still happen internally.
+ * @param shape the [Shape] of this icon button.
+ * @param content the content of this icon button, typically an [Icon]
+ */
+@Composable
+fun IconButton(
+    onClick: () -> Unit,
+    modifier: Modifier = Modifier,
+    enabled: Boolean = true,
+    colors: IconButtonColors = IconButtonDefaults.iconButtonColors(),
+    interactionSource: MutableInteractionSource? = null,
+    shape: Shape = IconButtonDefaults.standardShape,
+    content: @Composable () -> Unit
+) {
     Box(
         modifier =
             modifier
                 .minimumInteractiveComponentSize()
                 .size(IconButtonTokens.StateLayerSize)
-                .clip(IconButtonTokens.StateLayerShape.value)
-                .background(color = colors.containerColor(enabled))
+                .clip(shape)
+                .background(color = colors.containerColor(enabled), shape = shape)
                 .clickable(
                     onClick = onClick,
                     enabled = enabled,
                     role = Role.Button,
                     interactionSource = interactionSource,
-                    indication =
-                        ripple(bounded = false, radius = IconButtonTokens.StateLayerSize / 2)
+                    indication = ripple()
                 )
                 .childSemantics(),
         contentAlignment = Alignment.Center
@@ -137,6 +211,15 @@
  *   interactions will still happen internally.
  * @param content the content of this icon button, typically an [Icon]
  */
+@Deprecated(
+    message = "Use overload with `shape`",
+    replaceWith =
+        ReplaceWith(
+            "IconToggleButton(checked, onCheckedChange, modifier, enabled, colors," +
+                " interactionSource, shape, content)"
+        ),
+    level = DeprecationLevel.HIDDEN
+)
 @Composable
 fun IconToggleButton(
     checked: Boolean,
@@ -147,12 +230,65 @@
     interactionSource: MutableInteractionSource? = null,
     content: @Composable () -> Unit
 ) {
+    IconToggleButton(
+        checked,
+        onCheckedChange,
+        modifier,
+        enabled,
+        colors,
+        interactionSource,
+        IconButtonTokens.StateLayerShape.value,
+        content
+    )
+}
+
+/**
+ * <a href="https://m3.material.io/components/icon-button/overview" class="external"
+ * target="_blank">Material Design standard icon toggle button</a>.
+ *
+ * Icon buttons help people take supplementary actions with a single tap. They’re used when a
+ * compact button is required, such as in a toolbar or image list.
+ *
+ * ![Standard icon toggle button
+ * image](https://developer.android.com/images/reference/androidx/compose/material3/standard-icon-toggle-button.png)
+ *
+ * [content] should typically be an [Icon] (see [androidx.compose.material.icons.Icons]). If using a
+ * custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has
+ * an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.
+ *
+ * @sample androidx.compose.material3.samples.IconToggleButtonSample
+ * @param checked whether this icon button is toggled on or off
+ * @param onCheckedChange called when this icon button is clicked
+ * @param modifier the [Modifier] to be applied to this icon button
+ * @param enabled controls the enabled state of this icon button. When `false`, this component will
+ *   not respond to user input, and it will appear visually disabled and disabled to accessibility
+ *   services.
+ * @param colors [IconToggleButtonColors] that will be used to resolve the colors used for this icon
+ *   button in different states. See [IconButtonDefaults.iconToggleButtonColors].
+ * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
+ *   emitting [Interaction]s for this icon button. You can use this to change the icon button's
+ *   appearance or preview the icon button in different states. Note that if `null` is provided,
+ *   interactions will still happen internally.
+ * @param shape the [Shape] of this icon button.
+ * @param content the content of this icon button, typically an [Icon]
+ */
+@Composable
+fun IconToggleButton(
+    checked: Boolean,
+    onCheckedChange: (Boolean) -> Unit,
+    modifier: Modifier = Modifier,
+    enabled: Boolean = true,
+    colors: IconToggleButtonColors = IconButtonDefaults.iconToggleButtonColors(),
+    interactionSource: MutableInteractionSource? = null,
+    shape: Shape = IconButtonDefaults.standardShape,
+    content: @Composable () -> Unit
+) {
     Box(
         modifier =
             modifier
                 .minimumInteractiveComponentSize()
                 .size(IconButtonTokens.StateLayerSize)
-                .clip(IconButtonTokens.StateLayerShape.value)
+                .clip(shape)
                 .background(color = colors.containerColor(enabled, checked).value)
                 .toggleable(
                     value = checked,
@@ -160,8 +296,7 @@
                     enabled = enabled,
                     role = Role.Checkbox,
                     interactionSource = interactionSource,
-                    indication =
-                        ripple(bounded = false, radius = IconButtonTokens.StateLayerSize / 2)
+                    indication = ripple()
                 ),
         contentAlignment = Alignment.Center
     ) {
@@ -557,7 +692,10 @@
         interactionSource = interactionSource
     ) {
         Box(
-            modifier = Modifier.size(OutlinedIconButtonTokens.ContainerSize),
+            modifier =
+                Modifier.size(
+                    OutlinedIconButtonTokens.ContainerSize,
+                ),
             contentAlignment = Alignment.Center
         ) {
             content()
@@ -566,6 +704,10 @@
 
 /** Contains the default values used by all icon button types. */
 object IconButtonDefaults {
+    /** Default ripple shape for a standard icon button. */
+    val standardShape: Shape
+        @Composable get() = IconButtonTokens.StateLayerShape.value
+
     /** Default shape for a filled icon button. */
     val filledShape: Shape
         @Composable get() = FilledIconButtonTokens.ContainerShape.value
@@ -574,6 +716,58 @@
     val outlinedShape: Shape
         @Composable get() = OutlinedIconButtonTokens.ContainerShape.value
 
+    @ExperimentalMaterial3ExpressiveApi
+    /** Default round shape for any icon button. */
+    val roundShape: Shape
+        @Composable get() = IconButtonSmallTokens.ContainerShapeRound.value
+
+    @ExperimentalMaterial3ExpressiveApi
+    /** Default square shape for any icon button. */
+    val squareShape: Shape
+        @Composable get() = IconButtonSmallTokens.ContainerShapeSquare.value
+
+    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+    @get:ExperimentalMaterial3ExpressiveApi
+    @ExperimentalMaterial3ExpressiveApi
+    /** Default small narrow container for any icon button. */
+    val SmallIconSize: Dp = IconButtonSmallTokens.IconSize
+
+    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+    @get:ExperimentalMaterial3ExpressiveApi
+    @ExperimentalMaterial3ExpressiveApi
+    /** Default small narrow container for any icon button. */
+    val SmallNarrowContainerSize: DpSize =
+        DpSize(
+            IconButtonSmallTokens.IconSize +
+                IconButtonSmallTokens.NarrowLeadingSpace +
+                IconButtonSmallTokens.NarrowTrailingSpace,
+            IconButtonSmallTokens.ContainerHeight
+        )
+
+    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+    @get:ExperimentalMaterial3ExpressiveApi
+    @ExperimentalMaterial3ExpressiveApi
+    /** Default small narrow container for any icon button. */
+    val SmallContainerSize: DpSize =
+        DpSize(
+            IconButtonSmallTokens.IconSize +
+                IconButtonSmallTokens.UniformLeadingSpace +
+                IconButtonSmallTokens.UniformLeadingSpace,
+            IconButtonSmallTokens.ContainerHeight
+        )
+
+    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+    @get:ExperimentalMaterial3ExpressiveApi
+    @ExperimentalMaterial3ExpressiveApi
+    /** Default small narrow container for any icon button. */
+    val SmallWideContainerSize: DpSize =
+        DpSize(
+            IconButtonSmallTokens.IconSize +
+                IconButtonSmallTokens.WideLeadingSpace +
+                IconButtonSmallTokens.WideTrailingSpace,
+            IconButtonSmallTokens.ContainerHeight
+        )
+
     /** Creates a [IconButtonColors] that represents the default colors used in a [IconButton]. */
     @Composable
     fun iconButtonColors(): IconButtonColors {
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/LoadingIndicator.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/LoadingIndicator.kt
new file mode 100644
index 0000000..9138238
--- /dev/null
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/LoadingIndicator.kt
@@ -0,0 +1,517 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3
+
+import androidx.compose.animation.core.Animatable
+import androidx.compose.animation.core.AnimationEndReason
+import androidx.compose.animation.core.LinearEasing
+import androidx.compose.animation.core.RepeatMode
+import androidx.compose.animation.core.infiniteRepeatable
+import androidx.compose.animation.core.spring
+import androidx.compose.animation.core.tween
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.aspectRatio
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.progressSemantics
+import androidx.compose.material3.internal.toPath
+import androidx.compose.material3.internal.transformed
+import androidx.compose.material3.tokens.LoadingIndicatorTokens
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.draw.drawWithContent
+import androidx.compose.ui.geometry.Size
+import androidx.compose.ui.geometry.center
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Matrix
+import androidx.compose.ui.graphics.Path
+import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.graphics.drawscope.Fill
+import androidx.compose.ui.graphics.drawscope.rotate
+import androidx.compose.ui.semantics.ProgressBarRangeInfo
+import androidx.compose.ui.semantics.progressBarRangeInfo
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.util.fastForEach
+import androidx.graphics.shapes.Morph
+import androidx.graphics.shapes.RoundedPolygon
+import kotlin.math.max
+import kotlin.math.min
+import kotlinx.coroutines.async
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+
+// TODO Update the docs images to point to the loading indicator
+/**
+ * A Material Design loading indicator.
+ *
+ * This version of the loading indicator morphs between its [indicatorPolygons] shapes by the value
+ * of its [progress].
+ *
+ * It can be created like this:
+ *
+ * @sample androidx.compose.material3.samples.DeterminateLoadingIndicatorSample
+ *
+ * It can also be used as an indicator for a [PullToRefreshBox] like this:
+ *
+ * @sample androidx.compose.material3.samples.LoadingIndicatorPullToRefreshSample
+ * @param progress the progress of this loading indicator, where 0.0 represents no progress and 1.0
+ *   represents full progress. Values outside of this range are coerced into the range. The
+ *   indicator will morph its shapes between the provided [indicatorPolygons] according to the value
+ *   of the progress.
+ * @param modifier the [Modifier] to be applied to this loading indicator
+ * @param containerColor the loading indicator's container color
+ * @param indicatorColor the loading indicator's color
+ * @param containerShape the loading indicator's container shape. Note that the indicator will be
+ *   clipped to this shape only when the [containerColor] is defined and non-transparent.
+ * @param indicatorPolygons a list of [RoundedPolygon]s that defines the sequence of shapes this
+ *   loading indicator will morph between as it progresses from 0.0 to 1.0. The loading indicator
+ *   expects at least two items in that list.
+ * @throws IllegalArgumentException if the [indicatorPolygons] list holds less than two items
+ */
+@ExperimentalMaterial3ExpressiveApi
+@Composable
+fun LoadingIndicator(
+    progress: () -> Float,
+    modifier: Modifier = Modifier,
+    containerColor: Color = LoadingIndicatorDefaults.ContainerColor,
+    indicatorColor: Color = LoadingIndicatorDefaults.IndicatorColor,
+    containerShape: Shape = LoadingIndicatorDefaults.ContainerShape,
+    indicatorPolygons: List<RoundedPolygon> = LoadingIndicatorDefaults.DeterminateIndicatorPolygons
+) {
+    require(indicatorPolygons.size > 1) {
+        "indicatorPolygons should have, at least, two RoundedPolygons"
+    }
+    val coercedProgress = { progress().coerceIn(0f, 1f) }
+    val path = remember { Path() }
+    val scaleMatrix = remember { Matrix() }
+    val morphSequence =
+        remember(indicatorPolygons) {
+            morphSequence(polygons = indicatorPolygons, circularSequence = false)
+        }
+    val morphScaleFactor =
+        remember(morphSequence) {
+            // Calculate the shapes scale factor that will be applied to the morphed path as it's
+            // scaled into the available size.
+            // This overall scale factor ensures that the shapes are rendered without clipping and
+            // at the correct ratio within the component by taking into account their occupied size
+            // as they rotate, and taking into account the spec's ActiveIndicatorScale.
+            calculateScaleFactor(indicatorPolygons) * LoadingIndicatorDefaults.ActiveIndicatorScale
+        }
+    Box(
+        modifier =
+            modifier
+                .semantics(mergeDescendants = true) {
+                    progressBarRangeInfo = ProgressBarRangeInfo(coercedProgress(), 0f..1f)
+                }
+                .size(
+                    width = LoadingIndicatorDefaults.ContainerWidth,
+                    height = LoadingIndicatorDefaults.ContainerHeight
+                )
+                .fillMaxSize()
+                .clip(containerShape)
+                .background(containerColor),
+        contentAlignment = Alignment.Center
+    ) {
+        // Using a Spacer to render the indicator's shapes. Maintains a square aspect ratio (1:1)
+        // to prevent shape distortion during rendering.
+        Spacer(
+            modifier =
+                Modifier.aspectRatio(ratio = 1f, matchHeightConstraintsFirst = true)
+                    .drawWithContent {
+                        val progressValue = coercedProgress()
+                        // Adjust the active morph index according to the progress.
+                        val activeMorphIndex =
+                            (morphSequence.size * progressValue)
+                                .toInt()
+                                .coerceAtMost(morphSequence.size - 1)
+                        // Prepare the progress value that will be used for the active Morph.
+                        val adjustedProgressValue =
+                            if (progressValue == 1f && activeMorphIndex == morphSequence.size - 1) {
+                                // Prevents a zero when the progress is one and we are at the last
+                                // shape morph.
+                                1f
+                            } else {
+                                (progressValue * morphSequence.size) % 1f
+                            }
+
+                        // Rotate counterclockwise.
+                        val rotation = -progressValue * 180
+                        rotate(rotation) {
+                            drawPath(
+                                path =
+                                    processPath(
+                                        path =
+                                            morphSequence[activeMorphIndex].toPath(
+                                                // Use the adjusted progress.
+                                                progress = adjustedProgressValue,
+                                                path = path,
+                                                startAngle = 0
+                                            ),
+                                        size = size,
+                                        scaleFactor = morphScaleFactor,
+                                        scaleMatrix = scaleMatrix
+                                    ),
+                                color = indicatorColor,
+                                style = Fill
+                            )
+                        }
+                    }
+        )
+    }
+}
+
+// TODO Update the docs images to point to the loading indicator.
+/**
+ * A Material Design loading indicator.
+ *
+ * This version of the loading indicator animates and morphs between various shapes as long as the
+ * loading indicator is visible.
+ *
+ * It can be created like this:
+ *
+ * @sample androidx.compose.material3.samples.LoadingIndicatorSample
+ * @param modifier the [Modifier] to be applied to this loading indicator
+ * @param containerColor the loading indicator's container color
+ * @param indicatorColor the loading indicator's color
+ * @param containerShape the loading indicator's container shape. Note that the indicator will be
+ *   clipped to this shape only when the [containerColor] is defined and non-transparent.
+ * @param indicatorPolygons a list of [RoundedPolygon]s that defines the sequence of shapes this
+ *   loading indicator will morph between. The loading indicator expects at least two items in that
+ *   list.
+ * @throws IllegalArgumentException if the [indicatorPolygons] list holds less than two items
+ */
+@ExperimentalMaterial3ExpressiveApi
+@Composable
+fun LoadingIndicator(
+    modifier: Modifier = Modifier,
+    containerColor: Color = Color.Unspecified,
+    indicatorColor: Color = LoadingIndicatorDefaults.IndicatorColor,
+    containerShape: Shape = LoadingIndicatorDefaults.ContainerShape,
+    indicatorPolygons: List<RoundedPolygon> =
+        LoadingIndicatorDefaults.IndeterminateIndicatorPolygons,
+) {
+    require(indicatorPolygons.size > 1) {
+        "indicatorPolygons should have, at least, two RoundedPolygons"
+    }
+    val morphSequence =
+        remember(indicatorPolygons) {
+            morphSequence(polygons = indicatorPolygons, circularSequence = true)
+        }
+    val shapesScaleFactor =
+        remember(indicatorPolygons) {
+            // Calculate the shapes scale factor that will be applied to the morphed path as it's
+            // scaled into the available size.
+            // This overall scale factor ensures that the shapes are rendered without clipping and
+            // at the correct ratio within the component by taking into account their occupied size
+            // as they rotate, and taking into account the spec's ActiveIndicatorScale.
+            calculateScaleFactor(indicatorPolygons) * LoadingIndicatorDefaults.ActiveIndicatorScale
+        }
+    val morphProgress = remember { Animatable(0f) }
+    var morphRotationTargetAngle = remember { QuarterRotation }
+    val globalRotation = remember { Animatable(0f) }
+    var currentMorphIndex by remember { mutableIntStateOf(0) }
+    LaunchedEffect(Unit) {
+        launch {
+            // Note that we up the visibilityThreshold here to 0.1, which is x10 than the default
+            // threshold, and ends the low-damping spring in a shorter time.
+            val morphAnimationSpec =
+                spring(dampingRatio = 0.6f, stiffness = 200f, visibilityThreshold = 0.1f)
+            while (true) {
+                // Async launch of a spring that will finish in less than 650ms
+                // (MorphIntervalMillis). We then delay the entire while loop by 650ms till the next
+                // morph starts.
+                val deferred = async {
+                    val animationResult =
+                        morphProgress.animateTo(
+                            targetValue = 1f,
+                            animationSpec = morphAnimationSpec
+                        )
+                    if (animationResult.endReason == AnimationEndReason.Finished) {
+                        currentMorphIndex = (currentMorphIndex + 1) % morphSequence.size
+                        morphProgress.snapTo(0f)
+                        morphRotationTargetAngle =
+                            (morphRotationTargetAngle + QuarterRotation) % FullRotation
+                    }
+                }
+                delay(MorphIntervalMillis)
+                deferred.await()
+            }
+        }
+        globalRotation.animateTo(
+            targetValue = FullRotation,
+            animationSpec =
+                infiniteRepeatable(
+                    tween(GlobalRotationDurationMillis, easing = LinearEasing),
+                    repeatMode = RepeatMode.Restart
+                )
+        )
+    }
+
+    val path = remember { Path() }
+    val scaleMatrix = remember { Matrix() }
+    Box(
+        modifier =
+            modifier
+                .progressSemantics()
+                .size(
+                    width = LoadingIndicatorDefaults.ContainerWidth,
+                    height = LoadingIndicatorDefaults.ContainerHeight
+                )
+                .fillMaxSize()
+                .clip(containerShape)
+                .background(containerColor),
+        contentAlignment = Alignment.Center
+    ) {
+        Spacer(
+            modifier =
+                Modifier.aspectRatio(1f, matchHeightConstraintsFirst = true).drawWithContent {
+                    val progress = morphProgress.value
+                    // Rotate clockwise.
+                    rotate(progress * 90 + morphRotationTargetAngle + globalRotation.value) {
+                        drawPath(
+                            path =
+                                processPath(
+                                    path =
+                                        morphSequence[currentMorphIndex].toPath(
+                                            // Use the coerced progress value to eliminate any
+                                            // bounciness from the morph. We scale the drawing
+                                            // to simulate some bounciness instead.
+                                            progress = progress,
+                                            path = path,
+                                            startAngle = 0
+                                        ),
+                                    size = size,
+                                    scaleFactor = shapesScaleFactor,
+                                    scaleMatrix = scaleMatrix
+                                ),
+                            color = indicatorColor,
+                            style = Fill
+                        )
+                    }
+                }
+        )
+    }
+}
+
+/** Contains default values by the [LoadingIndicator]. */
+@ExperimentalMaterial3ExpressiveApi
+object LoadingIndicatorDefaults {
+
+    /** A [LoadingIndicator] default container width. */
+    val ContainerWidth: Dp = LoadingIndicatorTokens.ContainerWidth
+
+    /** A [LoadingIndicator] default container height. */
+    val ContainerHeight: Dp = LoadingIndicatorTokens.ContainerHeight
+
+    /** A [LoadingIndicator] default active indicator size. */
+    val IndicatorSize = LoadingIndicatorTokens.ActiveSize
+
+    /** A [LoadingIndicator] default container [Shape]. */
+    val ContainerShape: Shape
+        @Composable get() = LoadingIndicatorTokens.ContainerShape.value
+
+    /** A [LoadingIndicator] default active indicator [Color]. */
+    val IndicatorColor: Color
+        @Composable get() = LoadingIndicatorTokens.ActiveIndicatorColor.value
+
+    /** A [LoadingIndicator] default container [Color]. */
+    val ContainerColor: Color
+        @Composable get() = LoadingIndicatorTokens.ContainerColor.value
+
+    /**
+     * The sequence of [RoundedPolygon]s that the indeterminate [LoadingIndicator] will morph
+     * between when animating.
+     *
+     * By default, an indeterminate loading indicator will morph between seven shapes, but you may
+     * provide your own shapes sequence when calling the API.
+     */
+    val IndeterminateIndicatorPolygons =
+        listOf(
+            MaterialShapes.SoftBurst,
+            MaterialShapes.Cookie9Sided,
+            MaterialShapes.Pentagon,
+            MaterialShapes.Pill,
+            MaterialShapes.Sunny,
+            MaterialShapes.Cookie4Sided,
+            MaterialShapes.Oval
+        )
+
+    /**
+     * The sequence of [RoundedPolygon]s that the determinate [LoadingIndicator] will morph between
+     * when animating. The loading indicator will morph between the shapes as its progress moves
+     * between zero to one.
+     *
+     * By default, a determinate loading indicator will will morph between two shapes, but you may
+     * provide your own shapes sequence when calling the API.
+     */
+    val DeterminateIndicatorPolygons =
+        listOf(
+            // Rotating the circle gets us a smoother morphing to the soft-burst shapes, which is
+            // also being rotated at the same angle.
+            MaterialShapes.Circle.transformed(Matrix().apply { rotateZ(360f / 20) }),
+            MaterialShapes.SoftBurst
+        )
+
+    /**
+     * A percentage value of the LoadingIndicator's active indicator scale when rendered within the
+     * bounds of the container size.
+     */
+    internal val ActiveIndicatorScale =
+        IndicatorSize.value / min(ContainerWidth.value, ContainerHeight.value)
+}
+
+/**
+ * Returns a list of [Morph]s that describe the sequence of shapes that the [LoadingIndicator]
+ * should animate in a loop.
+ *
+ * This function will create a morph between each consecutive [RoundedPolygon] shaped in the
+ * provided array, and will create a final morph from the last shape to the first shape.
+ *
+ * Note that each [RoundedPolygon] within the returns [Morph]s is normalized here.
+ *
+ * @param polygons a [List] of [RoundedPolygon]s to create [Morph]s for
+ * @param circularSequence indicate if an additional [Morph] should be created from the last item to
+ *   the first item of the list in order to create a circular sequence of morphs
+ * @see RoundedPolygon.normalized
+ */
+private fun morphSequence(polygons: List<RoundedPolygon>, circularSequence: Boolean): List<Morph> {
+    return buildList {
+        for (i in polygons.indices) {
+            if (i + 1 < polygons.size) {
+                add(Morph(polygons[i].normalized(), polygons[i + 1].normalized()))
+            } else if (circularSequence) {
+                // Create a morph from the last shape to the first shape
+                add(Morph(polygons[i].normalized(), polygons[0].normalized()))
+            }
+        }
+    }
+}
+
+/**
+ * Calculates a scale factor that will be used when scaling the provided [RoundedPolygon]s into a
+ * specified sized container.
+ *
+ * Since the polygons may rotate, a simple [RoundedPolygon.calculateBounds] is not enough to
+ * determine the size the polygon will occupy as it rotates. Using the simple bounds calculation may
+ * result in a clipped shape.
+ *
+ * This function calculates and returns a scale factor by utilizing the
+ * [RoundedPolygon.calculateMaxBounds] and comparing its result to the
+ * [RoundedPolygon.calculateBounds]. The scale factor can later be used when calling [processPath].
+ */
+private fun calculateScaleFactor(indicatorPolygons: List<RoundedPolygon>): Float {
+    var scaleFactor = 1f
+    // Axis-aligned max bounding box for this object, where the rectangles left, top, right, and
+    // bottom values will be stored in entries 0, 1, 2, and 3, in that order.
+    val bounds = FloatArray(size = 4)
+    val maxBounds = FloatArray(size = 4)
+    indicatorPolygons.fastForEach { polygon ->
+        polygon.calculateBounds(bounds)
+        polygon.calculateMaxBounds(maxBounds)
+        val scaleX = bounds.width() / maxBounds.width()
+        val scaleY = bounds.height() / maxBounds.height()
+        // We use max(scaleX, scaleY) to handle cases like a pill-shape that can throw off the
+        // entire calculation.
+        scaleFactor = min(scaleFactor, max(scaleX, scaleY))
+    }
+    return scaleFactor
+}
+
+/**
+ * Calculates a scale factor that will be used when scaling the provided [Morph] into a specified
+ * sized container.
+ *
+ * Since the morph may rotate, a simple [Morph.calculateBounds] is not enough to determine the size
+ * the morph will occupy as it rotates. Using the simple bounds calculation may result in a clipped
+ * shape.
+ *
+ * This function calculates and returns a scale factor by utilizing the [Morph.calculateMaxBounds]
+ * and comparing its result to the [Morph.calculateBounds]. The scale factor can later be used when
+ * calling [processPath].
+ */
+private fun calculateScaleFactor(morph: Morph): Float {
+    val bounds = morph.calculateBounds()
+    val maxBounds = morph.calculateMaxBounds()
+    val scaleX = bounds.width() / maxBounds.width()
+    val scaleY = bounds.height() / maxBounds.height()
+    // We use max(scaleX, scaleY) to handle cases like a pill-shape that can throw off the
+    // entire calculation.
+    return max(scaleX, scaleY)
+}
+
+/**
+ * Returns the width value from the [FloatArray] that was calculated by a
+ * [RoundedPolygon.calculateBounds] or [[RoundedPolygon.calculateMaxBounds]].
+ */
+private fun FloatArray.width(): Float {
+    // Expecting a FloatArray of [left, top, right, bottom]
+    return this[2] - this[0]
+}
+
+/**
+ * Returns the height value from the [FloatArray] that was calculated by a
+ * [RoundedPolygon.calculateBounds] or [RoundedPolygon.calculateMaxBounds].
+ */
+private fun FloatArray.height(): Float {
+    // Expecting a FloatArray of [left, top, right, bottom]
+    return this[3] - this[1]
+}
+
+/**
+ * Process a given path to scale it and center it inside the given size.
+ *
+ * @param path a [Path] that was generated by a _normalized_ [Morph] or [RoundedPolygon]
+ * @param size a [Size] that the provided [path] is going to be scaled and centered into
+ * @param scaleFactor a scale factor that will be taken into account uniformly when the [path] is
+ *   scaled (i.e. the scaleX would be the [size] width x the scale factor, and the scaleY would be
+ *   the [size] height x the scale factor)
+ * @param scaleMatrix a [Matrix] that would be used to apply the scaling. Note that any provided
+ *   matrix will be reset in this function.
+ */
+private fun processPath(
+    path: Path,
+    size: Size,
+    scaleFactor: Float,
+    scaleMatrix: Matrix = Matrix(),
+): Path {
+    scaleMatrix.reset()
+
+    scaleMatrix.apply { scale(x = size.width * scaleFactor, y = size.height * scaleFactor) }
+
+    // Scale to the desired size.
+    path.transform(scaleMatrix)
+
+    // Translate the path to align its center with the available size center.
+    path.translate(size.center - path.getBounds().center)
+    return path
+}
+
+private const val GlobalRotationDurationMillis = 4666
+private const val MorphIntervalMillis = 650L
+
+private const val FullRotation = 360f
+private const val QuarterRotation = FullRotation / 4f
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/MaterialShapes.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/MaterialShapes.kt
new file mode 100644
index 0000000..ec24bc8
--- /dev/null
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/MaterialShapes.kt
@@ -0,0 +1,876 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3
+
+import androidx.compose.material3.internal.toPath
+import androidx.compose.material3.internal.transformed
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.geometry.Size
+import androidx.compose.ui.geometry.center
+import androidx.compose.ui.graphics.Matrix
+import androidx.compose.ui.graphics.Outline
+import androidx.compose.ui.graphics.Path
+import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.LayoutDirection
+import androidx.compose.ui.util.fastFlatMap
+import androidx.compose.ui.util.fastForEach
+import androidx.compose.ui.util.fastMap
+import androidx.compose.ui.util.fastMaxBy
+import androidx.graphics.shapes.CornerRounding
+import androidx.graphics.shapes.RoundedPolygon
+import androidx.graphics.shapes.TransformResult
+import androidx.graphics.shapes.circle
+import androidx.graphics.shapes.pill
+import androidx.graphics.shapes.rectangle
+import androidx.graphics.shapes.star
+import kotlin.math.PI
+import kotlin.math.atan2
+import kotlin.math.cos
+import kotlin.math.sin
+
+/**
+ * Returns a normalized [Path] that is remembered across compositions for this [RoundedPolygon].
+ *
+ * @param startAngle an angle to rotate the Material shape's path to start drawing from. The
+ *   rotation pivot is set to be the shape's centerX and centerY coordinates.
+ * @see RoundedPolygon.normalized
+ */
+@ExperimentalMaterial3ExpressiveApi
+@Composable
+fun RoundedPolygon.toPath(startAngle: Int = 0): Path {
+    val path = remember { Path() }
+    return remember(this, startAngle) {
+        this.toPath(path = path, startAngle = startAngle, repeatPath = false, closePath = true)
+    }
+}
+
+/**
+ * Returns a [Shape] that is remembered across compositions for this [RoundedPolygon].
+ *
+ * @param startAngle an angle to rotate the Material shape's path to start drawing from. The
+ *   rotation pivot is always set to be the shape's centerX and centerY coordinates.
+ */
+@ExperimentalMaterial3ExpressiveApi
+@Composable
+fun RoundedPolygon.toShape(startAngle: Int = 0): Shape {
+    return remember(this, startAngle) {
+        object : Shape {
+            private val path: Path = toPath(startAngle = startAngle)
+
+            override fun createOutline(
+                size: Size,
+                layoutDirection: LayoutDirection,
+                density: Density
+            ): Outline {
+                val scaleMatrix = Matrix().apply { scale(x = size.width, y = size.height) }
+                // Scale and translate the path to align its center with the available size
+                // center.
+                path.transform(scaleMatrix)
+                path.translate(size.center - path.getBounds().center)
+                return Outline.Generic(path)
+            }
+        }
+    }
+}
+
+/**
+ * Holds predefined Material Design shapes as [RoundedPolygon]s that can be used at various
+ * components as they are, or as part of a [Morph].
+ *
+ * ![Shapes
+ * image](https://developer.android.com/images/reference/androidx/compose/material3/shapes.png)
+ *
+ * Note that each [RoundedPolygon] in this class is normalized.
+ *
+ * @see RoundedPolygon.normalized
+ */
+@ExperimentalMaterial3ExpressiveApi
+sealed class MaterialShapes {
+
+    companion object {
+
+        // Cache various roundings for use below
+        private val cornerRound10 = CornerRounding(radius = .1f)
+        private val cornerRound15 = CornerRounding(radius = .15f)
+        private val cornerRound20 = CornerRounding(radius = .2f)
+        private val cornerRound30 = CornerRounding(radius = .3f)
+        private val cornerRound40 = CornerRounding(radius = .4f)
+        private val cornerRound50 = CornerRounding(radius = .5f)
+        private val cornerRound100 = CornerRounding(radius = 1f)
+
+        private val rotateNeg45 = Matrix().apply { rotateZ(-45f) }
+        private val rotate45 = Matrix().apply { rotateZ(45f) }
+        private val rotateNeg90 = Matrix().apply { rotateZ(-90f) }
+        private val rotate90 = Matrix().apply { rotateZ(90f) }
+        private val rotateNeg135 = Matrix().apply { rotateZ(-135f) }
+        private val unrounded = CornerRounding.Unrounded
+
+        private var _circle: RoundedPolygon? = null
+        private var _square: RoundedPolygon? = null
+        private var _slanted: RoundedPolygon? = null
+        private var _arch: RoundedPolygon? = null
+        private var _fan: RoundedPolygon? = null
+        private var _arrow: RoundedPolygon? = null
+        private var _semiCircle: RoundedPolygon? = null
+        private var _oval: RoundedPolygon? = null
+        private var _pill: RoundedPolygon? = null
+        private var _triangle: RoundedPolygon? = null
+        private var _diamond: RoundedPolygon? = null
+        private var _clamShell: RoundedPolygon? = null
+        private var _pentagon: RoundedPolygon? = null
+        private var _gem: RoundedPolygon? = null
+        private var _verySunny: RoundedPolygon? = null
+        private var _sunny: RoundedPolygon? = null
+        private var _cookie4Sided: RoundedPolygon? = null
+        private var _cookie6Sided: RoundedPolygon? = null
+        private var _cookie7Sided: RoundedPolygon? = null
+        private var _cookie9Sided: RoundedPolygon? = null
+        private var _cookie12Sided: RoundedPolygon? = null
+        private var _ghostish: RoundedPolygon? = null
+        private var _clover4Leaf: RoundedPolygon? = null
+        private var _clover8Leaf: RoundedPolygon? = null
+        private var _burst: RoundedPolygon? = null
+        private var _softBurst: RoundedPolygon? = null
+        private var _boom: RoundedPolygon? = null
+        private var _softBoom: RoundedPolygon? = null
+        private var _flower: RoundedPolygon? = null
+        private var _puffy: RoundedPolygon? = null
+        private var _puffyDiamond: RoundedPolygon? = null
+        private var _pixelCircle: RoundedPolygon? = null
+        private var _pixelTriangle: RoundedPolygon? = null
+        private var _bun: RoundedPolygon? = null
+        private var _heart: RoundedPolygon? = null
+
+        /** A circle shape. */
+        val Circle
+            get() = _circle ?: circle().normalized().also { _circle = it }
+
+        /** A rounded square shape. */
+        val Square
+            get() = _square ?: square().normalized().also { _square = it }
+
+        /** A slanted square shape. */
+        val Slanted
+            get() = _slanted ?: slanted().normalized().also { _slanted = it }
+
+        /** An arch shape. */
+        val Arch
+            get() = _arch ?: arch().normalized().also { _arch = it }
+
+        /** A fan shape. */
+        val Fan
+            get() = _fan ?: fan().normalized().also { _fan = it }
+
+        /** An arrow shape. */
+        val Arrow
+            get() = _arrow ?: arrow().normalized().also { _arrow = it }
+
+        /** A semi-circle shape. */
+        val SemiCircle
+            get() = _semiCircle ?: semiCircle().normalized().also { _semiCircle = it }
+
+        /** An oval shape. */
+        val Oval
+            get() = _oval ?: oval().normalized().also { _oval = it }
+
+        /** A pill shape. */
+        val Pill
+            get() = _pill ?: pill().normalized().also { _pill = it }
+
+        /** A rounded triangle shape. */
+        val Triangle
+            get() = _triangle ?: triangle().normalized().also { _triangle = it }
+
+        /** A diamond shape. */
+        val Diamond
+            get() = _diamond ?: diamond().normalized().also { _diamond = it }
+
+        /** A clam-shell shape. */
+        val ClamShell
+            get() = _clamShell ?: clamShell().normalized().also { _clamShell = it }
+
+        /** A pentagon shape. */
+        val Pentagon
+            get() = _pentagon ?: pentagon().normalized().also { _pentagon = it }
+
+        /** A gem shape. */
+        val Gem
+            get() = _gem ?: gem().normalized().also { _gem = it }
+
+        /** A sunny shape. */
+        val Sunny
+            get() = _sunny ?: sunny().normalized().also { _sunny = it }
+
+        /** A very-sunny shape. */
+        val VerySunny
+            get() = _verySunny ?: verySunny().normalized().also { _verySunny = it }
+
+        /** A 4-sided cookie shape. */
+        val Cookie4Sided
+            get() = _cookie4Sided ?: cookie4().normalized().also { _cookie4Sided = it }
+
+        /** A 6-sided cookie shape. */
+        val Cookie6Sided
+            get() = _cookie6Sided ?: cookie6().normalized().also { _cookie6Sided = it }
+
+        /** A 7-sided cookie shape. */
+        val Cookie7Sided
+            get() = _cookie7Sided ?: cookie7().normalized().also { _cookie7Sided = it }
+
+        /** A 9-sided cookie shape. */
+        val Cookie9Sided
+            get() = _cookie9Sided ?: cookie9().normalized().also { _cookie9Sided = it }
+
+        /** A 12-sided cookie shape. */
+        val Cookie12Sided
+            get() = _cookie12Sided ?: cookie12().normalized().also { _cookie12Sided = it }
+
+        /** A ghost-ish shape. */
+        val Ghostish
+            get() = _ghostish ?: ghostish().normalized().also { _ghostish = it }
+
+        /** A 4-leaf clover shape. */
+        val Clover4Leaf
+            get() = _clover4Leaf ?: clover4().normalized().also { _clover4Leaf = it }
+
+        /** An 8-leaf clover shape. */
+        val Clover8Leaf
+            get() = _clover8Leaf ?: clover8().normalized().also { _clover8Leaf = it }
+
+        /** A burst shape. */
+        val Burst
+            get() = _burst ?: burst().normalized().also { _burst = it }
+
+        /** A soft-burst shape. */
+        val SoftBurst
+            get() = _softBurst ?: softBurst().normalized().also { _softBurst = it }
+
+        /** A boom shape. */
+        val Boom
+            get() = _boom ?: boom().normalized().also { _boom = it }
+
+        /** A soft-boom shape. */
+        val SoftBoom
+            get() = _softBoom ?: softBoom().normalized().also { _softBoom = it }
+
+        /** A flower shape. */
+        val Flower
+            get() = _flower ?: flower().normalized().also { _flower = it }
+
+        /** A puffy shape. */
+        val Puffy
+            get() = _puffy ?: puffy().normalized().also { _puffy = it }
+
+        /** A puffy-diamond shape. */
+        val PuffyDiamond
+            get() = _puffyDiamond ?: puffyDiamond().normalized().also { _puffyDiamond = it }
+
+        /** A pixel-circle shape. */
+        val PixelCircle
+            get() = _pixelCircle ?: pixelCircle().normalized().also { _pixelCircle = it }
+
+        /** A pixel-triangle shape. */
+        val PixelTriangle
+            get() = _pixelTriangle ?: pixelTriangle().normalized().also { _pixelTriangle = it }
+
+        /** A bun shape. */
+        val Bun
+            get() = _bun ?: bun().normalized().also { _bun = it }
+
+        /** A heart shape. */
+        val Heart
+            get() = _heart ?: heart().normalized().also { _heart = it }
+
+        internal fun circle(numVertices: Int = 10): RoundedPolygon {
+            return RoundedPolygon.circle(numVertices = numVertices)
+        }
+
+        internal fun square(): RoundedPolygon {
+            return RoundedPolygon.rectangle(width = 1f, height = 1f, rounding = cornerRound30)
+        }
+
+        internal fun slanted(): RoundedPolygon {
+            return RoundedPolygon(
+                    numVertices = 4,
+                    rounding = CornerRounding(radius = 0.3f, smoothing = 0.5f)
+                )
+                .transformed(rotateNeg45)
+                .transformed { x, y ->
+                    TransformResult(x - 0.1f * y, y) // Compose's matrix doesn't support skew!?
+                }
+        }
+
+        internal fun arch(): RoundedPolygon {
+            return RoundedPolygon(
+                    numVertices = 4,
+                    perVertexRounding =
+                        listOf(cornerRound100, cornerRound100, cornerRound20, cornerRound20)
+                )
+                .transformed(rotateNeg135)
+        }
+
+        internal fun fan(): RoundedPolygon {
+            return RoundedPolygon(
+                    numVertices = 4,
+                    perVertexRounding =
+                        listOf(cornerRound100, cornerRound20, cornerRound20, cornerRound20)
+                )
+                .transformed(rotateNeg45)
+        }
+
+        internal fun arrow(): RoundedPolygon {
+            return triangleChip(
+                innerRadius = .3375f,
+                rounding = CornerRounding(radius = .25f, smoothing = .48f)
+            )
+        }
+
+        internal fun triangleChip(innerRadius: Float, rounding: CornerRounding): RoundedPolygon {
+            val topR = 0.888f
+            val points =
+                floatArrayOf(
+                    radialToCartesian(radius = topR, 270f.toRadians()).x,
+                    radialToCartesian(radius = topR, 270f.toRadians()).y,
+                    radialToCartesian(radius = 1f, 30f.toRadians()).x,
+                    radialToCartesian(radius = 1f, 30f.toRadians()).y,
+                    radialToCartesian(radius = innerRadius, 90f.toRadians()).x,
+                    radialToCartesian(radius = innerRadius, 90f.toRadians()).y,
+                    radialToCartesian(radius = 1f, 150f.toRadians()).x,
+                    radialToCartesian(radius = 1f, 150f.toRadians()).y
+                )
+            return RoundedPolygon(points, rounding)
+        }
+
+        internal fun semiCircle(): RoundedPolygon {
+            return RoundedPolygon.rectangle(
+                width = 1.6f,
+                height = 1f,
+                perVertexRounding =
+                    listOf(cornerRound20, cornerRound20, cornerRound100, cornerRound100)
+            )
+        }
+
+        internal fun oval(scaleX: Float = 1f, scaleY: Float = .7f): RoundedPolygon {
+            val m = Matrix().apply { scale(x = scaleX, y = scaleY) }
+            return RoundedPolygon.circle().transformed(m).transformed(rotateNeg45)
+        }
+
+        internal fun pill(width: Float = 1.25f, height: Float = 1f): RoundedPolygon {
+            return RoundedPolygon.pill(width = width, height = height).transformed(rotateNeg45)
+        }
+
+        internal fun triangle(): RoundedPolygon {
+            return RoundedPolygon(numVertices = 3, rounding = cornerRound20)
+                .transformed(rotateNeg90)
+        }
+
+        internal fun diamond(scaleX: Float = 1f, scaleY: Float = 1.2f): RoundedPolygon {
+            return RoundedPolygon(numVertices = 4, rounding = cornerRound30)
+                .transformed(Matrix().apply { scale(x = scaleX, y = scaleY) })
+        }
+
+        internal fun clamShell(): RoundedPolygon {
+            val cornerInset = .6f
+            val edgeInset = .4f
+            val height = .7f
+            val hexPoints =
+                floatArrayOf(
+                    1f,
+                    0f,
+                    cornerInset,
+                    height,
+                    edgeInset,
+                    height,
+                    -edgeInset,
+                    height,
+                    -cornerInset,
+                    height,
+                    -1f,
+                    0f,
+                    -cornerInset,
+                    -height,
+                    -edgeInset,
+                    -height,
+                    edgeInset,
+                    -height,
+                    cornerInset,
+                    -height,
+                )
+            val pvRounding =
+                listOf(
+                    cornerRound30,
+                    cornerRound30,
+                    unrounded,
+                    unrounded,
+                    cornerRound30,
+                    cornerRound30,
+                    cornerRound30,
+                    unrounded,
+                    unrounded,
+                    cornerRound30,
+                )
+            return RoundedPolygon(hexPoints, perVertexRounding = pvRounding)
+        }
+
+        internal fun pentagon(): RoundedPolygon {
+            return RoundedPolygon(numVertices = 5, rounding = cornerRound30)
+                .transformed(Matrix().apply { rotateZ(-360f / 20f) })
+        }
+
+        internal fun gem(): RoundedPolygon {
+            // irregular hexagon (right narrower than left, then rotated)
+            // First, generate a standard hexagon
+            val numVertices = 6
+            val radius = 1f
+            val points = FloatArray(numVertices * 2)
+            var index = 0
+            for (i in 0 until numVertices) {
+                val vertex = radialToCartesian(radius, (PI.toFloat() / numVertices * 2 * i))
+                points[index++] = vertex.x
+                points[index++] = vertex.y
+            }
+            // Now adjust-in the points at the top (next-to-last and second vertices, post rotation)
+            points[2] -= .1f
+            points[3] -= .1f
+            points[10] -= .1f
+            points[11] += .1f
+            return RoundedPolygon(points, cornerRound40).transformed(rotateNeg90)
+        }
+
+        internal fun sunny(): RoundedPolygon {
+            return RoundedPolygon.star(
+                numVerticesPerRadius = 8,
+                innerRadius = .8f,
+                rounding = cornerRound15
+            )
+        }
+
+        internal fun verySunny(): RoundedPolygon {
+            return RoundedPolygon.star(
+                numVerticesPerRadius = 8,
+                innerRadius = .65f,
+                rounding = cornerRound15
+            )
+        }
+
+        internal fun cookie4(): RoundedPolygon {
+            return RoundedPolygon.star(
+                    numVerticesPerRadius = 4,
+                    innerRadius = .5f,
+                    rounding = cornerRound30
+                )
+                .transformed(rotateNeg45)
+        }
+
+        internal fun cookie6(): RoundedPolygon {
+            // 6-point cookie
+            return RoundedPolygon.star(
+                    numVerticesPerRadius = 6,
+                    innerRadius = .75f,
+                    rounding = cornerRound50
+                )
+                .transformed(rotateNeg90)
+        }
+
+        internal fun cookie7(): RoundedPolygon {
+            // 7-point cookie
+            return RoundedPolygon.star(
+                    numVerticesPerRadius = 7,
+                    innerRadius = .75f,
+                    rounding = cornerRound50
+                )
+                .transformed(rotateNeg90)
+        }
+
+        internal fun cookie9(): RoundedPolygon {
+            return RoundedPolygon.star(
+                    numVerticesPerRadius = 9,
+                    innerRadius = .8f,
+                    rounding = cornerRound50
+                )
+                .transformed(rotateNeg90)
+        }
+
+        internal fun cookie12(): RoundedPolygon {
+            return RoundedPolygon.star(
+                    numVerticesPerRadius = 12,
+                    innerRadius = .8f,
+                    rounding = cornerRound50
+                )
+                .transformed(rotateNeg90)
+        }
+
+        internal fun ghostish(): RoundedPolygon {
+            val inset = .46f
+            val h = 1.2f
+            val points = floatArrayOf(-1f, -h, 1f, -h, 1f, h, 0f, inset, -1f, h)
+            val pvRounding =
+                listOf(cornerRound100, cornerRound100, cornerRound50, cornerRound100, cornerRound50)
+            return RoundedPolygon(points, perVertexRounding = pvRounding)
+        }
+
+        internal fun clover4(): RoundedPolygon {
+            // (no inner rounding)
+            return RoundedPolygon.star(
+                    numVerticesPerRadius = 4,
+                    innerRadius = .2f,
+                    rounding = cornerRound40,
+                    innerRounding = unrounded
+                )
+                .transformed(rotate45)
+        }
+
+        internal fun clover8(): RoundedPolygon {
+            // (no inner rounding)
+            return RoundedPolygon.star(
+                    numVerticesPerRadius = 8,
+                    innerRadius = .65f,
+                    rounding = cornerRound30,
+                    innerRounding = unrounded
+                )
+                .transformed(Matrix().apply { rotateZ(360f / 16) })
+        }
+
+        internal fun burst(): RoundedPolygon {
+            return RoundedPolygon.star(numVerticesPerRadius = 12, innerRadius = .7f)
+        }
+
+        internal fun softBurst(): RoundedPolygon {
+            return RoundedPolygon.star(
+                    radius = 1f,
+                    numVerticesPerRadius = 10,
+                    innerRadius = .65f,
+                    rounding = cornerRound10,
+                    innerRounding = cornerRound10
+                )
+                .transformed(Matrix().apply { rotateZ(360f / 20) })
+        }
+
+        internal fun boom(): RoundedPolygon {
+            return RoundedPolygon.star(numVerticesPerRadius = 15, innerRadius = .42f)
+                .transformed(Matrix().apply { rotateZ(360f / 60) })
+        }
+
+        internal fun softBoom(): RoundedPolygon {
+            val points =
+                arrayOf(
+                    Offset(0.456f, 0.224f),
+                    Offset(0.460f, 0.170f),
+                    Offset(0.500f, 0.100f),
+                    Offset(0.540f, 0.170f),
+                    Offset(0.544f, 0.224f),
+                    Offset(0.538f, 0.308f)
+                )
+            val actualPoints = doRepeat(points, 16, center = Offset(0.5f, 0.5f))
+            val roundings =
+                listOf(
+                        CornerRounding(radius = 0.020f),
+                        CornerRounding(radius = 0.143f),
+                        CornerRounding(radius = 0.025f),
+                        CornerRounding(radius = 0.143f),
+                        CornerRounding(radius = 0.190f),
+                        CornerRounding(radius = 0f)
+                    )
+                    .let { l -> (0 until 16).flatMap { l } }
+
+            return RoundedPolygon(
+                actualPoints,
+                perVertexRounding = roundings,
+                centerX = 0.5f,
+                centerY = 0.5f
+            )
+        }
+
+        internal fun flower(): RoundedPolygon {
+            val smoothRound = CornerRounding(radius = .12f, smoothing = .48f)
+            return RoundedPolygon.star(
+                numVerticesPerRadius = 8,
+                radius = 1f,
+                innerRadius = .588f,
+                rounding = smoothRound,
+                innerRounding = unrounded
+            )
+        }
+
+        internal fun puffy(): RoundedPolygon {
+            val pnr =
+                listOf(
+                    PointNRound(Offset(0.500f, 0.260f), CornerRounding.Unrounded),
+                    PointNRound(Offset(0.526f, 0.188f), CornerRounding(0.095f)),
+                    PointNRound(Offset(0.676f, 0.226f), CornerRounding(0.095f)),
+                    PointNRound(Offset(0.660f, 0.300f), CornerRounding.Unrounded),
+                    PointNRound(Offset(0.734f, 0.230f), CornerRounding(0.095f)),
+                    PointNRound(Offset(0.838f, 0.350f), CornerRounding(0.095f)),
+                    PointNRound(Offset(0.782f, 0.418f), CornerRounding.Unrounded),
+                    PointNRound(Offset(0.874f, 0.414f), CornerRounding(0.095f)),
+                )
+            val actualPoints =
+                doRepeat(pnr, reps = 4, center = Offset(0.5f, 0.5f), mirroring = true)
+
+            return RoundedPolygon(
+                actualPoints.fastFlatMap { listOf(it.o.x, it.o.y) }.toFloatArray(),
+                perVertexRounding = actualPoints.fastMap { it.r },
+                centerX = 0.5f,
+                centerY = 0.5f
+            )
+        }
+
+        internal fun puffyDiamond(): RoundedPolygon {
+            val points =
+                arrayOf(
+                    Offset(0.390f, 0.260f),
+                    Offset(0.390f, 0.130f),
+                    Offset(0.610f, 0.130f),
+                    Offset(0.610f, 0.260f),
+                    Offset(0.740f, 0.260f)
+                )
+            val actualPoints = doRepeat(points, reps = 4, center = Offset(0.5f, 0.5f))
+            val roundings =
+                listOf(
+                        CornerRounding(radius = 0.000f),
+                        CornerRounding(radius = 0.104f),
+                        CornerRounding(radius = 0.104f),
+                        CornerRounding(radius = 0.000f),
+                        CornerRounding(radius = 0.104f)
+                    )
+                    .let { l -> (0 until 4).flatMap { l } }
+
+            return RoundedPolygon(
+                actualPoints,
+                perVertexRounding = roundings,
+                centerX = 0.5f,
+                centerY = 0.5f
+            )
+        }
+
+        @Suppress("ListIterator", "PrimitiveInCollection")
+        internal fun pixelCircle(): RoundedPolygon {
+            val main = 0.4f
+            val holes = listOf(Offset(0.28f, 0.14f), Offset(0.16f, 0.16f), Offset(0.16f, 0.3f))
+            var p = Offset(main, -1f)
+            val corner = buildList {
+                add(p)
+                holes.fastForEach { delta ->
+                    p += Offset(0f, delta.y)
+                    add(p)
+                    p += Offset(delta.x, 0f)
+                    add(p)
+                }
+            }
+            val half = corner + corner.fastMap { Offset(it.x, -it.y) }.reversed()
+            val points = half + half.fastMap { Offset(-it.x, it.y) }.reversed()
+            return RoundedPolygon(
+                points.fastFlatMap { listOf(it.x, it.y) }.toFloatArray(),
+                unrounded
+            )
+        }
+
+        @Suppress("ListIterator", "PrimitiveInCollection")
+        internal fun pixelTriangle(): RoundedPolygon {
+            var point = Offset(0f, 0f)
+            val points = mutableListOf<Offset>()
+            points.add(point)
+            val sizes = listOf(56f, 28f, 44f, 26f, 44f, 32f, 38f, 26f, 38f, 32f)
+            sizes.chunked(2).forEach { (dx, dy) ->
+                point += Offset(dx, 0f)
+                points.add(point)
+                point += Offset(0f, dy)
+                points.add(point)
+            }
+            point += Offset(32f, 0f)
+            points.add(point)
+            point += Offset(0f, 38f)
+            points.add(point)
+            point += Offset(-32f, 0f)
+            points.add(point)
+            sizes.reversed().chunked(2).forEach { (dy, dx) ->
+                point += Offset(0f, dy)
+                points.add(point)
+                point += Offset(-dx, 0f)
+                points.add(point)
+            }
+            val centerX = points.fastMaxBy { it.x }!!.x / 2
+            val centerY = points.fastMaxBy { it.y }!!.y / 2
+
+            return RoundedPolygon(
+                points.fastFlatMap { listOf(it.x, it.y) }.toFloatArray(),
+                centerX = centerX,
+                centerY = centerY,
+            )
+        }
+
+        internal fun bun(): RoundedPolygon {
+            // Basically, two pills stacked on each other
+            val inset = .4f
+            val sandwichPoints =
+                floatArrayOf(
+                    1f,
+                    1f,
+                    inset,
+                    1f,
+                    -inset,
+                    1f,
+                    -1f,
+                    1f,
+                    -1f,
+                    0f,
+                    -inset,
+                    0f,
+                    -1f,
+                    0f,
+                    -1f,
+                    -1f,
+                    -inset,
+                    -1f,
+                    inset,
+                    -1f,
+                    1f,
+                    -1f,
+                    1f,
+                    0f,
+                    inset,
+                    0f,
+                    1f,
+                    0f
+                )
+            val pvRounding =
+                listOf(
+                    cornerRound100,
+                    unrounded,
+                    unrounded,
+                    cornerRound100,
+                    cornerRound100,
+                    unrounded,
+                    cornerRound100,
+                    cornerRound100,
+                    unrounded,
+                    unrounded,
+                    cornerRound100,
+                    cornerRound100,
+                    unrounded,
+                    cornerRound100
+                )
+            return RoundedPolygon(sandwichPoints, perVertexRounding = pvRounding)
+        }
+
+        internal fun heart(): RoundedPolygon {
+            val points =
+                floatArrayOf(
+                    .2f,
+                    0f,
+                    -.4f,
+                    .5f,
+                    -1f,
+                    1f,
+                    -1.5f,
+                    .5f,
+                    -1f,
+                    0f,
+                    -1.5f,
+                    -.5f,
+                    -1f,
+                    -1f,
+                    -.4f,
+                    -.5f
+                )
+            val pvRounding =
+                listOf(
+                    unrounded,
+                    unrounded,
+                    cornerRound100,
+                    cornerRound100,
+                    unrounded,
+                    cornerRound100,
+                    cornerRound100,
+                    unrounded
+                )
+            return RoundedPolygon(points, perVertexRounding = pvRounding).transformed(rotate90)
+        }
+
+        private data class PointNRound(val o: Offset, val r: CornerRounding)
+
+        private fun doRepeat(points: Array<Offset>, reps: Int, center: Offset) =
+            points.size.let { np ->
+                (0 until np * reps)
+                    .flatMap {
+                        val point = points[it % np].rotateDegrees((it / np) * 360f / reps, center)
+                        listOf(point.x, point.y)
+                    }
+                    .toFloatArray()
+            }
+
+        @Suppress("PrimitiveInCollection")
+        private fun doRepeat(
+            points: List<PointNRound>,
+            reps: Int,
+            center: Offset,
+            mirroring: Boolean
+        ) =
+            if (mirroring) {
+                buildList {
+                    val angles = points.fastMap { (it.o - center).angleDegrees() }
+                    val distances = points.fastMap { (it.o - center).getDistance() }
+                    val sectionAngle = 360f / reps
+                    repeat(reps) {
+                        points.indices.forEach { index ->
+                            val i = if (it % 2 == 0) index else points.lastIndex - index
+                            if (i > 0 || it % 2 == 0) {
+                                val a =
+                                    (sectionAngle * it +
+                                            if (it % 2 == 0) angles[i]
+                                            else sectionAngle - angles[i] + 2 * angles[0])
+                                        .toRadians()
+                                val finalPoint = Offset(cos(a), sin(a)) * distances[i] + center
+                                add(PointNRound(finalPoint, points[i].r))
+                            }
+                        }
+                    }
+                }
+            } else {
+                points.size.let { np ->
+                    (0 until np * reps).map {
+                        val point = points[it % np].o.rotateDegrees((it / np) * 360f / reps, center)
+                        PointNRound(point, points[it % np].r)
+                    }
+                }
+            }
+
+        private fun Offset.rotateDegrees(angle: Float, center: Offset = Offset.Zero) =
+            (angle.toRadians()).let { a ->
+                val off = this - center
+                Offset(off.x * cos(a) - off.y * sin(a), off.x * sin(a) + off.y * cos(a)) + center
+            }
+
+        private fun Float.toRadians(): Float {
+            return this / 360f * 2 * PI.toFloat()
+        }
+
+        private fun Offset.angleDegrees() = atan2(y, x) * 180f / PI.toFloat()
+
+        private fun directionVector(angleRadians: Float) =
+            Offset(cos(angleRadians), sin(angleRadians))
+
+        private fun radialToCartesian(
+            radius: Float,
+            angleRadians: Float,
+            center: Offset = Offset.Zero
+        ) = directionVector(angleRadians) * radius + center
+    }
+}
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Ripple.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Ripple.kt
index 5c2d85b..9cd6c5c 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Ripple.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Ripple.kt
@@ -305,6 +305,7 @@
 
     private fun removeRipple() {
         rippleNode?.let { undelegate(it) }
+        rippleNode = null
     }
 }
 
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SplitButton.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SplitButton.kt
index 5e63320..feb749e 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SplitButton.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SplitButton.kt
@@ -47,10 +47,12 @@
 import androidx.compose.ui.geometry.lerp
 import androidx.compose.ui.graphics.Shape
 import androidx.compose.ui.layout.Layout
+import androidx.compose.ui.platform.LocalLayoutDirection
 import androidx.compose.ui.semantics.Role
 import androidx.compose.ui.semantics.role
 import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.util.fastForEach
 import androidx.compose.ui.util.fastMap
@@ -505,11 +507,8 @@
      */
     private val MinHeight = ButtonDefaults.MinHeight
 
-    /**
-     * Default minimum width of the [TrailingButton]. Ratio 1 is recommended for the trailing
-     * button, so it follows the min height of the split button
-     */
-    private val TrailingButtonMinWidth = MinHeight
+    /** Default minimum width of the [TrailingButton]. */
+    private val TrailingButtonMinWidth = LeadingButtonMinWidth
 
     /**
      * Create a default `leading` button that has the same visual as a Filled[Button]. To create a
@@ -703,9 +702,11 @@
         interactionSource: MutableInteractionSource? = null,
         content: @Composable RowScope.() -> Unit
     ) {
-        val leftCornerMorphProgress: Float by animateFloatAsState(if (expanded) 1f else 0f)
+        val cornerMorphProgress: Float by animateFloatAsState(if (expanded) 1f else 0f)
         @Suppress("NAME_SHADOWING")
         val interactionSource = interactionSource ?: remember { MutableInteractionSource() }
+        val isRtl = LocalLayoutDirection.current == LayoutDirection.Rtl
+
         TrailingButton(
             onClick = onClick,
             modifier = modifier,
@@ -714,7 +715,7 @@
             elevation = elevation,
             border = border,
             interactionSource = interactionSource,
-            shape = rememberTrailingButtonShape { leftCornerMorphProgress },
+            shape = rememberTrailingButtonShape(isRtl) { cornerMorphProgress },
             content = content,
         )
     }
@@ -722,31 +723,37 @@
 
 @OptIn(ExperimentalMaterial3ExpressiveApi::class)
 @Composable
-private fun rememberTrailingButtonShape(progress: () -> Float) = remember {
-    GenericShape { size, _ ->
-        val rect = Rect(Offset.Zero, size)
-        val originalLeftCornerRadius =
-            CornerRadius((size.height * InnerCornerRadiusPercentage / 100))
-        val originalRoundRect =
-            RoundRect(
-                rect,
-                originalLeftCornerRadius,
-                CornerRadius(size.height / 2),
-                CornerRadius(size.height / 2),
-                originalLeftCornerRadius
-            )
-        val endRoundRect =
-            RoundRect(
-                rect,
-                CornerRadius(size.height / 2),
-                CornerRadius(size.height / 2),
-                CornerRadius(size.height / 2),
-                CornerRadius(size.height / 2)
-            )
-        val roundRect = lerp(originalRoundRect, endRoundRect, progress.invoke())
-        addRoundRect(roundRect)
+private fun rememberTrailingButtonShape(isRtl: Boolean, progress: () -> Float) =
+    remember(isRtl, progress) {
+        GenericShape { size, _ ->
+            val rect = Rect(Offset.Zero, size)
+            val originalStartCornerRadius =
+                CornerRadius((size.height * InnerCornerRadiusPercentage / 100))
+            val originalRoundRect =
+                if (isRtl) {
+                    RoundRect(
+                        rect,
+                        CornerRadius(size.height / 2),
+                        originalStartCornerRadius,
+                        originalStartCornerRadius,
+                        CornerRadius(size.height / 2)
+                    )
+                } else {
+                    RoundRect(
+                        rect,
+                        originalStartCornerRadius,
+                        CornerRadius(size.height / 2),
+                        CornerRadius(size.height / 2),
+                        originalStartCornerRadius
+                    )
+                }
+
+            val endRoundRect = RoundRect(rect, CornerRadius(size.height / 2))
+
+            val roundRect = lerp(originalRoundRect, endRoundRect, progress.invoke())
+            addRoundRect(roundRect)
+        }
     }
-}
 
 @OptIn(ExperimentalMaterial3ExpressiveApi::class)
 @Composable
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TextField.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TextField.kt
index fae16bb..1f41226 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TextField.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TextField.kt
@@ -47,7 +47,7 @@
 import androidx.compose.material3.internal.SuffixId
 import androidx.compose.material3.internal.SupportingId
 import androidx.compose.material3.internal.TextFieldId
-import androidx.compose.material3.internal.TextFieldPadding
+import androidx.compose.material3.internal.TextFieldLabelExtraPadding
 import androidx.compose.material3.internal.TrailingId
 import androidx.compose.material3.internal.ZeroConstraints
 import androidx.compose.material3.internal.defaultErrorSemantics
@@ -82,6 +82,7 @@
 import androidx.compose.ui.text.input.TextFieldValue
 import androidx.compose.ui.text.input.VisualTransformation
 import androidx.compose.ui.unit.Constraints
+import androidx.compose.ui.unit.Density
 import androidx.compose.ui.unit.IntOffset
 import androidx.compose.ui.unit.coerceAtLeast
 import androidx.compose.ui.unit.dp
@@ -691,7 +692,6 @@
                 supportingHeight = heightOrZero(supportingPlaceable),
                 animationProgress = animationProgress,
                 constraints = constraints,
-                density = density,
                 paddingValues = paddingValues,
             )
         val height = totalHeight - supportingHeight
@@ -710,6 +710,9 @@
 
         return layout(width, totalHeight) {
             if (labelPlaceable != null) {
+                // The padding defined by the user only applies to the text field when the label
+                // is focused. More padding needs to be added when the text field is unfocused.
+                val labelStartPosition = topPaddingValue + TextFieldLabelExtraPadding.roundToPx()
                 placeWithLabel(
                     width = width,
                     totalHeight = totalHeight,
@@ -723,10 +726,10 @@
                     containerPlaceable = containerPlaceable,
                     supportingPlaceable = supportingPlaceable,
                     singleLine = singleLine,
+                    labelStartPosition = labelStartPosition,
                     labelEndPosition = topPaddingValue,
                     textPosition = topPaddingValue + labelPlaceable.height,
                     animationProgress = animationProgress,
-                    density = density,
                 )
             } else {
                 placeWithoutLabel(
@@ -904,7 +907,6 @@
             supportingHeight = supportingHeight,
             animationProgress = animationProgress,
             constraints = ZeroConstraints,
-            density = density,
             paddingValues = paddingValues
         )
     }
@@ -939,7 +941,7 @@
     return max(wrappedWidth, constraints.minWidth)
 }
 
-private fun calculateHeight(
+private fun Density.calculateHeight(
     textFieldHeight: Int,
     labelHeight: Int,
     leadingHeight: Int,
@@ -950,22 +952,21 @@
     supportingHeight: Int,
     animationProgress: Float,
     constraints: Constraints,
-    density: Float,
     paddingValues: PaddingValues
 ): Int {
     val hasLabel = labelHeight > 0
 
-    val verticalPadding =
-        density *
-            (paddingValues.calculateTopPadding() + paddingValues.calculateBottomPadding()).value
-    // Even though the padding is defined by the developer, if there's a label, it only affects the
-    // text field in the focused state. Otherwise, we use the default value.
-    val actualVerticalPadding =
+    // The padding defined by the user only applies to the text field when the label
+    // is focused. More padding needs to be added when the text field is unfocused.
+    val baseVerticalPadding =
+        (paddingValues.calculateTopPadding() + paddingValues.calculateBottomPadding()).toPx()
+    val labelVerticalPadding =
         if (hasLabel) {
-            lerp((TextFieldPadding * 2).value * density, verticalPadding, animationProgress)
+            lerp((TextFieldLabelExtraPadding * 2).toPx(), 0f, animationProgress)
         } else {
-            verticalPadding
+            0f
         }
+    val verticalPadding = (baseVerticalPadding + labelVerticalPadding).roundToInt()
 
     val inputFieldHeight =
         maxOf(
@@ -977,11 +978,11 @@
         )
 
     val middleSectionHeight =
-        actualVerticalPadding + lerp(0, labelHeight, animationProgress) + inputFieldHeight
+        verticalPadding + (if (animationProgress == 1f) labelHeight else 0) + inputFieldHeight
 
     return max(
         constraints.minHeight,
-        maxOf(leadingHeight, trailingHeight, middleSectionHeight.roundToInt()) + supportingHeight
+        maxOf(leadingHeight, trailingHeight, middleSectionHeight) + supportingHeight
     )
 }
 
@@ -993,7 +994,7 @@
     width: Int,
     totalHeight: Int,
     textfieldPlaceable: Placeable,
-    labelPlaceable: Placeable?,
+    labelPlaceable: Placeable,
     placeholderPlaceable: Placeable?,
     leadingPlaceable: Placeable?,
     trailingPlaceable: Placeable?,
@@ -1002,10 +1003,10 @@
     containerPlaceable: Placeable,
     supportingPlaceable: Placeable?,
     singleLine: Boolean,
+    labelStartPosition: Int,
     labelEndPosition: Int,
     textPosition: Int,
     animationProgress: Float,
-    density: Float
 ) {
     // place container
     containerPlaceable.place(IntOffset.Zero)
@@ -1018,23 +1019,18 @@
         0,
         Alignment.CenterVertically.align(leadingPlaceable.height, height)
     )
-    labelPlaceable?.let {
-        // if it's a single line, the label's start position is in the center of the
-        // container. When it's a multiline text field, the label's start position is at the
-        // top with padding
-        val startPosition =
-            if (singleLine) {
-                Alignment.CenterVertically.align(it.height, height)
-            } else {
-                // Even though the padding is defined by the developer, it only affects the text
-                // field
-                // when the text field is focused. Otherwise, we use the default value.
-                (TextFieldPadding.value * density).roundToInt()
-            }
-        val distance = startPosition - labelEndPosition
-        val positionY = startPosition - (distance * animationProgress).roundToInt()
-        it.placeRelative(widthOrZero(leadingPlaceable), positionY)
-    }
+
+    val labelY =
+        labelPlaceable.let {
+            val startPosition =
+                if (singleLine) {
+                    Alignment.CenterVertically.align(it.height, height)
+                } else {
+                    labelStartPosition
+                }
+            lerp(startPosition, labelEndPosition, animationProgress)
+        }
+    labelPlaceable.placeRelative(widthOrZero(leadingPlaceable), labelY)
 
     prefixPlaceable?.placeRelative(widthOrZero(leadingPlaceable), textPosition)
 
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TextFieldDefaults.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TextFieldDefaults.kt
index a7f4fb3..af7ea36 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TextFieldDefaults.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TextFieldDefaults.kt
@@ -227,12 +227,11 @@
      * @param shape defines the shape of this decoration box's container
      * @param colors [TextFieldColors] that will be used to resolve the colors used for this text
      *   field decoration box in different states. See [TextFieldDefaults.colors].
-     * @param contentPadding the padding applied between the internal elements of this decoration
-     *   box and the edge of its container. If a [label] is present, the top padding represents the
-     *   distance from the top edge of the container to the top of the label when the text field is
-     *   focused. When [label] is null, the top padding represents the distance from the top edge of
-     *   the container to the top of the input field. All other paddings represent the distance from
-     *   the edge of the container to the corresponding edge of the closest element.
+     * @param contentPadding the padding between the input field and the surrounding elements of the
+     *   decoration box. Note that the padding values may not be respected if they are incompatible
+     *   with the text field's size constraints or layout. See
+     *   [TextFieldDefaults.contentPaddingWithLabel] and
+     *   [TextFieldDefaults.contentPaddingWithoutLabel].
      * @param container the container to be drawn behind the text field. By default, this uses
      *   [Container]. Default colors for the container come from the [colors].
      */
@@ -297,10 +296,12 @@
     }
 
     /**
-     * Default content padding applied to [TextField] when there is a label.
+     * Default content padding of the input field within the [TextField] when there is a label,
+     * except for the top padding, which instead represents the padding of the label in the focused
+     * state. The input field is placed directly beneath the label.
      *
-     * The top padding represents ths distance between the top edge of the [TextField] and the top
-     * of the label in the focused state. The input field is placed directly beneath the label.
+     * Horizontal padding represents the distance between the input field and the leading/trailing
+     * icons (if present) or the horizontal edges of the container if there are no icons.
      */
     fun contentPaddingWithLabel(
         start: Dp = TextFieldPadding,
@@ -309,7 +310,12 @@
         bottom: Dp = TextFieldWithLabelVerticalPadding
     ): PaddingValues = PaddingValues(start, top, end, bottom)
 
-    /** Default content padding applied to [TextField] when the label is null. */
+    /**
+     * Default content padding of the input field within the [TextField] when the label is null.
+     *
+     * Horizontal padding represents the distance between the input field and the leading/trailing
+     * icons (if present) or the horizontal edges of the container if there are no icons.
+     */
     fun contentPaddingWithoutLabel(
         start: Dp = TextFieldPadding,
         top: Dp = TextFieldPadding,
@@ -842,8 +848,10 @@
      * @param supportingText the optional supporting text to be displayed below the text field
      * @param colors [TextFieldColors] that will be used to resolve the colors used for this text
      *   field in different states. See [OutlinedTextFieldDefaults.colors].
-     * @param contentPadding the padding applied between the internal elements of this decoration
-     *   box and the edge of its container
+     * @param contentPadding the padding between the input field and the surrounding elements of the
+     *   decoration box. Note that the padding values may not be respected if they are incompatible
+     *   with the text field's size constraints or layout. See
+     *   [OutlinedTextFieldDefaults.contentPadding].
      * @param container the container to be drawn behind the text field. By default, this is
      *   transparent and only includes a border. The cutout in the border to fit the [label] will be
      *   automatically added by the framework. Default colors for the container come from the
@@ -904,7 +912,10 @@
     }
 
     /**
-     * Default content padding applied to [OutlinedTextField]. See [PaddingValues] for more details.
+     * Default content padding of the input field within the [OutlinedTextField].
+     *
+     * Horizontal padding represents the distance between the input field and the leading/trailing
+     * icons (if present) or the horizontal edges of the container if there are no icons.
      */
     fun contentPadding(
         start: Dp = TextFieldPadding,
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TimePicker.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TimePicker.kt
index cb515cc..aa0c01f 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TimePicker.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TimePicker.kt
@@ -1707,7 +1707,7 @@
 
     if (value.text.isEmpty()) {
         if (selection == TimePickerSelectionMode.Hour) {
-            state.hour = 0
+            state.hour = if (state.isAfternoon && !state.is24hour) 12 else 0
         } else {
             state.minute = 0
         }
@@ -1725,7 +1725,7 @@
 
         if (newValue <= max) {
             if (selection == TimePickerSelectionMode.Hour) {
-                state.hour = newValue
+                state.hour = newValue + if (state.isAfternoon && !state.is24hour) 12 else 0
                 if (newValue > 1 && !state.is24hour) {
                     state.selection = TimePickerSelectionMode.Minute
                 }
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/WavyProgressIndicator.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/WavyProgressIndicator.kt
index 07cf9bd..477aa04 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/WavyProgressIndicator.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/WavyProgressIndicator.kt
@@ -140,7 +140,7 @@
     gapSize: Dp = WavyProgressIndicatorDefaults.LinearIndicatorTrackGapSize,
     stopSize: Dp = WavyProgressIndicatorDefaults.LinearTrackStopIndicatorSize,
     amplitude: (progress: Float) -> Float = WavyProgressIndicatorDefaults.indicatorAmplitude,
-    wavelength: Dp = WavyProgressIndicatorDefaults.LinearWavelength,
+    wavelength: Dp = WavyProgressIndicatorDefaults.LinearDeterminateWavelength,
     waveSpeed: Dp = wavelength // Match to 1 wavelength per second
 ) {
     val coercedProgress = { progress().coerceIn(0f, 1f) }
@@ -296,7 +296,7 @@
     stroke: Stroke = WavyProgressIndicatorDefaults.linearIndicatorStroke,
     trackStroke: Stroke = WavyProgressIndicatorDefaults.linearTrackStroke,
     gapSize: Dp = WavyProgressIndicatorDefaults.LinearIndicatorTrackGapSize,
-    wavelength: Dp = WavyProgressIndicatorDefaults.LinearWavelength
+    wavelength: Dp = WavyProgressIndicatorDefaults.LinearIndeterminateWavelength
 ) {
     val infiniteTransition = rememberInfiniteTransition()
     val firstLineHead =
@@ -996,8 +996,11 @@
                 cap = StrokeCap.Round
             )
 
+    /** A default wavelength of a determinate linear progress indicator when it's in a wavy form. */
+    val LinearDeterminateWavelength: Dp = LinearProgressIndicatorTokens.ActiveWaveWavelength
+
     /** A default wavelength of a linear progress indicator when it's in a wavy form. */
-    val LinearWavelength: Dp = LinearProgressIndicatorTokens.ActiveWaveWavelength
+    val LinearIndeterminateWavelength: Dp = 20.dp // TODO Read from tokens when available
 
     /** A default linear progress indicator container height. */
     val LinearContainerHeight: Dp = LinearProgressIndicatorTokens.WaveHeight
@@ -1424,7 +1427,10 @@
         val halfHeight = currentSize.height / 2f
 
         var adjustedTrackGapSize = currentIndicatorTrackGapSize
-        var horizontalInsets = currentStrokeCapWidth
+
+        // The path will only be visible if the Cap can be drawn, so this flag will indicate when
+        // that happens to help us adjust the gap between the active indicator and the track.
+        var activeIndicatorVisible = false
 
         // For each of the progress paths, apply a segment from the PathMeasure that was previously
         // created for the entire width of the progress bar. Also, draw the track parts in the gaps
@@ -1443,21 +1449,27 @@
 
             if (i == 0) {
                 // Potentially shorten the gap and insets when the progress bar just enters the
-                // track
-                adjustedTrackGapSize = min(barHead, currentIndicatorTrackGapSize)
-                horizontalInsets = min(barHead, currentStrokeCapWidth)
+                // track.
+                // When rounded caps are applied, we need enough space to draw the initial path
+                // (i.e. circle), so by only adjusting the gap size when the
+                // barHead >= currentStrokeCapWidth we ensure that the track is not being shortened
+                // in this initial progress phase.
+                adjustedTrackGapSize =
+                    if (barHead < currentStrokeCapWidth) {
+                        0f // barHead
+                    } else {
+                        min(
+                            barHead - currentStrokeCapWidth,
+                            currentIndicatorTrackGapSize /*+ currentStrokeCapWidth * 2*/
+                        )
+                    }
+                activeIndicatorVisible = barHead >= currentStrokeCapWidth
             }
-            // Coerce the bar's head and tail with the horizontalInsets (i.e leave room for the
-            // drawing of the stroke caps). The adjustments here also ensure that the progress is
-            // visible even when the progress is very small by leaving the tail's value unadjusted.
-            val coerceRange = horizontalInsets..(width - currentStrokeCapWidth)
+            // Coerce the bar's head and tail to ensure we leave room for the drawing of the
+            // stroke's caps.
+            val coerceRange = currentStrokeCapWidth..(width - currentStrokeCapWidth)
             val adjustedBarHead = barHead.coerceIn(coerceRange)
-            val adjustedBarTail =
-                if (barTail + horizontalInsets < adjustedBarHead) {
-                    barTail.coerceIn(coerceRange)
-                } else {
-                    barTail
-                }
+            val adjustedBarTail = barTail.coerceIn(coerceRange)
 
             // Update the progressPathToDraw
             if (abs(endProgressFraction - startProgressFraction) > 0) {
@@ -1483,8 +1495,7 @@
                         )
                         // The progressPathToDraw is a segment of the full progress path, which is
                         // always in the maximum possible amplitude. This scaling will flatten the
-                        // wave
-                        // to the given amplitude percentage.
+                        // wave to the given amplitude percentage.
                         if (amplitude != 1f) {
                             scale(y = amplitude)
                         }
@@ -1494,7 +1505,14 @@
 
             // While we draw the progress parts from left to right, we also draw the track parts
             // from right to left and update the nextEndTrackOffset on every pass.
-            val adaptiveTrackSpacing = horizontalInsets * 2 + adjustedTrackGapSize
+            // Before that, we calculate the spacing between the active indicator and the track to
+            // adjust it if needed when the progress is small.
+            val adaptiveTrackSpacing =
+                if (activeIndicatorVisible) {
+                    adjustedTrackGapSize + currentStrokeCapWidth * 2
+                } else {
+                    adjustedTrackGapSize
+                }
             if (nextEndTrackOffset > adjustedBarHead + adaptiveTrackSpacing) {
                 trackPathToDraw.lineTo(
                     x = max(currentStrokeCapWidth, adjustedBarHead + adaptiveTrackSpacing),
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/internal/ShapeUtil.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/internal/ShapeUtil.kt
index 6d0154a..620d3c2 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/internal/ShapeUtil.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/internal/ShapeUtil.kt
@@ -16,15 +16,23 @@
 
 package androidx.compose.material3.internal
 
+import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.graphics.Matrix
 import androidx.compose.ui.graphics.Path
 import androidx.compose.ui.util.fastForEach
 import androidx.graphics.shapes.Cubic
 import androidx.graphics.shapes.Morph
 import androidx.graphics.shapes.RoundedPolygon
+import androidx.graphics.shapes.TransformResult
 import kotlin.math.PI
 import kotlin.math.atan2
 
+/** Transforms a [RoundedPolygon] with the given [Matrix] */
+internal fun RoundedPolygon.transformed(matrix: Matrix): RoundedPolygon = transformed { x, y ->
+    val transformedPoint = matrix.map(Offset(x, y))
+    TransformResult(transformedPoint.x, transformedPoint.y)
+}
+
 /**
  * Gets a [Path] representation for a [RoundedPolygon] shape. Note that there is some rounding
  * happening (to the nearest thousandth), to work around rendering artifacts introduced by some
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/internal/TextFieldImpl.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/internal/TextFieldImpl.kt
index adda9d9..34a9bfa 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/internal/TextFieldImpl.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/internal/TextFieldImpl.kt
@@ -67,6 +67,7 @@
 import androidx.compose.ui.unit.Constraints
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
 
 internal enum class TextFieldType {
     Filled,
@@ -490,6 +491,8 @@
 private const val PlaceholderAnimationDelayOrDuration = 67
 
 internal val TextFieldPadding = 16.dp
+// SP not DP because it should scale with font size. Value equal to bodySmall line height / 2.
+internal val TextFieldLabelExtraPadding = 8.sp
 internal val HorizontalIconPadding = 12.dp
 internal val SupportingTopPadding = 4.dp
 internal val PrefixSuffixTextPadding = 2.dp
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/pulltorefresh/PullToRefresh.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/pulltorefresh/PullToRefresh.kt
index 65d22ea..b1e681f 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/pulltorefresh/PullToRefresh.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/pulltorefresh/PullToRefresh.kt
@@ -28,15 +28,21 @@
 import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.foundation.layout.requiredSize
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.shape.CircleShape
 import androidx.compose.material3.CircularProgressIndicator
 import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
+import androidx.compose.material3.LoadingIndicatorDefaults
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults.Indicator
+import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults.loadingIndicatorColor
+import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults.loadingIndicatorContainerColor
 import androidx.compose.material3.tokens.ElevationTokens
 import androidx.compose.material3.tokens.MotionTokens
+import androidx.compose.material3.value
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.Immutable
 import androidx.compose.runtime.Stable
@@ -89,10 +95,16 @@
 /**
  * [PullToRefreshBox] is a container that expects a scrollable layout as content and adds gesture
  * support for manually refreshing when the user swipes downward at the beginning of the content. By
- * default, it uses [PullToRefreshDefaults.Indicator] as the refresh indicator.
+ * default, it uses [PullToRefreshDefaults.Indicator] as the refresh indicator, but you may also
+ * choose to set your own indicator or use [PullToRefreshDefaults.LoadingIndicator].
  *
  * @sample androidx.compose.material3.samples.PullToRefreshSample
  *
+ * Using a [androidx.compose.material3.LoadingIndicator] as the [PullToRefreshBox] indicator can be
+ * done like this
+ *
+ * @sample androidx.compose.material3.samples.PullToRefreshWithLoadingIndicatorSample
+ *
  * View models can be used as source as truth as shown in
  *
  * @sample androidx.compose.material3.samples.PullToRefreshViewModelSample
@@ -370,13 +382,33 @@
     val shape: Shape = CircleShape
 
     /** The default container color for [Indicator] */
+    @Deprecated(
+        "Use loadingIndicatorContainerColor instead",
+        ReplaceWith("loadingIndicatorContainerColor")
+    )
     val containerColor: Color
         @Composable get() = MaterialTheme.colorScheme.surfaceContainerHigh
 
+    /**
+     * The default container color for the loading indicator that appears when pulling to refresh.
+     */
+    @ExperimentalMaterial3ExpressiveApi
+    val loadingIndicatorContainerColor: Color
+        @Composable get() = LoadingIndicatorDefaults.ContainerColor
+
     /** The default indicator color for [Indicator] */
+    @Deprecated("Use loadingIndicatorColor instead", ReplaceWith("loadingIndicatorColor"))
     val indicatorColor: Color
         @Composable get() = MaterialTheme.colorScheme.onSurfaceVariant
 
+    /**
+     * The default active indicator color for the loading indicator that appears when pulling to
+     * refresh.
+     */
+    @ExperimentalMaterial3ExpressiveApi
+    val loadingIndicatorColor: Color
+        @Composable get() = LoadingIndicatorDefaults.IndicatorColor
+
     /** The default refresh threshold for [rememberPullToRefreshState] */
     val PositionalThreshold = 80.dp
 
@@ -449,6 +481,7 @@
      * @param threshold how much the indicator can be pulled down before a refresh is triggered on
      *   release
      */
+    @Suppress("DEPRECATION")
     @Composable
     fun Indicator(
         state: PullToRefreshState,
@@ -484,6 +517,74 @@
             }
         }
     }
+
+    /** A [LoadingIndicator] indicator for [PullToRefreshBox]. */
+    @ExperimentalMaterial3ExpressiveApi
+    @Composable
+    fun LoadingIndicator(
+        state: PullToRefreshState,
+        isRefreshing: Boolean,
+        modifier: Modifier = Modifier,
+        containerColor: Color = this.loadingIndicatorContainerColor,
+        color: Color = this.loadingIndicatorColor,
+        elevation: Dp = ElevationTokens.Level0,
+        threshold: Dp = PositionalThreshold
+    ) {
+        IndicatorBox(
+            modifier = modifier.size(width = LoaderIndicatorWidth, height = LoaderIndicatorHeight),
+            state = state,
+            isRefreshing = isRefreshing,
+            containerColor = containerColor,
+            elevation = elevation,
+            threshold = threshold,
+        ) {
+            Crossfade(
+                targetState = isRefreshing,
+                animationSpec = tween(durationMillis = CrossfadeDurationMs)
+            ) { refreshing ->
+                if (refreshing) {
+                    androidx.compose.material3.LoadingIndicator(
+                        // TODO Set the LoadingIndicator colors
+                        modifier =
+                            Modifier.requiredSize(
+                                width = LoaderIndicatorWidth,
+                                height = LoaderIndicatorHeight
+                            ),
+                        containerColor = containerColor,
+                        indicatorColor = color
+                    )
+                } else {
+                    // The LoadingIndicator will rotate and morph for a coerced progress value of 0
+                    // to 1. When the state's distanceFraction is above one, we rotate the entire
+                    // component we have a continuous rotation until the refreshing flag is true.
+                    androidx.compose.material3.LoadingIndicator(
+                        // TODO Set the LoadingIndicator colors
+                        progress = { state.distanceFraction },
+                        modifier =
+                            Modifier.requiredSize(
+                                    width = LoaderIndicatorWidth,
+                                    height = LoaderIndicatorHeight
+                                )
+                                .drawWithContent {
+                                    val progress = state.distanceFraction
+                                    if (progress > 1f) {
+                                        // Start the rotation on progress - 1 (i.e. 0) to avoid a
+                                        // jump that would be more noticeable on some
+                                        // LoadingIndicator shapes.
+                                        rotate(-(progress - 1) * 180) {
+                                            [email protected]()
+                                        }
+                                    } else {
+                                        drawContent()
+                                    }
+                                },
+                        containerColor = containerColor,
+                        indicatorColor = color
+                    )
+                }
+            }
+        }
+    }
 }
 
 /**
@@ -679,6 +780,11 @@
 private val ArrowWidth = 10.dp
 private val ArrowHeight = 5.dp
 
+@OptIn(ExperimentalMaterial3ExpressiveApi::class)
+internal val LoaderIndicatorHeight = LoadingIndicatorDefaults.ContainerHeight
+@OptIn(ExperimentalMaterial3ExpressiveApi::class)
+internal val LoaderIndicatorWidth = LoadingIndicatorDefaults.ContainerWidth
+
 // Values taken from SwipeRefreshLayout
 private const val MinAlpha = 0.3f
 private const val MaxAlpha = 1f
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/IconButtonSmallTokens.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/IconButtonSmallTokens.kt
new file mode 100644
index 0000000..aa3dc18
--- /dev/null
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/IconButtonSmallTokens.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// VERSION: v0_4_0
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+package androidx.compose.material3.tokens
+
+import androidx.compose.ui.unit.dp
+
+internal object IconButtonSmallTokens {
+    val ContainerHeight = 40.0.dp
+    val ContainerShapeRound = ShapeKeyTokens.CornerFull
+    val ContainerShapeSquare = ShapeKeyTokens.CornerMedium
+    val IconSize = 24.0.dp
+    val NarrowLeadingSpace = 4.0.dp
+    val NarrowTrailingSpace = 4.0.dp
+    val OutlinedOutlineWidth = 1.0.dp
+    val PressedContainerCornerSizeMultiplierPercent = 50.0f
+    val SelectedPressedContainerShape = ShapeKeyTokens.CornerMedium
+    val UniformLeadingSpace = 8.0.dp
+    val UniformTrailingSpace = 8.0.dp
+    val WideLeadingSpace = 14.0.dp
+    val WideTrailingSpace = 14.0.dp
+}
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/LoadingIndicatorTokens.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/LoadingIndicatorTokens.kt
new file mode 100644
index 0000000..1ef18af
--- /dev/null
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/LoadingIndicatorTokens.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// VERSION: v0_4_0
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+package androidx.compose.material3.tokens
+
+import androidx.compose.ui.unit.dp
+
+internal object LoadingIndicatorTokens {
+    val ActiveIndicatorColor = ColorSchemeKeyTokens.Primary
+    val ActiveSize = 38.0.dp
+    val ContainerColor = ColorSchemeKeyTokens.SecondaryContainer
+    val ContainerHeight = 48.0.dp
+    val ContainerShape = ShapeKeyTokens.CornerFull
+    val ContainerWidth = 48.0.dp
+}
diff --git a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/CalendarLocale.desktop.kt b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/CalendarLocale.desktop.kt
deleted file mode 100644
index 3f24336..0000000
--- a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/CalendarLocale.desktop.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material3
-
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.ReadOnlyComposable
-
-/** Returns the default [CalendarLocale]. */
-@Composable
-@ReadOnlyComposable
-@OptIn(ExperimentalMaterial3Api::class)
-internal actual fun defaultLocale(): CalendarLocale = java.util.Locale.getDefault()
diff --git a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/NavigationDrawer.desktop.kt b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/NavigationDrawer.desktop.kt
deleted file mode 100644
index 94baaa8..0000000
--- a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/NavigationDrawer.desktop.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material3
-
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
-
-/**
- * A predictive back handler that does nothing when running in a desktop context, since predictive
- * back is only supported on Android.
- *
- * @param drawerState state of the drawer
- * @param content content of the rest of the UI
- */
-@Composable
-internal actual fun DrawerPredictiveBackHandler(
-    drawerState: DrawerState,
-    content: @Composable (DrawerPredictiveBackState) -> Unit
-) {
-    content(remember { DrawerPredictiveBackState() })
-}
diff --git a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/TimeFormat.desktop.kt b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/TimeFormat.desktop.kt
deleted file mode 100644
index ca9055a..0000000
--- a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/TimeFormat.desktop.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material3
-
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.ReadOnlyComposable
-
-internal actual val is24HourFormat: Boolean
-    @Composable @ReadOnlyComposable get() = false
diff --git a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/TimePicker.desktop.kt b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/TimePicker.desktop.kt
deleted file mode 100644
index 530eca7..0000000
--- a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/TimePicker.desktop.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material3
-
-@OptIn(ExperimentalMaterial3Api::class)
-internal actual val defaultTimePickerLayoutType: TimePickerLayoutType =
-    TimePickerLayoutType.Vertical
diff --git a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/Tooltip.desktop.kt b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/Tooltip.desktop.kt
deleted file mode 100644
index 1085812..0000000
--- a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/Tooltip.desktop.kt
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material3
-
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.paddingFromBaseline
-import androidx.compose.foundation.layout.requiredHeightIn
-import androidx.compose.foundation.layout.sizeIn
-import androidx.compose.material3.tokens.PlainTooltipTokens
-import androidx.compose.material3.tokens.RichTooltipTokens
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.Shape
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.DpSize
-
-/**
- * Plain tooltip that provides a descriptive message.
- *
- * Usually used with [TooltipBox].
- *
- * @param modifier the [Modifier] to be applied to the tooltip.
- * @param caretSize [DpSize] for the caret of the tooltip, if a default caret is desired with a
- *   specific dimension. Please see [TooltipDefaults.caretSize] to see the default dimensions. Pass
- *   in Dp.Unspecified for this parameter if no caret is desired.
- * @param shape the [Shape] that should be applied to the tooltip container.
- * @param contentColor [Color] that will be applied to the tooltip's content.
- * @param containerColor [Color] that will be applied to the tooltip's container.
- * @param tonalElevation the tonal elevation of the tooltip.
- * @param shadowElevation the shadow elevation of the tooltip.
- * @param content the composable that will be used to populate the tooltip's content.
- */
-@Composable
-@ExperimentalMaterial3Api
-actual fun TooltipScope.PlainTooltip(
-    modifier: Modifier,
-    caretSize: DpSize,
-    shape: Shape,
-    contentColor: Color,
-    containerColor: Color,
-    tonalElevation: Dp,
-    shadowElevation: Dp,
-    content: @Composable () -> Unit
-) {
-    Surface(
-        modifier = modifier,
-        shape = shape,
-        color = containerColor,
-        tonalElevation = tonalElevation,
-        shadowElevation = shadowElevation
-    ) {
-        Box(
-            modifier =
-                Modifier.sizeIn(
-                        minWidth = TooltipMinWidth,
-                        maxWidth = PlainTooltipMaxWidth,
-                        minHeight = TooltipMinHeight
-                    )
-                    .padding(PlainTooltipContentPadding)
-        ) {
-            val textStyle = PlainTooltipTokens.SupportingTextFont.value
-            CompositionLocalProvider(
-                LocalContentColor provides contentColor,
-                LocalTextStyle provides textStyle,
-                content = content
-            )
-        }
-    }
-}
-
-/**
- * Rich text tooltip that allows the user to pass in a title, text, and action. Tooltips are used to
- * provide a descriptive message.
- *
- * Usually used with [TooltipBox]
- *
- * @param modifier the [Modifier] to be applied to the tooltip.
- * @param title An optional title for the tooltip.
- * @param action An optional action for the tooltip.
- * @param caretSize [DpSize] for the caret of the tooltip, if a default caret is desired with a
- *   specific dimension. Please see [TooltipDefaults.caretSize] to see the default dimensions. Pass
- *   in Dp.Unspecified for this parameter if no caret is desired.
- * @param shape the [Shape] that should be applied to the tooltip container.
- * @param colors [RichTooltipColors] that will be applied to the tooltip's container and content.
- * @param tonalElevation the tonal elevation of the tooltip.
- * @param shadowElevation the shadow elevation of the tooltip.
- * @param text the composable that will be used to populate the rich tooltip's text.
- */
-@Composable
-@ExperimentalMaterial3Api
-actual fun TooltipScope.RichTooltip(
-    modifier: Modifier,
-    title: (@Composable () -> Unit)?,
-    action: (@Composable () -> Unit)?,
-    caretSize: DpSize,
-    shape: Shape,
-    colors: RichTooltipColors,
-    tonalElevation: Dp,
-    shadowElevation: Dp,
-    text: @Composable () -> Unit
-) {
-    Surface(
-        modifier =
-            modifier.sizeIn(
-                minWidth = TooltipMinWidth,
-                maxWidth = RichTooltipMaxWidth,
-                minHeight = TooltipMinHeight
-            ),
-        shape = shape,
-        color = colors.containerColor,
-        tonalElevation = tonalElevation,
-        shadowElevation = shadowElevation
-    ) {
-        val actionLabelTextStyle = RichTooltipTokens.ActionLabelTextFont.value
-        val subheadTextStyle = RichTooltipTokens.SubheadFont.value
-        val supportingTextStyle = RichTooltipTokens.SupportingTextFont.value
-
-        Column(modifier = Modifier.padding(horizontal = RichTooltipHorizontalPadding)) {
-            title?.let {
-                Box(modifier = Modifier.paddingFromBaseline(top = HeightToSubheadFirstLine)) {
-                    CompositionLocalProvider(
-                        LocalContentColor provides colors.titleContentColor,
-                        LocalTextStyle provides subheadTextStyle,
-                        content = it
-                    )
-                }
-            }
-            Box(modifier = Modifier.textVerticalPadding(title != null, action != null)) {
-                CompositionLocalProvider(
-                    LocalContentColor provides colors.contentColor,
-                    LocalTextStyle provides supportingTextStyle,
-                    content = text
-                )
-            }
-            action?.let {
-                Box(
-                    modifier =
-                        Modifier.requiredHeightIn(min = ActionLabelMinHeight)
-                            .padding(bottom = ActionLabelBottomPadding)
-                ) {
-                    CompositionLocalProvider(
-                        LocalContentColor provides colors.actionContentColor,
-                        LocalTextStyle provides actionLabelTextStyle,
-                        content = it
-                    )
-                }
-            }
-        }
-    }
-}
diff --git a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/internal/AccessibilityServiceStateProvider.desktop.kt b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/internal/AccessibilityServiceStateProvider.desktop.kt
deleted file mode 100644
index d4e155e..0000000
--- a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/internal/AccessibilityServiceStateProvider.desktop.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material3.internal
-
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.State
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-
-@Composable
-internal actual fun rememberAccessibilityServiceState(
-    listenToTouchExplorationState: Boolean,
-    listenToSwitchAccessState: Boolean,
-): State<Boolean> {
-    return remember { mutableStateOf(false) }
-}
diff --git a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/internal/BasicTooltip.desktop.kt b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/internal/BasicTooltip.desktop.kt
deleted file mode 100644
index a689144..0000000
--- a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/internal/BasicTooltip.desktop.kt
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material3.internal
-
-import androidx.compose.foundation.layout.Box
-import androidx.compose.material3.ExperimentalMaterial3Api
-import androidx.compose.material3.TooltipState
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.window.Popup
-import androidx.compose.ui.window.PopupPositionProvider
-import androidx.compose.ui.window.PopupProperties
-
-/**
- * NOTICE: Fork from androidx.compose.foundation.BasicTooltip box since those are experimental
- *
- * Tooltip that provides a descriptive message for an anchor. It can be used to call the users
- * attention to the anchor.
- *
- * @param positionProvider [PopupPositionProvider] that will be used to place the tooltip relative
- *   to the anchor content.
- * @param tooltip the composable that will be used to populate the tooltip's content.
- * @param state handles the state of the tooltip's visibility.
- * @param modifier the [Modifier] to be applied to this BasicTooltipBox.
- * @param focusable [Boolean] that determines if the tooltip is focusable. When true, the tooltip
- *   will consume touch events while it's shown and will have accessibility focus move to the first
- *   element of the component. When false, the tooltip won't consume touch events while it's shown
- *   but assistive-tech users will need to swipe or drag to get to the first element of the
- *   component.
- * @param enableUserInput [Boolean] which determines if this BasicTooltipBox will handle long press
- *   and mouse hover to trigger the tooltip through the state provided.
- * @param content the composable that the tooltip will anchor to.
- */
-@OptIn(ExperimentalMaterial3Api::class)
-@Composable
-internal actual fun BasicTooltipBox(
-    positionProvider: PopupPositionProvider,
-    tooltip: @Composable () -> Unit,
-    state: TooltipState,
-    modifier: Modifier,
-    focusable: Boolean,
-    enableUserInput: Boolean,
-    content: @Composable () -> Unit
-) {
-    // TODO: Reuse android implementation - there is no platform specifics here.
-    //  Use expect/actual only for string resources
-    Box(modifier = modifier) {
-        content()
-        if (state.isVisible) {
-            Popup(
-                popupPositionProvider = positionProvider,
-                onDismissRequest = { state.dismiss() },
-                properties =
-                    PopupProperties(
-                        // TODO(b/326167778): focusable = true cannot work with mouse
-                        focusable = false
-                    )
-            ) {
-                tooltip()
-            }
-        }
-    }
-}
diff --git a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/internal/CalendarModel.desktop.kt b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/internal/CalendarModel.desktop.kt
deleted file mode 100644
index 2e183af..0000000
--- a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/internal/CalendarModel.desktop.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material3.internal
-
-import androidx.compose.material3.CalendarLocale
-
-/** Returns a [CalendarModel] to be used by the date picker. */
-internal actual fun createCalendarModel(locale: CalendarLocale): CalendarModel =
-    LegacyCalendarModelImpl(locale)
-
-/**
- * Formats a UTC timestamp into a string with a given date format skeleton.
- *
- * @param utcTimeMillis a UTC timestamp to format (milliseconds from epoch)
- * @param skeleton a date format skeleton
- * @param locale the [CalendarLocale] to use when formatting the given timestamp
- * @param cache a [MutableMap] for caching formatter related results for better performance
- */
-internal actual fun formatWithSkeleton(
-    utcTimeMillis: Long,
-    skeleton: String,
-    locale: CalendarLocale,
-    cache: MutableMap<String, Any>
-): String {
-    // Note: there is no equivalent in Java for Android's DateFormat.getBestDateTimePattern.
-    // The JDK SimpleDateFormat expects a pattern, so the results will be "2023Jan7",
-    // "2023January", etc. in case a skeleton holds an actual ICU skeleton and not a pattern.
-    return LegacyCalendarModelImpl.formatWithPattern(
-        utcTimeMillis = utcTimeMillis,
-        pattern = skeleton,
-        locale = locale,
-        cache = cache
-    )
-}
diff --git a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/internal/DefaultPlatformTextStyle.desktop.kt b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/internal/DefaultPlatformTextStyle.desktop.kt
deleted file mode 100644
index 7bf9d47..0000000
--- a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/internal/DefaultPlatformTextStyle.desktop.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material3.internal
-
-import androidx.compose.ui.text.PlatformTextStyle
-
-internal actual fun defaultPlatformTextStyle(): PlatformTextStyle? = null
diff --git a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/internal/Strings.desktop.kt b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/internal/Strings.desktop.kt
deleted file mode 100644
index 4e0f782..0000000
--- a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/internal/Strings.desktop.kt
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material3.internal
-
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.Immutable
-import androidx.compose.runtime.ReadOnlyComposable
-import java.util.Locale
-
-@Composable
-@ReadOnlyComposable
-internal actual fun getString(string: Strings): String {
-    return when (string) {
-        Strings.NavigationMenu -> "Navigation menu"
-        Strings.CloseDrawer -> "Close navigation menu"
-        Strings.CloseSheet -> "Close sheet"
-        Strings.DefaultErrorMessage -> "Invalid input"
-        Strings.SliderRangeStart -> "Range Start"
-        Strings.SliderRangeEnd -> "Range End"
-        Strings.Dialog -> "Dialog"
-        Strings.MenuExpanded -> "Expanded"
-        Strings.MenuCollapsed -> "Collapsed"
-        Strings.ToggleDropdownMenu -> "Toggle dropdown menu"
-        Strings.SnackbarDismiss -> "Dismiss"
-        Strings.SearchBarSearch -> "Search"
-        Strings.SuggestionsAvailable -> "Suggestions below"
-        Strings.DatePickerTitle -> "Select date"
-        Strings.DatePickerHeadline -> "Selected date"
-        Strings.DatePickerYearPickerPaneTitle -> "Year picker visible"
-        Strings.DatePickerSwitchToYearSelection -> "Switch to selecting a year"
-        Strings.DatePickerSwitchToDaySelection ->
-            "Swipe to select a year, or tap to switch " + "back to selecting a day"
-        Strings.DatePickerSwitchToNextMonth -> "Change to next month"
-        Strings.DatePickerSwitchToPreviousMonth -> "Change to previous month"
-        Strings.DatePickerNavigateToYearDescription -> "Navigate to year %1$"
-        Strings.DatePickerHeadlineDescription -> "Current selection: %1$"
-        Strings.DatePickerNoSelectionDescription -> "None"
-        Strings.DatePickerTodayDescription -> "Today"
-        Strings.DatePickerScrollToShowLaterYears -> "Scroll to show later years"
-        Strings.DatePickerScrollToShowEarlierYears -> "Scroll to show earlier years"
-        Strings.DateInputTitle -> "Select date"
-        Strings.DateInputHeadline -> "Entered date"
-        Strings.DateInputLabel -> "Date"
-        Strings.DateInputHeadlineDescription -> "Entered date: %1$"
-        Strings.DateInputNoInputDescription -> "None"
-        Strings.DateInputInvalidNotAllowed -> "Date not allowed: %1$"
-        Strings.DateInputInvalidForPattern -> "Date does not match expected pattern: %1$"
-        Strings.DateInputInvalidYearRange -> "Date out of expected year range %1$ - %2$"
-        Strings.DatePickerSwitchToCalendarMode -> "Switch to calendar input mode"
-        Strings.DatePickerSwitchToInputMode -> "Switch to text input mode"
-        Strings.DateRangePickerTitle -> "Select dates"
-        Strings.DateRangePickerStartHeadline -> "Start date"
-        Strings.DateRangePickerEndHeadline -> "End date"
-        Strings.DateRangePickerScrollToShowNextMonth -> "Scroll to show the next month"
-        Strings.DateRangePickerScrollToShowPreviousMonth -> "Scroll to show the previous month"
-        Strings.DateRangePickerDayInRange -> "In range"
-        Strings.DateRangeInputTitle -> "Enter dates"
-        Strings.DateRangeInputInvalidRangeInput -> "Invalid date range input"
-        Strings.BottomSheetPaneTitle -> "Bottom Sheet"
-        Strings.BottomSheetDragHandleDescription -> "Drag Handle"
-        Strings.BottomSheetPartialExpandDescription -> "Collapse bottom sheet"
-        Strings.BottomSheetDismissDescription -> "Dismiss bottom sheet"
-        Strings.BottomSheetExpandDescription -> "Expand bottom sheet"
-        Strings.TooltipLongPressLabel -> "Show tooltip"
-        Strings.TimePickerAM -> "AM"
-        Strings.TimePickerPM -> "PM"
-        Strings.TimePickerPeriodToggle -> "Select AM or PM"
-        Strings.TimePickerMinuteSelection -> "Select minutes"
-        Strings.TimePickerHourSelection -> "Select hour"
-        Strings.TimePickerHourSuffix -> "%1$ o\\'clock"
-        Strings.TimePickerMinuteSuffix -> "%1$ minutes"
-        Strings.TimePicker24HourSuffix -> "%1$ hours"
-        Strings.TimePickerMinute -> "Minute"
-        Strings.TimePickerHour -> "Hour"
-        Strings.TimePickerMinuteTextField -> "for minutes"
-        Strings.TimePickerHourTextField -> "for hour"
-        Strings.TooltipPaneDescription -> "Tooltip"
-        else -> ""
-    }
-}
-
-@JvmInline
-@Immutable
-internal actual value class Strings constructor(val value: Int) {
-    actual companion object {
-        actual val NavigationMenu = Strings(0)
-        actual val CloseDrawer = Strings(1)
-        actual val CloseSheet = Strings(2)
-        actual val DefaultErrorMessage = Strings(3)
-        actual val SliderRangeStart = Strings(4)
-        actual val SliderRangeEnd = Strings(5)
-        actual val Dialog = Strings(6)
-        actual val MenuExpanded = Strings(7)
-        actual val MenuCollapsed = Strings(8)
-        actual val SnackbarDismiss = Strings(9)
-        actual val SearchBarSearch = Strings(10)
-        actual val SuggestionsAvailable = Strings(11)
-        actual val DatePickerTitle = Strings(12)
-        actual val DatePickerHeadline = Strings(13)
-        actual val DatePickerYearPickerPaneTitle = Strings(14)
-        actual val DatePickerSwitchToYearSelection = Strings(15)
-        actual val DatePickerSwitchToDaySelection = Strings(16)
-        actual val DatePickerSwitchToNextMonth = Strings(17)
-        actual val DatePickerSwitchToPreviousMonth = Strings(18)
-        actual val DatePickerNavigateToYearDescription = Strings(19)
-        actual val DatePickerHeadlineDescription = Strings(20)
-        actual val DatePickerNoSelectionDescription = Strings(21)
-        actual val DatePickerTodayDescription = Strings(22)
-        actual val DatePickerScrollToShowLaterYears = Strings(23)
-        actual val DatePickerScrollToShowEarlierYears = Strings(24)
-        actual val DateInputTitle = Strings(25)
-        actual val DateInputHeadline = Strings(26)
-        actual val DateInputLabel = Strings(27)
-        actual val DateInputHeadlineDescription = Strings(28)
-        actual val DateInputNoInputDescription = Strings(29)
-        actual val DateInputInvalidNotAllowed = Strings(30)
-        actual val DateInputInvalidForPattern = Strings(31)
-        actual val DateInputInvalidYearRange = Strings(32)
-        actual val DatePickerSwitchToCalendarMode = Strings(33)
-        actual val DatePickerSwitchToInputMode = Strings(34)
-        actual val DateRangePickerTitle = Strings(35)
-        actual val DateRangePickerStartHeadline = Strings(36)
-        actual val DateRangePickerEndHeadline = Strings(37)
-        actual val DateRangePickerScrollToShowNextMonth = Strings(38)
-        actual val DateRangePickerScrollToShowPreviousMonth = Strings(39)
-        actual val DateRangePickerDayInRange = Strings(40)
-        actual val DateRangeInputTitle = Strings(41)
-        actual val DateRangeInputInvalidRangeInput = Strings(42)
-        actual val BottomSheetPaneTitle = Strings(43)
-        actual val BottomSheetDragHandleDescription = Strings(44)
-        actual val BottomSheetPartialExpandDescription = Strings(45)
-        actual val BottomSheetDismissDescription = Strings(46)
-        actual val BottomSheetExpandDescription = Strings(47)
-        actual val TooltipLongPressLabel = Strings(48)
-        actual val TimePickerAM = Strings(49)
-        actual val TimePickerPM = Strings(50)
-        actual val TimePickerPeriodToggle = Strings(51)
-        actual val TimePickerHourSelection = Strings(52)
-        actual val TimePickerMinuteSelection = Strings(53)
-        actual val TimePickerHourSuffix = Strings(54)
-        actual val TimePicker24HourSuffix = Strings(55)
-        actual val TimePickerMinuteSuffix = Strings(56)
-        actual val TimePickerHour = Strings(57)
-        actual val TimePickerMinute = Strings(58)
-        actual val TimePickerHourTextField = Strings(59)
-        actual val TimePickerMinuteTextField = Strings(60)
-        actual val TooltipPaneDescription = Strings(61)
-        actual val ExposedDropdownMenu = Strings(62)
-        actual val ToggleDropdownMenu = Strings(63)
-    }
-}
-
-@Composable
-@ReadOnlyComposable
-internal actual fun getString(string: Strings, vararg formatArgs: Any): String =
-    String.format(getString(string), Locale.getDefault(), *formatArgs)
diff --git a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/internal/SystemBarsDefaultInsets.desktop.kt b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/internal/SystemBarsDefaultInsets.desktop.kt
deleted file mode 100644
index fef57d6..0000000
--- a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/internal/SystemBarsDefaultInsets.desktop.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material3.internal
-
-import androidx.compose.foundation.layout.WindowInsets
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.unit.dp
-
-internal actual val WindowInsets.Companion.systemBarsForVisualComponents: WindowInsets
-    @Composable get() = WindowInsets(0.dp, 0.dp, 0.dp, 0.dp)
diff --git a/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/AlertDialog.jvmStubs.kt b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/AlertDialog.jvmStubs.kt
new file mode 100644
index 0000000..05eb985
--- /dev/null
+++ b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/AlertDialog.jvmStubs.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.window.DialogProperties
+
+@Composable
+actual fun AlertDialog(
+    onDismissRequest: () -> Unit,
+    confirmButton: @Composable () -> Unit,
+    modifier: Modifier,
+    dismissButton: @Composable (() -> Unit)?,
+    icon: @Composable (() -> Unit)?,
+    title: @Composable (() -> Unit)?,
+    text: @Composable (() -> Unit)?,
+    shape: Shape,
+    containerColor: Color,
+    iconContentColor: Color,
+    titleContentColor: Color,
+    textContentColor: Color,
+    tonalElevation: Dp,
+    properties: DialogProperties
+): Unit = implementedInJetBrainsFork()
diff --git a/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/CalendarLocale.jvmStubs.kt b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/CalendarLocale.jvmStubs.kt
new file mode 100644
index 0000000..02ed679
--- /dev/null
+++ b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/CalendarLocale.jvmStubs.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.ReadOnlyComposable
+
+/** Returns the default [CalendarLocale]. */
+@Composable
+@ReadOnlyComposable
+@OptIn(ExperimentalMaterial3Api::class)
+internal actual fun defaultLocale(): CalendarLocale = implementedInJetBrainsFork()
diff --git a/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/ModalBottomSheet.jvmStubs.kt b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/ModalBottomSheet.jvmStubs.kt
new file mode 100644
index 0000000..d1e0033
--- /dev/null
+++ b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/ModalBottomSheet.jvmStubs.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3
+
+import androidx.compose.animation.core.Animatable
+import androidx.compose.animation.core.AnimationVector1D
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Immutable
+
+@Immutable
+@ExperimentalMaterial3Api
+actual class ModalBottomSheetProperties
+actual constructor(
+    actual val shouldDismissOnBackPress: Boolean,
+)
+
+@Immutable
+@ExperimentalMaterial3Api
+actual object ModalBottomSheetDefaults {
+    actual val properties: ModalBottomSheetProperties = implementedInJetBrainsFork()
+}
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+internal actual fun ModalBottomSheetDialog(
+    onDismissRequest: () -> Unit,
+    properties: ModalBottomSheetProperties,
+    predictiveBackProgress: Animatable<Float, AnimationVector1D>,
+    content: @Composable () -> Unit
+): Unit = implementedInJetBrainsFork()
diff --git a/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/NavigationDrawer.jvmStubs.kt b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/NavigationDrawer.jvmStubs.kt
new file mode 100644
index 0000000..39fe5a5
--- /dev/null
+++ b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/NavigationDrawer.jvmStubs.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3
+
+import androidx.compose.runtime.Composable
+
+@Composable
+internal actual fun DrawerPredictiveBackHandler(
+    drawerState: DrawerState,
+    content: @Composable (DrawerPredictiveBackState) -> Unit
+): Unit = implementedInJetBrainsFork()
diff --git a/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/NotImplemented.jvmStubs.kt b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/NotImplemented.jvmStubs.kt
new file mode 100644
index 0000000..faf2f8f
--- /dev/null
+++ b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/NotImplemented.jvmStubs.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3
+
+@Suppress("NOTHING_TO_INLINE")
+internal inline fun implementedInJetBrainsFork(): Nothing =
+    throw NotImplementedError(
+        """
+        Implemented only in JetBrains fork.
+        Please use `org.jetbrains.compose.material3:material3` package instead.
+        """
+            .trimIndent()
+    )
diff --git a/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/SkikoMenu.jvmStubs.kt b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/SkikoMenu.jvmStubs.kt
new file mode 100644
index 0000000..487bc51
--- /dev/null
+++ b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/SkikoMenu.jvmStubs.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3
+
+import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.ScrollState
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.ColumnScope
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.DpOffset
+import androidx.compose.ui.window.PopupProperties
+
+@Composable
+actual fun DropdownMenu(
+    expanded: Boolean,
+    onDismissRequest: () -> Unit,
+    modifier: Modifier,
+    offset: DpOffset,
+    scrollState: ScrollState,
+    properties: PopupProperties,
+    shape: Shape,
+    containerColor: Color,
+    tonalElevation: Dp,
+    shadowElevation: Dp,
+    border: BorderStroke?,
+    content: @Composable ColumnScope.() -> Unit
+): Unit = implementedInJetBrainsFork()
+
+@Composable
+actual fun DropdownMenuItem(
+    text: @Composable () -> Unit,
+    onClick: () -> Unit,
+    modifier: Modifier,
+    leadingIcon: @Composable (() -> Unit)?,
+    trailingIcon: @Composable (() -> Unit)?,
+    enabled: Boolean,
+    colors: MenuItemColors,
+    contentPadding: PaddingValues,
+    interactionSource: MutableInteractionSource?,
+): Unit = implementedInJetBrainsFork()
+
+internal actual val DefaultMenuProperties: PopupProperties = implementedInJetBrainsFork()
diff --git a/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/TimeFormat.jvmStubs.kt b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/TimeFormat.jvmStubs.kt
new file mode 100644
index 0000000..c07f8c7
--- /dev/null
+++ b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/TimeFormat.jvmStubs.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.ReadOnlyComposable
+
+internal actual val is24HourFormat: Boolean
+    @Composable @ReadOnlyComposable get() = implementedInJetBrainsFork()
diff --git a/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/TimePicker.jvmStubs.kt b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/TimePicker.jvmStubs.kt
new file mode 100644
index 0000000..8b28f7b
--- /dev/null
+++ b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/TimePicker.jvmStubs.kt
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3
+
+@OptIn(ExperimentalMaterial3Api::class)
+internal actual val defaultTimePickerLayoutType: TimePickerLayoutType = implementedInJetBrainsFork()
diff --git a/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/Tooltip.jvmStubs.kt b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/Tooltip.jvmStubs.kt
new file mode 100644
index 0000000..c4692a6
--- /dev/null
+++ b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/Tooltip.jvmStubs.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.DpSize
+
+@Composable
+@ExperimentalMaterial3Api
+actual fun TooltipScope.PlainTooltip(
+    modifier: Modifier,
+    caretSize: DpSize,
+    shape: Shape,
+    contentColor: Color,
+    containerColor: Color,
+    tonalElevation: Dp,
+    shadowElevation: Dp,
+    content: @Composable () -> Unit
+): Unit = implementedInJetBrainsFork()
+
+@Composable
+@ExperimentalMaterial3Api
+actual fun TooltipScope.RichTooltip(
+    modifier: Modifier,
+    title: (@Composable () -> Unit)?,
+    action: (@Composable () -> Unit)?,
+    caretSize: DpSize,
+    shape: Shape,
+    colors: RichTooltipColors,
+    tonalElevation: Dp,
+    shadowElevation: Dp,
+    text: @Composable () -> Unit
+): Unit = implementedInJetBrainsFork()
diff --git a/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/internal/AccessibilityServiceStateProvider.jvmStubs.kt b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/internal/AccessibilityServiceStateProvider.jvmStubs.kt
new file mode 100644
index 0000000..e68e24c
--- /dev/null
+++ b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/internal/AccessibilityServiceStateProvider.jvmStubs.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3.internal
+
+import androidx.compose.material3.implementedInJetBrainsFork
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.State
+
+@Composable
+internal actual fun rememberAccessibilityServiceState(
+    listenToTouchExplorationState: Boolean,
+    listenToSwitchAccessState: Boolean,
+): State<Boolean> = implementedInJetBrainsFork()
diff --git a/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/internal/BasicTooltip.jvmStubs.kt b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/internal/BasicTooltip.jvmStubs.kt
new file mode 100644
index 0000000..c72051a
--- /dev/null
+++ b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/internal/BasicTooltip.jvmStubs.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3.internal
+
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.TooltipState
+import androidx.compose.material3.implementedInJetBrainsFork
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.window.PopupPositionProvider
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+internal actual fun BasicTooltipBox(
+    positionProvider: PopupPositionProvider,
+    tooltip: @Composable () -> Unit,
+    state: TooltipState,
+    modifier: Modifier,
+    focusable: Boolean,
+    enableUserInput: Boolean,
+    content: @Composable () -> Unit
+): Unit = implementedInJetBrainsFork()
diff --git a/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/internal/CalendarModel.jvmStubs.kt b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/internal/CalendarModel.jvmStubs.kt
new file mode 100644
index 0000000..ab14c60
--- /dev/null
+++ b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/internal/CalendarModel.jvmStubs.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3.internal
+
+import androidx.compose.material3.CalendarLocale
+import androidx.compose.material3.implementedInJetBrainsFork
+
+internal actual fun createCalendarModel(locale: CalendarLocale): CalendarModel =
+    implementedInJetBrainsFork()
+
+internal actual fun formatWithSkeleton(
+    utcTimeMillis: Long,
+    skeleton: String,
+    locale: CalendarLocale,
+    cache: MutableMap<String, Any>
+): String = implementedInJetBrainsFork()
diff --git a/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/internal/DefaultPlatformTextStyle.jvmStubs.kt b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/internal/DefaultPlatformTextStyle.jvmStubs.kt
new file mode 100644
index 0000000..2a27f48
--- /dev/null
+++ b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/internal/DefaultPlatformTextStyle.jvmStubs.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3.internal
+
+import androidx.compose.material3.implementedInJetBrainsFork
+import androidx.compose.ui.text.PlatformTextStyle
+
+internal actual fun defaultPlatformTextStyle(): PlatformTextStyle? = implementedInJetBrainsFork()
diff --git a/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/internal/Strings.jvmStubs.kt b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/internal/Strings.jvmStubs.kt
new file mode 100644
index 0000000..8b30e91
--- /dev/null
+++ b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/internal/Strings.jvmStubs.kt
@@ -0,0 +1,102 @@
+/*
+ * 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.material3.internal
+
+import androidx.compose.material3.implementedInJetBrainsFork
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Immutable
+import androidx.compose.runtime.ReadOnlyComposable
+
+@Composable
+@ReadOnlyComposable
+internal actual fun getString(string: Strings): String = implementedInJetBrainsFork()
+
+@JvmInline
+@Immutable
+internal actual value class Strings constructor(val value: Int) {
+    actual companion object {
+        actual val NavigationMenu: Strings = implementedInJetBrainsFork()
+        actual val CloseDrawer: Strings = implementedInJetBrainsFork()
+        actual val CloseSheet: Strings = implementedInJetBrainsFork()
+        actual val DefaultErrorMessage: Strings = implementedInJetBrainsFork()
+        actual val SliderRangeStart: Strings = implementedInJetBrainsFork()
+        actual val SliderRangeEnd: Strings = implementedInJetBrainsFork()
+        actual val Dialog: Strings = implementedInJetBrainsFork()
+        actual val MenuExpanded: Strings = implementedInJetBrainsFork()
+        actual val MenuCollapsed: Strings = implementedInJetBrainsFork()
+        actual val SnackbarDismiss: Strings = implementedInJetBrainsFork()
+        actual val SearchBarSearch: Strings = implementedInJetBrainsFork()
+        actual val SuggestionsAvailable: Strings = implementedInJetBrainsFork()
+        actual val DatePickerTitle: Strings = implementedInJetBrainsFork()
+        actual val DatePickerHeadline: Strings = implementedInJetBrainsFork()
+        actual val DatePickerYearPickerPaneTitle: Strings = implementedInJetBrainsFork()
+        actual val DatePickerSwitchToYearSelection: Strings = implementedInJetBrainsFork()
+        actual val DatePickerSwitchToDaySelection: Strings = implementedInJetBrainsFork()
+        actual val DatePickerSwitchToNextMonth: Strings = implementedInJetBrainsFork()
+        actual val DatePickerSwitchToPreviousMonth: Strings = implementedInJetBrainsFork()
+        actual val DatePickerNavigateToYearDescription: Strings = implementedInJetBrainsFork()
+        actual val DatePickerHeadlineDescription: Strings = implementedInJetBrainsFork()
+        actual val DatePickerNoSelectionDescription: Strings = implementedInJetBrainsFork()
+        actual val DatePickerTodayDescription: Strings = implementedInJetBrainsFork()
+        actual val DatePickerScrollToShowLaterYears: Strings = implementedInJetBrainsFork()
+        actual val DatePickerScrollToShowEarlierYears: Strings = implementedInJetBrainsFork()
+        actual val DateInputTitle: Strings = implementedInJetBrainsFork()
+        actual val DateInputHeadline: Strings = implementedInJetBrainsFork()
+        actual val DateInputLabel: Strings = implementedInJetBrainsFork()
+        actual val DateInputHeadlineDescription: Strings = implementedInJetBrainsFork()
+        actual val DateInputNoInputDescription: Strings = implementedInJetBrainsFork()
+        actual val DateInputInvalidNotAllowed: Strings = implementedInJetBrainsFork()
+        actual val DateInputInvalidForPattern: Strings = implementedInJetBrainsFork()
+        actual val DateInputInvalidYearRange: Strings = implementedInJetBrainsFork()
+        actual val DatePickerSwitchToCalendarMode: Strings = implementedInJetBrainsFork()
+        actual val DatePickerSwitchToInputMode: Strings = implementedInJetBrainsFork()
+        actual val DateRangePickerTitle: Strings = implementedInJetBrainsFork()
+        actual val DateRangePickerStartHeadline: Strings = implementedInJetBrainsFork()
+        actual val DateRangePickerEndHeadline: Strings = implementedInJetBrainsFork()
+        actual val DateRangePickerScrollToShowNextMonth: Strings = implementedInJetBrainsFork()
+        actual val DateRangePickerScrollToShowPreviousMonth: Strings = implementedInJetBrainsFork()
+        actual val DateRangePickerDayInRange: Strings = implementedInJetBrainsFork()
+        actual val DateRangeInputTitle: Strings = implementedInJetBrainsFork()
+        actual val DateRangeInputInvalidRangeInput: Strings = implementedInJetBrainsFork()
+        actual val BottomSheetPaneTitle: Strings = implementedInJetBrainsFork()
+        actual val BottomSheetDragHandleDescription: Strings = implementedInJetBrainsFork()
+        actual val BottomSheetPartialExpandDescription: Strings = implementedInJetBrainsFork()
+        actual val BottomSheetDismissDescription: Strings = implementedInJetBrainsFork()
+        actual val BottomSheetExpandDescription: Strings = implementedInJetBrainsFork()
+        actual val TooltipLongPressLabel: Strings = implementedInJetBrainsFork()
+        actual val TimePickerAM: Strings = implementedInJetBrainsFork()
+        actual val TimePickerPM: Strings = implementedInJetBrainsFork()
+        actual val TimePickerPeriodToggle: Strings = implementedInJetBrainsFork()
+        actual val TimePickerHourSelection: Strings = implementedInJetBrainsFork()
+        actual val TimePickerMinuteSelection: Strings = implementedInJetBrainsFork()
+        actual val TimePickerHourSuffix: Strings = implementedInJetBrainsFork()
+        actual val TimePicker24HourSuffix: Strings = implementedInJetBrainsFork()
+        actual val TimePickerMinuteSuffix: Strings = implementedInJetBrainsFork()
+        actual val TimePickerHour: Strings = implementedInJetBrainsFork()
+        actual val TimePickerMinute: Strings = implementedInJetBrainsFork()
+        actual val TimePickerHourTextField: Strings = implementedInJetBrainsFork()
+        actual val TimePickerMinuteTextField: Strings = implementedInJetBrainsFork()
+        actual val TooltipPaneDescription: Strings = implementedInJetBrainsFork()
+        actual val ExposedDropdownMenu: Strings = implementedInJetBrainsFork()
+        actual val ToggleDropdownMenu: Strings = implementedInJetBrainsFork()
+    }
+}
+
+@Composable
+@ReadOnlyComposable
+internal actual fun getString(string: Strings, vararg formatArgs: Any): String =
+    implementedInJetBrainsFork()
diff --git a/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/internal/SystemBarsDefaultInsets.jvmStubs.kt b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/internal/SystemBarsDefaultInsets.jvmStubs.kt
new file mode 100644
index 0000000..5c6bf7d
--- /dev/null
+++ b/compose/material3/material3/src/jvmStubsMain/kotlin/androidx/compose/material3/internal/SystemBarsDefaultInsets.jvmStubs.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3.internal
+
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.material3.implementedInJetBrainsFork
+import androidx.compose.runtime.Composable
+
+internal actual val WindowInsets.Companion.systemBarsForVisualComponents: WindowInsets
+    @Composable get() = implementedInJetBrainsFork()
diff --git a/compose/material3/material3/src/skikoMain/kotlin/androidx/compose/material3/AlertDialog.skiko.kt b/compose/material3/material3/src/skikoMain/kotlin/androidx/compose/material3/AlertDialog.skiko.kt
deleted file mode 100644
index da00d6f..0000000
--- a/compose/material3/material3/src/skikoMain/kotlin/androidx/compose/material3/AlertDialog.skiko.kt
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material3
-
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.Shape
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.window.DialogProperties
-
-// Keep expect/actual for maintain binary compatibility.
-// `@file:JvmName` doesn't work here because Android and Desktop were published with different names
-// Please note that binary compatibility for Desktop is tracked only in JetBrains fork
-
-@Composable
-actual fun AlertDialog(
-    onDismissRequest: () -> Unit,
-    confirmButton: @Composable () -> Unit,
-    modifier: Modifier,
-    dismissButton: @Composable (() -> Unit)?,
-    icon: @Composable (() -> Unit)?,
-    title: @Composable (() -> Unit)?,
-    text: @Composable (() -> Unit)?,
-    shape: Shape,
-    containerColor: Color,
-    iconContentColor: Color,
-    titleContentColor: Color,
-    textContentColor: Color,
-    tonalElevation: Dp,
-    properties: DialogProperties
-): Unit =
-    AlertDialogImpl(
-        onDismissRequest = onDismissRequest,
-        confirmButton = confirmButton,
-        modifier = modifier,
-        dismissButton = dismissButton,
-        icon = icon,
-        title = title,
-        text = text,
-        shape = shape,
-        containerColor = containerColor,
-        iconContentColor = iconContentColor,
-        titleContentColor = titleContentColor,
-        textContentColor = textContentColor,
-        tonalElevation = tonalElevation,
-        properties = properties
-    )
diff --git a/compose/material3/material3/src/skikoMain/kotlin/androidx/compose/material3/ModalBottomSheet.skiko.kt b/compose/material3/material3/src/skikoMain/kotlin/androidx/compose/material3/ModalBottomSheet.skiko.kt
deleted file mode 100644
index 15778bb..0000000
--- a/compose/material3/material3/src/skikoMain/kotlin/androidx/compose/material3/ModalBottomSheet.skiko.kt
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material3
-
-import androidx.compose.animation.core.Animatable
-import androidx.compose.animation.core.AnimationVector1D
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.Immutable
-import androidx.compose.ui.window.Dialog
-import androidx.compose.ui.window.DialogProperties
-
-@Immutable
-@ExperimentalMaterial3Api
-actual class ModalBottomSheetProperties
-actual constructor(
-    actual val shouldDismissOnBackPress: Boolean,
-) {
-    override fun equals(other: Any?): Boolean {
-        if (this === other) return true
-        if (other !is ModalBottomSheetProperties) return false
-
-        return true
-    }
-
-    override fun hashCode(): Int {
-        var result = shouldDismissOnBackPress.hashCode()
-        return result
-    }
-}
-
-@Immutable
-@ExperimentalMaterial3Api
-actual object ModalBottomSheetDefaults {
-    actual val properties = ModalBottomSheetProperties()
-}
-
-@OptIn(ExperimentalMaterial3Api::class)
-@Composable
-internal actual fun ModalBottomSheetDialog(
-    onDismissRequest: () -> Unit,
-    properties: ModalBottomSheetProperties,
-    predictiveBackProgress: Animatable<Float, AnimationVector1D>,
-    content: @Composable () -> Unit
-) {
-    Dialog(
-        onDismissRequest = onDismissRequest,
-        properties = DialogProperties(dismissOnBackPress = properties.shouldDismissOnBackPress),
-        content = content
-    )
-}
diff --git a/compose/material3/material3/src/skikoMain/kotlin/androidx/compose/material3/SkikoMenu.skiko.kt b/compose/material3/material3/src/skikoMain/kotlin/androidx/compose/material3/SkikoMenu.skiko.kt
deleted file mode 100644
index d0d080b..0000000
--- a/compose/material3/material3/src/skikoMain/kotlin/androidx/compose/material3/SkikoMenu.skiko.kt
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material3
-
-import androidx.compose.animation.core.MutableTransitionState
-import androidx.compose.foundation.BorderStroke
-import androidx.compose.foundation.ScrollState
-import androidx.compose.foundation.interaction.MutableInteractionSource
-import androidx.compose.foundation.layout.ColumnScope
-import androidx.compose.foundation.layout.PaddingValues
-import androidx.compose.foundation.rememberScrollState
-import androidx.compose.material3.internal.DropdownMenuPositionProvider
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.ExperimentalComposeUiApi
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.focus.FocusDirection
-import androidx.compose.ui.focus.FocusManager
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.Shape
-import androidx.compose.ui.graphics.TransformOrigin
-import androidx.compose.ui.input.InputMode
-import androidx.compose.ui.input.InputModeManager
-import androidx.compose.ui.input.key.Key
-import androidx.compose.ui.input.key.KeyEvent
-import androidx.compose.ui.input.key.KeyEventType
-import androidx.compose.ui.input.key.key
-import androidx.compose.ui.input.key.type
-import androidx.compose.ui.platform.LocalDensity
-import androidx.compose.ui.platform.LocalFocusManager
-import androidx.compose.ui.platform.LocalInputModeManager
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.DpOffset
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.window.Popup
-import androidx.compose.ui.window.PopupProperties
-
-@Deprecated(
-    "Replaced by DropdownMenu with properties parameter",
-    ReplaceWith(
-        "DropdownMenu(expanded, onDismissRequest, modifier, offset, " +
-            "androidx.compose.ui.window.PopupProperties(focusable = focusable), " +
-            "content)"
-    ),
-    level = DeprecationLevel.HIDDEN
-)
-@Suppress("ModifierParameter")
-@Composable
-fun DropdownMenu(
-    expanded: Boolean,
-    onDismissRequest: () -> Unit,
-    focusable: Boolean = true,
-    modifier: Modifier = Modifier,
-    offset: DpOffset = DpOffset(0.dp, 0.dp),
-    content: @Composable ColumnScope.() -> Unit
-) =
-    DropdownMenu(
-        expanded = expanded,
-        onDismissRequest = onDismissRequest,
-        modifier = modifier,
-        offset = offset,
-        properties = PopupProperties(focusable = focusable),
-        content = content
-    )
-
-// Workaround for `Overload resolution ambiguity` between old and new overload.
-@Deprecated("Maintained for binary compatibility", level = DeprecationLevel.HIDDEN)
-@Composable
-fun DropdownMenu(
-    expanded: Boolean,
-    onDismissRequest: () -> Unit,
-    modifier: Modifier = Modifier,
-    offset: DpOffset = DpOffset(0.dp, 0.dp),
-    content: @Composable ColumnScope.() -> Unit
-) =
-    DropdownMenu(
-        expanded = expanded,
-        onDismissRequest = onDismissRequest,
-        modifier = modifier,
-        offset = offset,
-        properties = PopupProperties(focusable = true),
-        content = content
-    )
-
-@Composable
-actual fun DropdownMenu(
-    expanded: Boolean,
-    onDismissRequest: () -> Unit,
-    modifier: Modifier,
-    offset: DpOffset,
-    scrollState: ScrollState,
-    properties: PopupProperties,
-    shape: Shape,
-    containerColor: Color,
-    tonalElevation: Dp,
-    shadowElevation: Dp,
-    border: BorderStroke?,
-    content: @Composable ColumnScope.() -> Unit
-) {
-    val expandedState = remember { MutableTransitionState(false) }
-    expandedState.targetState = expanded
-
-    if (expandedState.currentState || expandedState.targetState) {
-        val transformOriginState = remember { mutableStateOf(TransformOrigin.Center) }
-        val density = LocalDensity.current
-        val popupPositionProvider =
-            remember(offset, density) {
-                DropdownMenuPositionProvider(offset, density) { parentBounds, menuBounds ->
-                    transformOriginState.value = calculateTransformOrigin(parentBounds, menuBounds)
-                }
-            }
-
-        var focusManager: FocusManager? by mutableStateOf(null)
-        var inputModeManager: InputModeManager? by mutableStateOf(null)
-        Popup(
-            onDismissRequest = onDismissRequest,
-            popupPositionProvider = popupPositionProvider,
-            properties = properties,
-            onKeyEvent = { handlePopupOnKeyEvent(it, focusManager, inputModeManager) },
-        ) {
-            focusManager = LocalFocusManager.current
-            inputModeManager = LocalInputModeManager.current
-
-            DropdownMenuContent(
-                expandedState = expandedState,
-                transformOriginState = transformOriginState,
-                scrollState = scrollState,
-                shape = shape,
-                containerColor = containerColor,
-                tonalElevation = tonalElevation,
-                shadowElevation = shadowElevation,
-                border = border,
-                modifier = modifier,
-                content = content,
-            )
-        }
-    }
-}
-
-@Deprecated(
-    level = DeprecationLevel.HIDDEN,
-    replaceWith =
-        ReplaceWith(
-            expression =
-                "DropdownMenu(\n" +
-                    "    expanded = expanded,\n" +
-                    "    onDismissRequest = onDismissRequest,\n" +
-                    "    modifier = modifier,\n" +
-                    "    offset = offset,\n" +
-                    "    scrollState = scrollState,\n" +
-                    "    properties = properties,\n" +
-                    "    shape = MenuDefaults.shape,\n" +
-                    "    containerColor = MenuDefaults.containerColor,\n" +
-                    "    tonalElevation = MenuDefaults.TonalElevation,\n" +
-                    "    shadowElevation = MenuDefaults.ShadowElevation,\n" +
-                    "    border = null,\n" +
-                    "    content = content,\n" +
-                    ")",
-        ),
-    message =
-        "Maintained for binary compatibility. Use overload with parameters for shape, " +
-            "color, elevation, and border."
-)
-@Composable
-fun DropdownMenu(
-    expanded: Boolean,
-    onDismissRequest: () -> Unit,
-    modifier: Modifier = Modifier,
-    offset: DpOffset = DpOffset(0.dp, 0.dp),
-    scrollState: ScrollState = rememberScrollState(),
-    properties: PopupProperties = PopupProperties(focusable = true),
-    content: @Composable ColumnScope.() -> Unit
-) =
-    DropdownMenu(
-        expanded = expanded,
-        onDismissRequest = onDismissRequest,
-        modifier = modifier,
-        offset = offset,
-        scrollState = scrollState,
-        properties = properties,
-        shape = MenuDefaults.shape,
-        containerColor = MenuDefaults.containerColor,
-        tonalElevation = MenuDefaults.TonalElevation,
-        shadowElevation = MenuDefaults.ShadowElevation,
-        border = null,
-        content = content,
-    )
-
-@Suppress("ModifierParameter")
-@OptIn(ExperimentalMaterial3Api::class)
-@Deprecated(
-    level = DeprecationLevel.HIDDEN,
-    replaceWith =
-        ReplaceWith(
-            expression =
-                "DropdownMenu(expanded,onDismissRequest, modifier, offset, " +
-                    "rememberScrollState(), properties, content)",
-            "androidx.compose.foundation.rememberScrollState"
-        ),
-    message = "Replaced by a DropdownMenu function with a ScrollState parameter"
-)
-@Composable
-fun DropdownMenu(
-    expanded: Boolean,
-    onDismissRequest: () -> Unit,
-    modifier: Modifier,
-    offset: DpOffset,
-    properties: PopupProperties,
-    content: @Composable ColumnScope.() -> Unit
-) =
-    DropdownMenu(
-        expanded = expanded,
-        onDismissRequest = onDismissRequest,
-        modifier = modifier,
-        offset = offset,
-        scrollState = rememberScrollState(),
-        properties = properties,
-        content = content
-    )
-
-@Composable
-actual fun DropdownMenuItem(
-    text: @Composable () -> Unit,
-    onClick: () -> Unit,
-    modifier: Modifier,
-    leadingIcon: @Composable (() -> Unit)?,
-    trailingIcon: @Composable (() -> Unit)?,
-    enabled: Boolean,
-    colors: MenuItemColors,
-    contentPadding: PaddingValues,
-    interactionSource: MutableInteractionSource?,
-) {
-    DropdownMenuItemContent(
-        text = text,
-        onClick = onClick,
-        modifier = modifier,
-        leadingIcon = leadingIcon,
-        trailingIcon = trailingIcon,
-        enabled = enabled,
-        colors = colors,
-        contentPadding = contentPadding,
-        interactionSource = interactionSource,
-    )
-}
-
-internal actual val DefaultMenuProperties =
-    PopupProperties(
-        focusable = true
-        // TODO: Add a flag to not block clicks outside while being focusable
-    )
-
-@OptIn(ExperimentalComposeUiApi::class)
-private fun handlePopupOnKeyEvent(
-    keyEvent: KeyEvent,
-    focusManager: FocusManager?,
-    inputModeManager: InputModeManager?
-): Boolean =
-    if (keyEvent.type == KeyEventType.KeyDown) {
-        when (keyEvent.key) {
-            Key.DirectionDown -> {
-                inputModeManager?.requestInputMode(InputMode.Keyboard)
-                focusManager?.moveFocus(FocusDirection.Next)
-                true
-            }
-            Key.DirectionUp -> {
-                inputModeManager?.requestInputMode(InputMode.Keyboard)
-                focusManager?.moveFocus(FocusDirection.Previous)
-                true
-            }
-            else -> false
-        }
-    } else {
-        false
-    }
diff --git a/compose/runtime/OWNERS b/compose/runtime/OWNERS
index 1d23419..8db12da 100644
--- a/compose/runtime/OWNERS
+++ b/compose/runtime/OWNERS
@@ -1,5 +1,4 @@
 # Bug component: 343210
[email protected]
 [email protected]
 [email protected]
 [email protected]
diff --git a/compose/runtime/runtime-lint/src/main/java/androidx/compose/runtime/lint/ProduceStateDetector.kt b/compose/runtime/runtime-lint/src/main/java/androidx/compose/runtime/lint/ProduceStateDetector.kt
index 84099fd..87dc3587 100644
--- a/compose/runtime/runtime-lint/src/main/java/androidx/compose/runtime/lint/ProduceStateDetector.kt
+++ b/compose/runtime/runtime-lint/src/main/java/androidx/compose/runtime/lint/ProduceStateDetector.kt
@@ -32,8 +32,13 @@
 import com.android.tools.lint.detector.api.SourceCodeScanner
 import com.intellij.psi.PsiMethod
 import java.util.EnumSet
+import org.jetbrains.uast.UBinaryExpression
 import org.jetbrains.uast.UCallExpression
+import org.jetbrains.uast.UExpression
+import org.jetbrains.uast.UMultiResolvable
+import org.jetbrains.uast.UQualifiedReferenceExpression
 import org.jetbrains.uast.USimpleNameReferenceExpression
+import org.jetbrains.uast.UastBinaryOperator
 import org.jetbrains.uast.getParameterForArgument
 import org.jetbrains.uast.tryResolve
 import org.jetbrains.uast.visitor.AbstractUastVisitor
@@ -72,7 +77,7 @@
                      * false positives.
                      */
                     override fun visitCallExpression(node: UCallExpression): Boolean {
-                        val resolvedMethod = node.resolve() ?: return false
+                        val resolvedMethod = node.resolve() ?: return referencesReceiver
                         return resolvedMethod.parameterList.parameters.any { parameter ->
                             val type = parameter.type
 
@@ -94,24 +99,57 @@
                     }
 
                     /**
-                     * Visit any simple name reference expressions to see if there is a reference to
-                     * `value` that resolves to a call to MutableState#setValue.
+                     * Visit binary operator to see if
+                     * 1) it is an assign operator;
+                     * 2) its left operand refers to 'value'; and
+                     * 3) it is resolved to a call to MutableState#setValue.
                      */
-                    override fun visitSimpleNameReferenceExpression(
-                        node: USimpleNameReferenceExpression
-                    ): Boolean {
-                        if (node.identifier != "value") return false
-                        val resolvedMethod = node.tryResolve() as? PsiMethod ?: return false
+                    override fun visitBinaryExpression(node: UBinaryExpression): Boolean {
+                        // =, +=, etc.
+                        if (node.operator !is UastBinaryOperator.AssignOperator) {
+                            return callsSetValue
+                        }
+                        // this.value =, value +=, etc.
+                        if (node.leftOperand.rightMostNameReference()?.identifier != "value") {
+                            return callsSetValue
+                        }
+                        // NB: we can't use node.resolveOperator() during the migration,
+                        // since K1 / K2 UAST behaviors mismatch.
+                        // `multiResolve()` literally encompasses all possible resolution
+                        // results for (compound, overridden) operators.
+                        val resolvedMethods =
+                            (node as? UMultiResolvable)?.multiResolve() ?: return callsSetValue
                         if (
-                            resolvedMethod.name == "setValue" &&
-                                resolvedMethod.containingClass?.inheritsFrom(
-                                    Names.Runtime.MutableState
-                                ) == true
+                            resolvedMethods.any {
+                                (it.element as? PsiMethod).isValueAccessorFromMutableState()
+                            }
                         ) {
                             callsSetValue = true
+                            return true
+                        }
+                        // TODO(b/34684249): revisit this fallback option after restoring
+                        //  K2 UAST binary resolution to allow only setter, not getter
+                        val resolvedOperand = node.leftOperand.tryResolve()
+                        if ((resolvedOperand as? PsiMethod).isValueAccessorFromMutableState()) {
+                            callsSetValue = true
                         }
                         return callsSetValue
                     }
+
+                    private tailrec fun UExpression.rightMostNameReference():
+                        USimpleNameReferenceExpression? {
+                        return when (this) {
+                            is USimpleNameReferenceExpression -> this
+                            is UQualifiedReferenceExpression ->
+                                this.selector.rightMostNameReference()
+                            else -> null
+                        }
+                    }
+
+                    private fun PsiMethod?.isValueAccessorFromMutableState(): Boolean =
+                        this != null &&
+                            (name == "setValue" || name == "getValue") &&
+                            containingClass?.inheritsFrom(Names.Runtime.MutableState) == true
                 }
             )
 
diff --git a/compose/runtime/runtime-lint/src/test/java/androidx/compose/runtime/lint/ProduceStateDetectorTest.kt b/compose/runtime/runtime-lint/src/test/java/androidx/compose/runtime/lint/ProduceStateDetectorTest.kt
index afb41b5..7428692 100644
--- a/compose/runtime/runtime-lint/src/test/java/androidx/compose/runtime/lint/ProduceStateDetectorTest.kt
+++ b/compose/runtime/runtime-lint/src/test/java/androidx/compose/runtime/lint/ProduceStateDetectorTest.kt
@@ -114,6 +114,9 @@
                     produceState(true, true) {
                         this.value = true
                     }
+                    produceState("Hi", "Any?") {
+                        value += ", world"
+                    }
                     produceState(true, true) {
                         doSomethingWithScope()
                     }
diff --git a/compose/runtime/runtime-livedata/build.gradle b/compose/runtime/runtime-livedata/build.gradle
index 2655560..3efb105 100644
--- a/compose/runtime/runtime-livedata/build.gradle
+++ b/compose/runtime/runtime-livedata/build.gradle
@@ -37,7 +37,7 @@
     api(project(":compose:runtime:runtime"))
     api("androidx.lifecycle:lifecycle-livedata:2.6.1")
     api("androidx.lifecycle:lifecycle-runtime:2.6.1")
-    api("androidx.lifecycle:lifecycle-runtime-compose:2.8.2")
+    api("androidx.lifecycle:lifecycle-runtime-compose:2.8.3")
 
     androidTestImplementation(projectOrArtifact(":compose:ui:ui-test-junit4"))
     androidTestImplementation(project(":compose:test-utils"))
diff --git a/compose/runtime/runtime-saveable/build.gradle b/compose/runtime/runtime-saveable/build.gradle
index 74e95cb..45c128e 100644
--- a/compose/runtime/runtime-saveable/build.gradle
+++ b/compose/runtime/runtime-saveable/build.gradle
@@ -32,7 +32,8 @@
 
 androidXMultiplatform {
     android()
-    desktop()
+    jvmStubs()
+    linuxX64Stubs()
 
     defaultPlatform(PlatformIdentifier.ANDROID)
 
@@ -40,8 +41,7 @@
         commonMain {
             dependencies {
                 implementation(libs.kotlinStdlibCommon)
-
-                api project(":compose:runtime:runtime")
+                api(project(":compose:runtime:runtime"))
             }
         }
 
@@ -56,33 +56,26 @@
             }
         }
 
-
         androidMain {
             dependsOn(jvmMain)
             dependencies {
                 implementation(libs.kotlinStdlib)
-                api "androidx.annotation:annotation:1.1.0"
+                api("androidx.annotation:annotation:1.1.0")
             }
         }
 
-        desktopMain {
+        jvmStubsMain {
             dependsOn(jvmMain)
         }
 
-        jvmTest {
+        androidInstrumentedTest {
             dependsOn(commonTest)
             dependencies {
-            }
-        }
-
-        androidInstrumentedTest {
-            dependsOn(jvmTest)
-            dependencies {
-                implementation project(':compose:ui:ui')
-                implementation project(":compose:ui:ui-test-junit4")
-                implementation project(":compose:test-utils")
-                implementation "androidx.fragment:fragment:1.3.0"
-                implementation "androidx.activity:activity-compose:1.7.0"
+                implementation(project(":compose:ui:ui"))
+                implementation(project(":compose:ui:ui-test-junit4"))
+                implementation(project(":compose:test-utils"))
+                implementation("androidx.fragment:fragment:1.3.0")
+                implementation("androidx.activity:activity-compose:1.7.0")
                 implementation(libs.testUiautomator)
                 implementation(libs.testCore)
                 implementation(libs.testRules)
@@ -96,7 +89,7 @@
         }
 
         androidUnitTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(libs.testRules)
                 implementation(libs.testRunner)
@@ -104,10 +97,6 @@
                 implementation(libs.truth)
             }
         }
-
-        desktopTest {
-            dependsOn(jvmTest)
-        }
     }
 }
 
diff --git a/compose/runtime/runtime-test-utils/build.gradle b/compose/runtime/runtime-test-utils/build.gradle
index 227b4f8..141b480 100644
--- a/compose/runtime/runtime-test-utils/build.gradle
+++ b/compose/runtime/runtime-test-utils/build.gradle
@@ -25,7 +25,8 @@
 
 androidXMultiplatform {
     android()
-    desktop()
+    jvmStubs()
+    linuxX64Stubs()
 
     defaultPlatform(PlatformIdentifier.ANDROID)
 
@@ -39,8 +40,6 @@
                 implementation(libs.kotlinReflect)
             }
         }
-        androidMain.dependencies {
-        }
 
         jvmMain {
             dependsOn(commonMain)
@@ -54,7 +53,7 @@
             }
         }
 
-        desktopMain {
+        jvmStubsMain {
             dependsOn(jvmMain)
             dependencies {
             }
diff --git a/compose/runtime/runtime-test-utils/src/commonMain/kotlin/androidx/compose/runtime/mock/SynchronizedObject.kt b/compose/runtime/runtime-test-utils/src/commonMain/kotlin/androidx/compose/runtime/mock/SynchronizedObject.kt
new file mode 100644
index 0000000..0337a1e
--- /dev/null
+++ b/compose/runtime/runtime-test-utils/src/commonMain/kotlin/androidx/compose/runtime/mock/SynchronizedObject.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.runtime.mock
+
+internal expect class SynchronizedObject()
+
+@PublishedApi
+internal expect inline fun <R> synchronized(lock: SynchronizedObject, block: () -> R): R
diff --git a/compose/runtime/runtime-test-utils/src/commonMain/kotlin/androidx/compose/runtime/mock/TestMonotonicFrameClock.kt b/compose/runtime/runtime-test-utils/src/commonMain/kotlin/androidx/compose/runtime/mock/TestMonotonicFrameClock.kt
index 23fb7cb..52d8753 100644
--- a/compose/runtime/runtime-test-utils/src/commonMain/kotlin/androidx/compose/runtime/mock/TestMonotonicFrameClock.kt
+++ b/compose/runtime/runtime-test-utils/src/commonMain/kotlin/androidx/compose/runtime/mock/TestMonotonicFrameClock.kt
@@ -72,7 +72,7 @@
     @get:Suppress("MethodNameUnits") // Nanos for high-precision animation clocks
     val frameDelayNanos: Long = DefaultFrameDelay
 ) : MonotonicFrameClock {
-    private val lock = Any()
+    private val lock = SynchronizedObject()
     private val awaiters = mutableListOf<Awaiter<*>>()
     private var posted = false
 
diff --git a/compose/runtime/runtime-test-utils/src/jvmMain/kotlin/androidx/compose/runtime/mock/SynchronizedObject.jvm.kt b/compose/runtime/runtime-test-utils/src/jvmMain/kotlin/androidx/compose/runtime/mock/SynchronizedObject.jvm.kt
new file mode 100644
index 0000000..ef04295
--- /dev/null
+++ b/compose/runtime/runtime-test-utils/src/jvmMain/kotlin/androidx/compose/runtime/mock/SynchronizedObject.jvm.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:JvmName("ActualJvm_jvmKt")
+@file:JvmMultifileClass
+
+package androidx.compose.runtime.mock
+
+@Suppress("ACTUAL_WITHOUT_EXPECT") // https://youtrack.jetbrains.com/issue/KT-37316
+internal actual typealias SynchronizedObject = Any
+
+@PublishedApi
+internal actual inline fun <R> synchronized(lock: SynchronizedObject, block: () -> R): R =
+    kotlin.synchronized(lock, block)
diff --git a/compose/runtime/runtime-test-utils/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/mock/SynchronizedObject.linuxx64Stubs.kt b/compose/runtime/runtime-test-utils/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/mock/SynchronizedObject.linuxx64Stubs.kt
new file mode 100644
index 0000000..bb4e1d9
--- /dev/null
+++ b/compose/runtime/runtime-test-utils/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/mock/SynchronizedObject.linuxx64Stubs.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.runtime.mock
+
+@Suppress("ACTUAL_WITHOUT_EXPECT") // https://youtrack.jetbrains.com/issue/KT-37316
+internal actual typealias SynchronizedObject = Any
+
+@PublishedApi
+internal actual inline fun <R> synchronized(lock: SynchronizedObject, block: () -> R): R = block()
diff --git a/compose/runtime/runtime/api/current.txt b/compose/runtime/runtime/api/current.txt
index 374319c..ee38e7d 100644
--- a/compose/runtime/runtime/api/current.txt
+++ b/compose/runtime/runtime/api/current.txt
@@ -184,7 +184,7 @@
 
   public static final class Composer.Companion {
     method public Object getEmpty();
-    method @SuppressCompatibility @androidx.compose.runtime.InternalComposeTracingApi public void setTracer(androidx.compose.runtime.CompositionTracer tracer);
+    method @SuppressCompatibility @androidx.compose.runtime.InternalComposeTracingApi public void setTracer(androidx.compose.runtime.CompositionTracer? tracer);
     property public final Object Empty;
   }
 
@@ -1084,7 +1084,7 @@
   }
 
   @SuppressCompatibility @androidx.compose.runtime.ExperimentalComposeRuntimeApi public interface CompositionObserver {
-    method public void onBeginComposition(androidx.compose.runtime.Composition composition, java.util.Map<androidx.compose.runtime.RecomposeScope,? extends java.util.Set<?>?> invalidationMap);
+    method public void onBeginComposition(androidx.compose.runtime.Composition composition, java.util.Map<androidx.compose.runtime.RecomposeScope,? extends java.util.Set<?>> invalidationMap);
     method public void onEndComposition(androidx.compose.runtime.Composition composition);
   }
 
diff --git a/compose/runtime/runtime/api/restricted_current.txt b/compose/runtime/runtime/api/restricted_current.txt
index b8aa3d7..00784cf 100644
--- a/compose/runtime/runtime/api/restricted_current.txt
+++ b/compose/runtime/runtime/api/restricted_current.txt
@@ -189,7 +189,7 @@
 
   public static final class Composer.Companion {
     method public Object getEmpty();
-    method @SuppressCompatibility @androidx.compose.runtime.InternalComposeTracingApi public void setTracer(androidx.compose.runtime.CompositionTracer tracer);
+    method @SuppressCompatibility @androidx.compose.runtime.InternalComposeTracingApi public void setTracer(androidx.compose.runtime.CompositionTracer? tracer);
     property public final Object Empty;
   }
 
@@ -1135,7 +1135,7 @@
   }
 
   @SuppressCompatibility @androidx.compose.runtime.ExperimentalComposeRuntimeApi public interface CompositionObserver {
-    method public void onBeginComposition(androidx.compose.runtime.Composition composition, java.util.Map<androidx.compose.runtime.RecomposeScope,? extends java.util.Set<?>?> invalidationMap);
+    method public void onBeginComposition(androidx.compose.runtime.Composition composition, java.util.Map<androidx.compose.runtime.RecomposeScope,? extends java.util.Set<?>> invalidationMap);
     method public void onEndComposition(androidx.compose.runtime.Composition composition);
   }
 
diff --git a/compose/runtime/runtime/build.gradle b/compose/runtime/runtime/build.gradle
index 97976e6..aee37a5 100644
--- a/compose/runtime/runtime/build.gradle
+++ b/compose/runtime/runtime/build.gradle
@@ -33,7 +33,8 @@
 
 androidXMultiplatform {
     android()
-    desktop()
+    jvmStubs()
+    linuxX64Stubs()
 
     defaultPlatform(PlatformIdentifier.ANDROID)
 
@@ -42,7 +43,7 @@
             dependencies {
                 implementation(libs.kotlinStdlibCommon)
                 implementation(libs.kotlinCoroutinesCore)
-                implementation("androidx.collection:collection:1.4.0")
+                implementation(project(":collection:collection"))
             }
         }
 
@@ -110,14 +111,17 @@
             dependsOn(commonMain)
         }
 
-        desktopMain {
+        jvmStubsMain {
             dependsOn(jvmMain)
             dependsOn(nonAndroidMain)
         }
 
-        desktopTest {
+        jvmStubsTest {
             dependsOn(jvmTest)
-            dependsOn(nonEmulatorJvmTest)
+        }
+
+        linuxx64StubsMain {
+            dependsOn(nonAndroidMain)
         }
     }
 }
diff --git a/compose/runtime/runtime/integration-tests/build.gradle b/compose/runtime/runtime/integration-tests/build.gradle
index be189bd..588e594 100644
--- a/compose/runtime/runtime/integration-tests/build.gradle
+++ b/compose/runtime/runtime/integration-tests/build.gradle
@@ -31,7 +31,6 @@
 
 androidXMultiplatform {
     android()
-    desktop()
 
     sourceSets {
         commonMain {
@@ -66,13 +65,6 @@
             }
         }
 
-        desktopMain {
-            dependsOn(jvmMain)
-            dependencies {
-                api(libs.kotlinCoroutinesSwing)
-            }
-        }
-
         jvmTest {
             dependsOn(commonTest)
             dependencies {
@@ -97,10 +89,6 @@
         androidUnitTest {
             dependsOn(jvmTest)
         }
-
-        desktopTest {
-            dependsOn(jvmTest)
-        }
     }
 }
 
diff --git a/compose/runtime/runtime/integration-tests/src/androidInstrumentedTest/kotlin/androidx/compose/runtime/AndroidCompositionObserverTests.kt b/compose/runtime/runtime/integration-tests/src/androidInstrumentedTest/kotlin/androidx/compose/runtime/AndroidCompositionObserverTests.kt
index 38d41aa..48befe5 100644
--- a/compose/runtime/runtime/integration-tests/src/androidInstrumentedTest/kotlin/androidx/compose/runtime/AndroidCompositionObserverTests.kt
+++ b/compose/runtime/runtime/integration-tests/src/androidInstrumentedTest/kotlin/androidx/compose/runtime/AndroidCompositionObserverTests.kt
@@ -45,7 +45,7 @@
                         object : CompositionObserver {
                             override fun onBeginComposition(
                                 composition: Composition,
-                                invalidationMap: Map<RecomposeScope, Set<Any>?>
+                                invalidationMap: Map<RecomposeScope, Set<Any>>
                             ) {}
 
                             override fun onEndComposition(composition: Composition) {}
diff --git a/compose/runtime/runtime/src/androidMain/kotlin/androidx/compose/runtime/collection/ActualIntMap.android.kt b/compose/runtime/runtime/src/androidMain/kotlin/androidx/compose/runtime/collection/ActualIntMap.android.kt
deleted file mode 100644
index 1f894ed..0000000
--- a/compose/runtime/runtime/src/androidMain/kotlin/androidx/compose/runtime/collection/ActualIntMap.android.kt
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.runtime.collection
-
-import android.util.SparseArray
-
-internal actual class IntMap<E>
-private constructor(private val sparseArray: android.util.SparseArray<E>) {
-
-    actual constructor(initialCapacity: Int) : this(SparseArray(initialCapacity))
-
-    /** True if this map contains key */
-    actual operator fun contains(key: Int): Boolean = sparseArray.indexOfKey(key) >= 0
-
-    /** Get [key] or null */
-    actual operator fun get(key: Int): E? = sparseArray[key]
-
-    /** Get [key] or [valueIfAbsent] */
-    actual fun get(key: Int, valueIfAbsent: E): E = sparseArray.get(key, valueIfAbsent)
-
-    /** Set [key] to [value] */
-    actual operator fun set(key: Int, value: E) = sparseArray.put(key, value)
-
-    /**
-     * Remove key, if it exists
-     *
-     * Otherwise no op
-     */
-    actual fun remove(key: Int) = sparseArray.remove(key)
-
-    /** Clear this map */
-    actual fun clear() = sparseArray.clear()
-
-    /** Current count of values */
-    actual val size: Int
-        get() = sparseArray.size()
-}
-
-// filename is not allowed if only a class is declared
-private val allowFilename = 0
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 dcd4eae..96121f1 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
@@ -30,7 +30,6 @@
 import androidx.compose.runtime.changelist.ChangeList
 import androidx.compose.runtime.changelist.ComposerChangeListWriter
 import androidx.compose.runtime.changelist.FixupList
-import androidx.compose.runtime.collection.IntMap
 import androidx.compose.runtime.collection.ScopeMap
 import androidx.compose.runtime.internal.IntRef
 import androidx.compose.runtime.internal.invokeComposable
@@ -1129,7 +1128,7 @@
          * recompositions.
          */
         @InternalComposeTracingApi
-        fun setTracer(tracer: CompositionTracer) {
+        fun setTracer(tracer: CompositionTracer?) {
             compositionTracer = tracer
         }
     }
@@ -1296,7 +1295,7 @@
     private val entersStack = IntStack()
     private var parentProvider: PersistentCompositionLocalMap =
         persistentCompositionLocalHashMapOf()
-    private var providerUpdates: IntMap<PersistentCompositionLocalMap>? = null
+    private var providerUpdates: MutableIntObjectMap<PersistentCompositionLocalMap>? = null
     private var providersInvalid = false
     private val providersInvalidStack = IntStack()
     private var reusing = false
@@ -2203,7 +2202,7 @@
         val providerUpdates =
             providerUpdates
                 ?: run {
-                    val newProviderUpdates = IntMap<PersistentCompositionLocalMap>()
+                    val newProviderUpdates = MutableIntObjectMap<PersistentCompositionLocalMap>()
                     this.providerUpdates = newProviderUpdates
                     newProviderUpdates
                 }
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composition.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composition.kt
index 6f8f20a..77e4f1f 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composition.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composition.kt
@@ -678,7 +678,7 @@
                         @Suppress("UNCHECKED_CAST")
                         observer.onBeginComposition(
                             this,
-                            invalidations.asMap() as Map<RecomposeScope, Set<Any>?>
+                            invalidations.asMap() as Map<RecomposeScope, Set<Any>>
                         )
                     }
                     composer.composeContent(invalidations, content)
@@ -889,7 +889,7 @@
                     @Suppress("UNCHECKED_CAST")
                     observer?.onBeginComposition(
                         this,
-                        invalidations.asMap() as Map<RecomposeScope, Set<Any>?>
+                        invalidations.asMap() as Map<RecomposeScope, Set<Any>>
                     )
                     composer.recompose(invalidations).also { shouldDrain ->
                         // Apply would normally do this for us; do it now if apply shouldn't happen.
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Stack.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Stack.kt
index 42f0d1a..03989dd 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Stack.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Stack.kt
@@ -16,10 +16,10 @@
 
 package androidx.compose.runtime
 
-// TODO(b/139762913): Consider changing to inline class of ArrayList<T> to avoid wrapper class
-internal class Stack<T> {
-    private val backing = ArrayList<T>()
+import kotlin.jvm.JvmInline
 
+@JvmInline
+internal value class Stack<T>(private val backing: ArrayList<T> = ArrayList()) {
     val size: Int
         get() = backing.size
 
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/IntMap.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/IntMap.kt
deleted file mode 100644
index a89d532..0000000
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/IntMap.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.runtime.collection
-
-/** Map of (int) -> Element that attempts to avoid boxing. */
-internal expect class IntMap<E>(initialCapacity: Int = 10) {
-
-    /** True if this map contains key */
-    operator fun contains(key: Int): Boolean
-
-    /** Get [key] or null */
-    operator fun get(key: Int): E?
-
-    /** Get [key] or [valueIfAbsent] */
-    fun get(key: Int, valueIfAbsent: E): E
-
-    /** Sets [key] to [value] */
-    operator fun set(key: Int, value: E)
-
-    /**
-     * Remove [key], if it exists
-     *
-     * Otherwise no op
-     */
-    fun remove(key: Int)
-
-    /** Clear this map */
-    fun clear()
-
-    /** Current count of key value pairs. */
-    val size: Int
-}
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/ScopeMap.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/ScopeMap.kt
index 497f33f..dddcb13 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/ScopeMap.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/ScopeMap.kt
@@ -16,12 +16,16 @@
 
 package androidx.compose.runtime.collection
 
+import androidx.collection.MutableScatterMap
 import androidx.collection.MutableScatterSet
 import androidx.collection.mutableScatterMapOf
+import kotlin.jvm.JvmInline
 
 /** Maps values to a set of scopes. */
-internal class ScopeMap<Key : Any, Scope : Any> {
-    val map = mutableScatterMapOf<Any, Any>()
+@JvmInline
+internal value class ScopeMap<Key : Any, Scope : Any>(
+    val map: MutableScatterMap<Any, Any> = mutableScatterMapOf(),
+) {
 
     /** The number of values in the map. */
     val size
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/Snapshot.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/Snapshot.kt
index f5d9bbf..9cb3aaf 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/Snapshot.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/Snapshot.kt
@@ -809,6 +809,7 @@
                 val result =
                     innerApplyLocked(
                         nextSnapshotId,
+                        modified,
                         optimisticMerges,
                         openSnapshots.clear(previousGlobalSnapshot.id)
                     )
@@ -957,6 +958,7 @@
 
     internal fun innerApplyLocked(
         snapshotId: Int,
+        modified: MutableScatterSet<StateObject>,
         optimisticMerges: Map<StateRecord, StateRecord>?,
         invalidSnapshots: SnapshotIdSet
     ): SnapshotApplyResult {
@@ -973,7 +975,6 @@
         // is for the apply.
         var mergedRecords: MutableList<Pair<StateObject, StateRecord>>? = null
         val start = this.invalid.set(id).or(this.previousIds)
-        val modified = modified!!
         var statesToRemove: MutableList<StateObject>? = null
         modified.forEach { state ->
             val first = state.firstStateRecord
@@ -1481,7 +1482,7 @@
             if (modified == null || modified.size == 0) {
                 closeAndReleasePinning()
             } else {
-                val result = innerApplyLocked(parent.id, optimisticMerges, parent.invalid)
+                val result = innerApplyLocked(parent.id, modified, optimisticMerges, parent.invalid)
                 if (result != SnapshotApplyResult.Success) return result
 
                 parent.modified?.apply { addAll(modified) }
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotStateSet.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotStateSet.kt
index e90d8ee..f9d9ef3 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotStateSet.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotStateSet.kt
@@ -20,6 +20,8 @@
 import androidx.compose.runtime.SynchronizedObject
 import androidx.compose.runtime.external.kotlinx.collections.immutable.PersistentSet
 import androidx.compose.runtime.external.kotlinx.collections.immutable.persistentSetOf
+import androidx.compose.runtime.synchronized
+import kotlin.jvm.JvmName
 
 /**
  * An implementation of [MutableSet] that can be observed and snapshot. This is the result type
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/tooling/CompositionObserver.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/tooling/CompositionObserver.kt
index e3bef5b8..659cc9a 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/tooling/CompositionObserver.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/tooling/CompositionObserver.kt
@@ -45,10 +45,7 @@
      * @param invalidationMap the recompose scopes that will be recomposed by this composition. This
      *   list is empty for the initial composition.
      */
-    fun onBeginComposition(
-        composition: Composition,
-        invalidationMap: Map<RecomposeScope, Set<Any>?>
-    )
+    fun onBeginComposition(composition: Composition, invalidationMap: Map<RecomposeScope, Set<Any>>)
 
     /** Called after composition has been completed for [composition]. */
     fun onEndComposition(composition: Composition)
diff --git a/compose/runtime/runtime/src/commonTest/kotlin/androidx/compose/runtime/CompositionTestExtensions.kt b/compose/runtime/runtime/src/commonTest/kotlin/androidx/compose/runtime/CompositionTestExtensions.kt
index f18fa53..594ad0a 100644
--- a/compose/runtime/runtime/src/commonTest/kotlin/androidx/compose/runtime/CompositionTestExtensions.kt
+++ b/compose/runtime/runtime/src/commonTest/kotlin/androidx/compose/runtime/CompositionTestExtensions.kt
@@ -16,8 +16,6 @@
 
 package androidx.compose.runtime
 
-import org.jetbrains.annotations.TestOnly
-
 @TestOnly
 fun Composition.getSlots(): Iterable<Any?> = (this as CompositionImpl).slotTable.slots.asIterable()
 
diff --git a/compose/runtime/runtime/src/commonTest/kotlin/androidx/compose/runtime/changelist/OperationsTest.kt b/compose/runtime/runtime/src/commonTest/kotlin/androidx/compose/runtime/changelist/OperationsTest.kt
deleted file mode 100644
index 66ae4f6..0000000
--- a/compose/runtime/runtime/src/commonTest/kotlin/androidx/compose/runtime/changelist/OperationsTest.kt
+++ /dev/null
@@ -1,709 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.runtime.changelist
-
-import androidx.compose.runtime.changelist.Operation.IntParameter
-import androidx.compose.runtime.changelist.Operation.ObjectParameter
-import androidx.compose.runtime.changelist.TestOperations.MixedOperation
-import androidx.compose.runtime.changelist.TestOperations.NoArgsOperation
-import androidx.compose.runtime.changelist.TestOperations.OneIntOperation
-import androidx.compose.runtime.changelist.TestOperations.OneObjectOperation
-import androidx.compose.runtime.changelist.TestOperations.ThreeIntsOperation
-import androidx.compose.runtime.changelist.TestOperations.ThreeObjectsOperation
-import androidx.compose.runtime.changelist.TestOperations.TwoIntsOperation
-import androidx.compose.runtime.changelist.TestOperations.TwoObjectsOperation
-import kotlin.reflect.KProperty1
-import kotlin.reflect.full.declaredMembers
-import kotlin.reflect.jvm.isAccessible
-import kotlin.test.assertEquals
-import kotlin.test.assertTrue
-import kotlin.test.fail
-import org.junit.Test
-
-class OperationsTest {
-
-    private val stack = Operations()
-
-    @Test
-    fun testInitialization() {
-        assertStackState(
-            message = "OpStack did not initialize in the expected state",
-            stack = stack
-        )
-    }
-
-    @Test
-    fun testPush_withNoBlock_writesOperationWithNoArgs() {
-        stack.push(NoArgsOperation)
-        assertStackState(
-            message =
-                "OpStack was not in the expected state " +
-                    "after pushing an operation with no arguments",
-            stack = stack,
-            expectedOperations = listOf(NoArgsOperation)
-        )
-    }
-
-    @Test(expected = IllegalArgumentException::class)
-    fun testPush_withNoBlock_failsIfOperationHasArguments() {
-        stack.push(MixedOperation)
-    }
-
-    @Test
-    fun testPush_intArguments() {
-        stack.push(OneIntOperation) {
-            val (int1) = OneIntOperation.intParams
-            setInt(int1, 42)
-        }
-        assertStackState(
-            stack = stack,
-            expectedOperations = listOf(OneIntOperation),
-            expectedIntArgs = listOf(42)
-        )
-
-        stack.push(TwoIntsOperation) {
-            val (int1, int2) = TwoIntsOperation.intParams
-            setInt(int1, 1234)
-            setInt(int2, 5678)
-        }
-        assertStackState(
-            stack = stack,
-            expectedOperations = listOf(OneIntOperation, TwoIntsOperation),
-            expectedIntArgs = listOf(42, 1234, 5678)
-        )
-
-        stack.push(ThreeIntsOperation) {
-            val (int1, int2, int3) = ThreeIntsOperation.intParams
-            setInt(int1, 11)
-            setInt(int2, 22)
-            setInt(int3, 33)
-        }
-        assertStackState(
-            stack = stack,
-            expectedOperations = listOf(OneIntOperation, TwoIntsOperation, ThreeIntsOperation),
-            expectedIntArgs = listOf(42, 1234, 5678, 11, 22, 33)
-        )
-    }
-
-    @Test
-    fun testPush_objectArguments() {
-        stack.push(OneObjectOperation) {
-            val (obj1) = OneObjectOperation.objParams
-            setObject(obj1, null)
-        }
-        assertStackState(
-            stack = stack,
-            expectedOperations = listOf(OneObjectOperation),
-            expectedObjArgs = listOf(null)
-        )
-
-        stack.push(TwoObjectsOperation) {
-            val (obj1, obj2) = TwoObjectsOperation.objParams
-            setObject(obj1, "Hello")
-            setObject(obj2, "World")
-        }
-        assertStackState(
-            stack = stack,
-            expectedOperations = listOf(OneObjectOperation, TwoObjectsOperation),
-            expectedObjArgs = listOf(null, "Hello", "World")
-        )
-
-        stack.push(ThreeObjectsOperation) {
-            val (obj1, obj2, obj3) = ThreeObjectsOperation.objParams
-            setObject(obj1, Unit)
-            setObject(obj2, "Another string")
-            setObject(obj3, 123.456)
-        }
-        assertStackState(
-            stack = stack,
-            expectedOperations =
-                listOf(OneObjectOperation, TwoObjectsOperation, ThreeObjectsOperation),
-            expectedObjArgs = listOf(null, "Hello", "World", Unit, "Another string", 123.456)
-        )
-    }
-
-    @Test
-    fun testPush_mixedArguments() {
-        stack.push(MixedOperation) {
-            val (int1, int2) = MixedOperation.intParams
-            val (obj1, obj2) = MixedOperation.objParams
-
-            setInt(int1, 999)
-            setInt(int2, -1)
-            setObject(obj1, "String 1")
-            setObject(obj2, "String 2")
-        }
-
-        assertStackState(
-            stack = stack,
-            expectedOperations = listOf(MixedOperation),
-            expectedIntArgs = listOf(999, -1),
-            expectedObjArgs = listOf("String 1", "String 2")
-        )
-    }
-
-    @Test
-    fun testPush_variousOperations() {
-        pushVariousOperations(stack)
-        assertStackInVariousOperationState(stack = stack)
-    }
-
-    @Test
-    fun testPush_withResizingRequired() {
-        check(
-            stack.opCodes.size == Operations.InitialCapacity &&
-                stack.intArgs.size == Operations.InitialCapacity &&
-                stack.objectArgs.size == Operations.InitialCapacity
-        ) {
-            "OpStack did not initialize one or more of its backing arrays (opCodes, intArgs, " +
-                "or objectArgs) to `OpStack.InitialCapacity`. Please use the constant or update " +
-                "this test with the correct capacity to ensure that resizing is being tested."
-        }
-
-        val itemsToForceResize = Operations.InitialCapacity + 1
-        repeat(itemsToForceResize) { opNumber ->
-            stack.push(TwoIntsOperation) {
-                val (int1, int2) = TwoIntsOperation.intParams
-                setInt(int1, opNumber * 10 + 1)
-                setInt(int2, opNumber * 10 + 2)
-            }
-        }
-
-        repeat(itemsToForceResize) { opNumber ->
-            stack.push(TwoObjectsOperation) {
-                val (obj1, obj2) = TwoObjectsOperation.objParams
-                setObject(obj1, "op $opNumber, obj 1")
-                setObject(obj2, "op $opNumber, obj 2")
-            }
-        }
-
-        assertStackState(
-            message =
-                "Stack was not in the expected state after pushing " +
-                    "$itemsToForceResize operations, requiring that the stack resize all " +
-                    "of its internal arrays.",
-            stack = stack,
-            expectedOperations =
-                List(itemsToForceResize) { TwoIntsOperation } +
-                    List(itemsToForceResize) { TwoObjectsOperation },
-            expectedIntArgs =
-                generateSequence(0) { it + 1 }
-                    .flatMap { sequenceOf(it * 10 + 1, it * 10 + 2) }
-                    .take(itemsToForceResize * TwoIntsOperation.ints)
-                    .toList(),
-            expectedObjArgs =
-                generateSequence(0) { it + 1 }
-                    .flatMap { sequenceOf("op $it, obj 1", "op $it, obj 2") }
-                    .take(itemsToForceResize * TwoObjectsOperation.objects)
-                    .toList()
-        )
-    }
-
-    @Test
-    fun testPush_throwsIfAnyIntArgsNotProvided() {
-        try {
-            stack.push(TwoIntsOperation) {
-                val (_, intArg2) = TwoIntsOperation.intParams
-                setInt(intArg2, 42)
-            }
-            fail(
-                "Pushing an operation that defines two parameters should fail " +
-                    "if only one of the arguments is set"
-            )
-        } catch (e: IllegalStateException) {
-            assertTrue(
-                message =
-                    "The thrown exception does not appear to have reported the expected " +
-                        "error (its message is '${e.message}')",
-                actual = e.message.orEmpty().contains("Not all arguments were provided")
-            )
-        }
-    }
-
-    @Test
-    fun testPush_throwsIfAnyObjectArgsNotProvided() {
-        try {
-            stack.push(TwoObjectsOperation) {
-                val (_, objectArg2) = TwoObjectsOperation.objParams
-                setObject(objectArg2, Any())
-            }
-            fail(
-                "Pushing an operation that defines two parameters should fail " +
-                    "if only one of the arguments is set"
-            )
-        } catch (e: IllegalStateException) {
-            assertTrue(
-                message =
-                    "The thrown exception does not appear to have reported the expected " +
-                        "error (its message is '${e.message}')",
-                actual = e.message.orEmpty().contains("Not all arguments were provided")
-            )
-        }
-    }
-
-    @Test
-    fun testPush_throwsIfIntArgProvidedTwice() {
-        try {
-            stack.push(ThreeIntsOperation) {
-                val (_, intArg2, _) = ThreeIntsOperation.intParams
-                setInt(intArg2, 2)
-                setInt(intArg2, 2)
-            }
-            fail("Pushing an operation should fail if an argument is set twice")
-        } catch (e: IllegalStateException) {
-            assertTrue(
-                message =
-                    "The thrown exception does not appear to have reported the expected " +
-                        "error (its message is '${e.message}')",
-                actual = e.message.orEmpty().contains("Already pushed argument")
-            )
-        }
-    }
-
-    @Test
-    fun testPush_throwsIfObjectArgProvidedTwice() {
-        try {
-            stack.push(ThreeObjectsOperation) {
-                val (_, objectArg2, _) = ThreeObjectsOperation.objParams
-                setObject(objectArg2, Any())
-                setObject(objectArg2, Any())
-            }
-            fail("Pushing an operation should fail if an argument is set twice")
-        } catch (e: IllegalStateException) {
-            assertTrue(
-                message =
-                    "The thrown exception does not appear to have reported the expected " +
-                        "error (its message is '${e.message}')",
-                actual = e.message.orEmpty().contains("Already pushed argument")
-            )
-        }
-    }
-
-    @Test(expected = NoSuchElementException::class)
-    fun testPop_throwsIfStackIsEmpty() {
-        stack.pop()
-    }
-
-    @Test
-    fun testPop_removesOnlyOperation() {
-        stack.push(MixedOperation) {
-            val (int1, int2) = MixedOperation.intParams
-            val (obj1, obj2) = MixedOperation.objParams
-
-            setInt(int1, 20)
-            setInt(int2, 30)
-            setObject(obj1, "obj1")
-            setObject(obj2, "obj2")
-        }
-
-        stack.pop()
-        assertStackState(
-            message = "Stack should be empty after popping the only item",
-            stack = stack
-        )
-    }
-
-    @Test
-    fun testPop_removesMostRecentlyPushedOperation() {
-        stack.push(MixedOperation) {
-            val (int1, int2) = MixedOperation.intParams
-            val (obj1, obj2) = MixedOperation.objParams
-
-            setInt(int1, 20)
-            setInt(int2, 30)
-            setObject(obj1, "obj1")
-            setObject(obj2, "obj2")
-        }
-
-        stack.pop()
-        assertStackState(
-            message = "Stack should be empty after popping the only item",
-            stack = stack
-        )
-    }
-
-    @Test(expected = NoSuchElementException::class)
-    fun testPopInto_throwsIfStackIsEmpty() {
-        stack.pop()
-    }
-
-    @Test
-    fun testPopInto_copiesAndRemovesOperationToNewTarget() {
-        repeat(40) { opNumber ->
-            stack.push(ThreeObjectsOperation) {
-                val (obj1, obj2, obj3) = ThreeObjectsOperation.objParams
-                setObject(obj1, "${opNumber}A")
-                setObject(obj2, "${opNumber}B")
-                setObject(obj3, "${opNumber}C")
-            }
-        }
-
-        val destinationStack = Operations()
-        repeat(20) { opNumber ->
-            destinationStack.push(ThreeIntsOperation) {
-                val (int1, int2, int3) = ThreeIntsOperation.intParams
-                setInt(int1, opNumber * 10)
-                setInt(int2, opNumber * 20)
-                setInt(int3, opNumber * 30)
-            }
-        }
-
-        assertStackState(
-            message = "Source stack did not initialize to the expected state",
-            stack = stack,
-            expectedOperations = List(40) { ThreeObjectsOperation },
-            expectedObjArgs =
-                generateSequence(0) { it + 1 }
-                    .flatMap { sequenceOf("${it}A", "${it}B", "${it}C") }
-                    .take(40 * ThreeObjectsOperation.objects)
-                    .toList()
-        )
-
-        assertStackState(
-            message = "Destination stack did not initialize to the expected state",
-            stack = destinationStack,
-            expectedOperations = List(20) { ThreeIntsOperation },
-            expectedIntArgs =
-                generateSequence(0) { it + 1 }
-                    .flatMap { sequenceOf(it * 10, it * 20, it * 30) }
-                    .take(20 * ThreeIntsOperation.ints)
-                    .toList()
-        )
-
-        stack.popInto(destinationStack)
-
-        assertStackState(
-            message = "The last pushed operation was not removed from the source stack as expected",
-            stack = stack,
-            expectedOperations = List(39) { ThreeObjectsOperation },
-            expectedObjArgs =
-                generateSequence(0) { it + 1 }
-                    .flatMap { sequenceOf("${it}A", "${it}B", "${it}C") }
-                    .take(39 * ThreeObjectsOperation.objects)
-                    .toList()
-        )
-
-        assertStackState(
-            message = "The popped item was not added to the destination stack as expected",
-            stack = destinationStack,
-            expectedOperations = List(20) { ThreeIntsOperation } + ThreeObjectsOperation,
-            expectedIntArgs =
-                generateSequence(0) { it + 1 }
-                    .flatMap { sequenceOf(it * 10, it * 20, it * 30) }
-                    .take(20 * ThreeIntsOperation.ints)
-                    .toList(),
-            expectedObjArgs = listOf("39A", "39B", "39C")
-        )
-    }
-
-    @Test
-    fun testClear_resetsToInitialState() {
-        val operationCount = Operations.InitialCapacity * 4
-        repeat(operationCount) { opNumber ->
-            stack.push(MixedOperation) {
-                val (int1, int2) = MixedOperation.intParams
-                val (obj1, obj2) = MixedOperation.objParams
-
-                setInt(int1, opNumber)
-                setInt(int2, -opNumber)
-                setObject(obj1, "obj1:$opNumber")
-                setObject(obj2, "obj2:$opNumber")
-            }
-        }
-
-        assertStackState(
-            message = "Stack was not seeded into the expected state",
-            stack = stack,
-            expectedOperations = List(operationCount) { MixedOperation },
-            expectedIntArgs =
-                generateSequence(0) { it + 1 }
-                    .flatMap { sequenceOf(it, -it) }
-                    .take(operationCount * MixedOperation.ints)
-                    .toList(),
-            expectedObjArgs =
-                generateSequence(0) { it + 1 }
-                    .flatMap { sequenceOf("obj1:$it", "obj2:$it") }
-                    .take(operationCount * MixedOperation.objects)
-                    .toList(),
-        )
-
-        stack.clear()
-        assertStackState(
-            message = "Stack did not properly reset after calling clear()",
-            stack = stack,
-        )
-    }
-
-    @Test
-    fun testDrain_iteratesThroughAllElements_inPushOrder_andClearsStack() {
-        pushVariousOperations(stack)
-
-        val capturedOperations = mutableListOf<Operation>()
-        val capturedInts = mutableListOf<Int>()
-        val capturedObjects = mutableListOf<Any?>()
-        stack.drain {
-            capturedOperations += operation
-            repeat(operation.ints) { offset -> capturedInts += getInt(IntParameter(offset)) }
-            repeat(operation.objects) { offset ->
-                capturedObjects += getObject(ObjectParameter<Any?>(offset))
-            }
-        }
-
-        assertEquals(
-            message = "The stack's operations were not received in the expected order.",
-            expected =
-                listOf<Operation>(
-                    MixedOperation,
-                    NoArgsOperation,
-                    TwoIntsOperation,
-                    ThreeObjectsOperation,
-                    NoArgsOperation
-                ),
-            actual = capturedOperations
-        )
-
-        assertEquals(
-            message = "The stack's int arguments were not received in the expected order.",
-            expected = listOf(999, -1, 0xABCDEF, 0x123456),
-            actual = capturedInts
-        )
-
-        assertEquals(
-            message = "The stack's object arguments were not received in the expected order.",
-            expected = listOf("String 1", "String 2", 1.0, Unit, null),
-            actual = capturedObjects
-        )
-
-        assertStackState(message = "Stack should be empty after calling drain()", stack = stack)
-    }
-
-    @Test
-    fun testForEach_iteratesThroughOperations_inPushOrder() {
-        pushVariousOperations(stack)
-
-        val capturedOperations = mutableListOf<Operation>()
-        val capturedInts = mutableListOf<Int>()
-        val capturedObjects = mutableListOf<Any?>()
-        stack.forEach {
-            capturedOperations += operation
-            repeat(operation.ints) { offset -> capturedInts += getInt(IntParameter(offset)) }
-            repeat(operation.objects) { offset ->
-                capturedObjects += getObject(ObjectParameter<Any?>(offset))
-            }
-        }
-
-        assertEquals(
-            message = "The stack's operations were not received in the expected order.",
-            expected =
-                listOf<Operation>(
-                    MixedOperation,
-                    NoArgsOperation,
-                    TwoIntsOperation,
-                    ThreeObjectsOperation,
-                    NoArgsOperation
-                ),
-            actual = capturedOperations
-        )
-
-        assertEquals(
-            message = "The stack's int arguments were not received in the expected order.",
-            expected = listOf(999, -1, 0xABCDEF, 0x123456),
-            actual = capturedInts
-        )
-
-        assertEquals(
-            message = "The stack's object arguments were not received in the expected order.",
-            expected = listOf("String 1", "String 2", 1.0, Unit, null),
-            actual = capturedObjects
-        )
-
-        assertStackInVariousOperationState(
-            message = "Stack should not be modified after iterating",
-            stack = stack
-        )
-    }
-
-    private fun pushVariousOperations(stack: Operations) {
-        stack.apply {
-            push(MixedOperation) {
-                val (int1, int2) = MixedOperation.intParams
-                val (obj1, obj2) = MixedOperation.objParams
-
-                setInt(int1, 999)
-                setInt(int2, -1)
-                setObject(obj1, "String 1")
-                setObject(obj2, "String 2")
-            }
-
-            push(NoArgsOperation)
-
-            push(TwoIntsOperation) {
-                val (int1, int2) = TwoIntsOperation.intParams
-
-                setInt(int1, 0xABCDEF)
-                setInt(int2, 0x123456)
-            }
-
-            push(ThreeObjectsOperation) {
-                val (obj1, obj2, obj3) = ThreeObjectsOperation.objParams
-
-                setObject(obj1, 1.0)
-                setObject(obj2, Unit)
-                setObject(obj3, null)
-            }
-
-            push(NoArgsOperation)
-        }
-    }
-
-    private fun assertStackInVariousOperationState(message: String = "", stack: Operations) {
-        assertStackState(
-            message = message,
-            stack = stack,
-            expectedOperations =
-                listOf(
-                    MixedOperation,
-                    NoArgsOperation,
-                    TwoIntsOperation,
-                    ThreeObjectsOperation,
-                    NoArgsOperation
-                ),
-            expectedIntArgs = listOf(999, -1, 0xABCDEF, 0x123456),
-            expectedObjArgs = listOf("String 1", "String 2", 1.0, Unit, null)
-        )
-    }
-
-    private fun assertStackState(
-        message: String = "",
-        stack: Operations,
-        expectedOperations: List<Operation> = emptyList(),
-        expectedIntArgs: List<Int> = emptyList(),
-        expectedObjArgs: List<Any?> = emptyList()
-    ) {
-        val errors = mutableListOf<String>()
-
-        val size = stack.size
-        val isEmpty = stack.isEmpty()
-        val isNotEmpty = stack.isNotEmpty()
-        if (size != expectedOperations.size) {
-            errors +=
-                "Stack did not report correct size " +
-                    "(expected ${expectedOperations.size}, was $size)"
-        }
-
-        if (isEmpty != expectedOperations.isEmpty()) {
-            errors +=
-                "isEmpty() did not return expected value " +
-                    "(expected ${expectedOperations.isEmpty()}, was $isEmpty)"
-        }
-
-        if (isNotEmpty != expectedOperations.isNotEmpty()) {
-            errors +=
-                "isNotEmpty() did not return expected value " +
-                    "(expected ${expectedOperations.isNotEmpty()}, was $isNotEmpty)"
-        }
-
-        val actualOpCodes = stack.opCodes
-        if (!actualOpCodes.asIterable().startsWith(expectedOperations)) {
-            errors +=
-                "opCodes array did not match expected operations " +
-                    "(expected [${expectedOperations.joinToString()}], was " +
-                    "[${actualOpCodes.joinToString()}])"
-        }
-
-        val actualIntArgs = stack.intArgs
-        if (!actualIntArgs.asIterable().startsWith(expectedIntArgs)) {
-            errors +=
-                "intArgs array did not match expected operations " +
-                    "(expected [${expectedIntArgs.joinToString()}], was " +
-                    "[${actualIntArgs.joinToString()}])"
-        }
-
-        val actualObjectArgs = stack.objectArgs
-        if (!actualObjectArgs.asIterable().startsWith(expectedObjArgs, null)) {
-            errors +=
-                "objectArgs array did not match expected operations " +
-                    "(expected [${expectedObjArgs.joinToString()}], was " +
-                    "[${actualObjectArgs.joinToString()}])"
-        }
-
-        if (errors.isNotEmpty()) {
-            fail(
-                message.takeIf { it.isNotBlank() }?.let { "$it\n" }.orEmpty() +
-                    "Failed with the following validation errors:" +
-                    errors.joinToString { "\n    - $it" }
-            )
-        }
-    }
-
-    private fun <T> Iterable<T>.startsWith(other: Iterable<T>): Boolean {
-        val thisIterator = iterator()
-        val otherIterator = other.iterator()
-
-        while (otherIterator.hasNext()) {
-            if (!thisIterator.hasNext() || thisIterator.next() != otherIterator.next()) {
-                return false
-            }
-        }
-
-        return true
-    }
-
-    private fun <T> Iterable<T>.startsWith(other: Iterable<T>, endFill: T): Boolean {
-        val thisIterator = iterator()
-        val otherIterator = other.iterator()
-
-        while (otherIterator.hasNext()) {
-            if (!thisIterator.hasNext() || thisIterator.next() != otherIterator.next()) {
-                return false
-            }
-        }
-
-        while (thisIterator.hasNext()) {
-            if (thisIterator.next() != endFill) {
-                return false
-            }
-        }
-
-        return true
-    }
-
-    private val Operations.opCodes: Array<Operation?>
-        get() = readPropertyReflectively("opCodes")
-
-    private val Operations.intArgs: IntArray
-        get() = readPropertyReflectively("intArgs")
-
-    private val Operations.objectArgs: Array<Any?>
-        get() = readPropertyReflectively("objectArgs")
-
-    private inline fun <reified T : Any, reified R> T.readPropertyReflectively(
-        propertyName: String
-    ): R {
-        val property =
-            this::class
-                .declaredMembers
-                .mapNotNull {
-                    @Suppress("UNCHECKED_CAST")
-                    it as? KProperty1<T, R>
-                }
-                .single { it.name == propertyName }
-
-        property.isAccessible = true
-        return property.get(this)
-    }
-}
diff --git a/compose/runtime/runtime/src/commonTest/kotlin/androidx/compose/runtime/collection/IntMapTest.kt b/compose/runtime/runtime/src/commonTest/kotlin/androidx/compose/runtime/collection/IntMapTest.kt
deleted file mode 100644
index 0b5255f..0000000
--- a/compose/runtime/runtime/src/commonTest/kotlin/androidx/compose/runtime/collection/IntMapTest.kt
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.runtime.collection
-
-import kotlin.random.Random
-import kotlin.test.Test
-import kotlin.test.assertEquals
-import kotlin.test.assertFalse
-import kotlin.test.assertTrue
-import kotlinx.test.IgnoreAndroidUnitTestTarget
-
-// Run on all platforms except Android unit tests. IntMap on Android is backed by the platform
-// SparseArray class, which is not implemented and will no-op on outside of an instrumented
-// environment.
-@IgnoreAndroidUnitTestTarget
-class IntMapTest {
-
-    @Test
-    fun addingValue_increasesSize() {
-        val subject = IntMap<Int>(10)
-        subject[1] = 2
-        assertEquals(subject.size, 1)
-
-        subject[2] = 3
-        assertEquals(subject.size, 2)
-
-        subject[1] = 5
-        assertEquals(subject.size, 2)
-    }
-
-    @Test
-    fun setValue_canBeRetrieved() {
-        val subject = IntMap<Int>(10)
-        val added = mutableSetOf<Int>()
-        for (i in 1..1000) {
-            val next = Random.nextInt(i)
-            added.add(next)
-            subject[next] = next
-        }
-        for (item in added) {
-            assertEquals(subject[item], item)
-        }
-    }
-
-    @Test
-    fun removingValue_decreasesSize() {
-        val (subject, added) = makeRandom100()
-        val item = added.first()
-        subject.remove(item)
-        assertEquals(subject.size, added.size - 1)
-        assertEquals(subject[item], null)
-    }
-
-    @Test
-    fun removedValue_canBeSet() {
-        val (subject, added) = makeRandom100()
-        val item = added.first()
-        subject.remove(item)
-        subject[item] = -1
-        assertEquals(subject[item], -1)
-    }
-
-    @Test
-    fun clear_clears() {
-        val (subject, added) = makeRandom100()
-        subject.clear()
-        for (item in added) {
-            assertEquals(subject[item], null)
-        }
-
-        val item = added.first()
-        subject[item] = -1
-        assertEquals(subject[item], -1)
-    }
-
-    @Test(timeout = 5_000)
-    fun set() {
-        val map = IntMap<String>()
-        map.set(900, "9")
-        assertTrue(900 in map)
-        map.set(800, "8")
-        assertTrue(800 in map)
-        map.set(700, "7")
-        assertTrue(700 in map)
-        map.set(600, "6")
-        assertTrue(600 in map)
-        map.set(500, "5")
-        assertTrue(500 in map)
-        map.set(100, "1")
-        assertTrue(100 in map)
-        map.set(200, "2")
-        assertTrue(200 in map)
-        map.set(300, "3")
-        assertTrue(300 in map)
-        map.set(400, "4")
-        assertTrue(400 in map)
-    }
-
-    @Test(timeout = 5_000)
-    fun get() {
-        val map = IntMap<String>()
-        map.set(900, "9")
-        assertEquals("9", map[900])
-        map.set(800, "8")
-        assertEquals("8", map[800])
-        map.set(700, "7")
-        assertEquals("7", map[700])
-        map.set(600, "6")
-        assertEquals("6", map[600])
-        map.set(500, "5")
-        assertEquals("5", map[500])
-        map.set(100, "1")
-        assertEquals("1", map[100])
-        map.set(200, "2")
-        assertEquals("2", map[200])
-        map.set(300, "3")
-        assertEquals("3", map[300])
-        map.set(400, "4")
-        assertEquals("4", map[400])
-    }
-
-    @Test(timeout = 5_000)
-    fun remove() {
-        val map = IntMap<String>()
-        map.set(900, "9")
-        map.set(800, "8")
-        map.set(700, "7")
-        map.set(600, "6")
-        map.set(500, "5")
-        map.set(100, "1")
-        map.set(200, "2")
-        map.set(300, "3")
-        map.set(400, "4")
-
-        map.remove(700)
-        assertFalse(700 in map)
-        map.remove(800)
-        assertFalse(800 in map)
-        map.remove(600)
-        assertFalse(600 in map)
-        map.remove(300)
-        assertFalse(300 in map)
-        map.remove(100)
-        assertFalse(100 in map)
-        map.remove(900)
-        assertFalse(900 in map)
-        map.remove(500)
-        assertFalse(500 in map)
-        map.remove(200)
-        assertFalse(200 in map)
-        map.remove(400)
-        assertFalse(400 in map)
-    }
-
-    private fun makeRandom100(): Pair<IntMap<Int>, MutableSet<Int>> {
-        val subject = IntMap<Int>(10)
-        val added = mutableSetOf<Int>()
-        for (i in 1..1000) {
-            val next = Random.nextInt(i)
-            added.add(next)
-            subject[next] = next
-        }
-        for (item in added) {
-            assertEquals(subject[item], item)
-        }
-        return subject to added
-    }
-}
diff --git a/compose/runtime/runtime/src/desktopMain/kotlin/androidx/compose/runtime/MonotonicFrameClock.desktop.kt b/compose/runtime/runtime/src/desktopMain/kotlin/androidx/compose/runtime/MonotonicFrameClock.desktop.kt
deleted file mode 100644
index 53c3de7..0000000
--- a/compose/runtime/runtime/src/desktopMain/kotlin/androidx/compose/runtime/MonotonicFrameClock.desktop.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.runtime
-
-import kotlinx.coroutines.delay
-
-private object DefaultDelayMonotonicFrameClock : MonotonicFrameClock {
-    private const val DefaultFrameDelay = 16L // milliseconds
-
-    override suspend fun <R> withFrameNanos(onFrame: (Long) -> R): R {
-        delay(DefaultFrameDelay)
-        return onFrame(System.nanoTime())
-    }
-}
-
-@Deprecated(
-    "MonotonicFrameClocks are not globally applicable across platforms. " +
-        "Use an appropriate local clock."
-)
-actual val DefaultMonotonicFrameClock: MonotonicFrameClock
-    get() = DefaultDelayMonotonicFrameClock
diff --git a/compose/runtime/runtime/src/desktopMain/kotlin/androidx/compose/runtime/collection/ActualIntMap.desktop.kt b/compose/runtime/runtime/src/desktopMain/kotlin/androidx/compose/runtime/collection/ActualIntMap.desktop.kt
deleted file mode 100644
index 4ecb796..0000000
--- a/compose/runtime/runtime/src/desktopMain/kotlin/androidx/compose/runtime/collection/ActualIntMap.desktop.kt
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.runtime.collection
-
-internal actual class IntMap<E> actual constructor(initialCapacity: Int) {
-    private val DELETED = Any()
-    private var keys = IntArray(initialCapacity)
-    private var _size = 0
-    private var values = Array<Any?>(initialCapacity) { null }
-
-    /** True if this map contains key */
-    actual operator fun contains(key: Int): Boolean {
-        val index = keys.binarySearch(_size, key)
-        return index >= 0 && values[index] !== DELETED
-    }
-
-    /** Get [key] or null */
-    actual operator fun get(key: Int): E? {
-        val index = keys.binarySearch(_size, key)
-        return if (index >= 0 && values[index] !== DELETED) {
-            @Suppress("UNCHECKED_CAST")
-            values[index] as E
-        } else {
-            null
-        }
-    }
-
-    /** Get [key] or [valueIfAbsent] */
-    actual fun get(key: Int, valueIfAbsent: E): E {
-        val index = keys.binarySearch(_size, key)
-        return if (index >= 0 && values[index] !== DELETED) {
-            @Suppress("UNCHECKED_CAST")
-            values[index] as E
-        } else {
-            valueIfAbsent
-        }
-    }
-
-    /** Set [key] to [value] */
-    actual operator fun set(key: Int, value: E) {
-        var index = keys.binarySearch(_size, key)
-        if (index >= 0) {
-            values[index] = value
-        } else {
-            index = -index - 1
-            keys = keys.insert(_size, index, key)
-            values = values.insert(_size, index, value)
-            _size++
-        }
-    }
-
-    /**
-     * Remove key, if it exists
-     *
-     * Otherwise no op
-     */
-    actual fun remove(key: Int) {
-        // note this never GCs
-        val index = keys.binarySearch(_size, key)
-        if (index >= 0) {
-            values[index] = DELETED
-            _size--
-        }
-    }
-
-    /** Clear this map */
-    actual fun clear() {
-        _size = 0
-        for (i in keys.indices) {
-            keys[i] = 0
-        }
-        for (i in values.indices) {
-            values[i] = null
-        }
-    }
-
-    /** Current count of (key, value) pairs */
-    actual val size: Int
-        get() = _size
-}
-
-private fun IntArray.binarySearch(size: Int, value: Int): Int {
-    var min = 0
-    var max = size - 1
-    while (min <= max) {
-        val mid = (min + max) / 2
-        val midValue = this[mid]
-        if (midValue < value) {
-            min = mid + 1
-        } else if (midValue > value) {
-            max = mid - 1
-        } else {
-            return mid
-        }
-    }
-    return -(min + 1)
-}
-
-private fun IntArray.insert(currentSize: Int, index: Int, value: Int): IntArray {
-    if (currentSize + 1 <= size) {
-        if (index < currentSize) {
-            System.arraycopy(this, index, this, index + 1, currentSize - index)
-        }
-        this[index] = value
-        return this
-    }
-
-    val result = IntArray(size * 2)
-    System.arraycopy(this, 0, result, 0, index)
-    result[index] = value
-    System.arraycopy(this, index, result, index + 1, size - index)
-    return result
-}
-
-private fun Array<Any?>.insert(currentSize: Int, index: Int, value: Any?): Array<Any?> {
-    if (currentSize + 1 <= size) {
-        if (index < currentSize) {
-            System.arraycopy(this, index, this, index + 1, currentSize - index)
-        }
-        this[index] = value
-        return this
-    }
-
-    val result = Array<Any?>(size * 2) { null }
-    System.arraycopy(this, 0, result, 0, index)
-    result[index] = value
-    System.arraycopy(this, index, result, index + 1, size - index)
-    return result
-}
diff --git a/compose/runtime/runtime/src/desktopMain/kotlin/androidx/compose/runtime/internal/Utils.desktop.kt b/compose/runtime/runtime/src/desktopMain/kotlin/androidx/compose/runtime/internal/Utils.desktop.kt
deleted file mode 100644
index 934f60eb..0000000
--- a/compose/runtime/runtime/src/desktopMain/kotlin/androidx/compose/runtime/internal/Utils.desktop.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.runtime.internal
-
-internal actual fun logError(message: String, e: Throwable) {
-    System.err.println(message)
-    e.printStackTrace(System.err)
-}
diff --git a/compose/runtime/runtime/src/jvmStubsMain/kotlin/androidx/compose/runtime/MonotonicFrameClock.jvmStubs.kt b/compose/runtime/runtime/src/jvmStubsMain/kotlin/androidx/compose/runtime/MonotonicFrameClock.jvmStubs.kt
new file mode 100644
index 0000000..2cf85ce
--- /dev/null
+++ b/compose/runtime/runtime/src/jvmStubsMain/kotlin/androidx/compose/runtime/MonotonicFrameClock.jvmStubs.kt
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.runtime
+
+actual val DefaultMonotonicFrameClock: MonotonicFrameClock
+    get() = implementedInJetBrainsFork()
diff --git a/compose/runtime/runtime/src/jvmStubsMain/kotlin/androidx/compose/runtime/NotImplemented.jvmStubs.kt b/compose/runtime/runtime/src/jvmStubsMain/kotlin/androidx/compose/runtime/NotImplemented.jvmStubs.kt
new file mode 100644
index 0000000..c1b2c07
--- /dev/null
+++ b/compose/runtime/runtime/src/jvmStubsMain/kotlin/androidx/compose/runtime/NotImplemented.jvmStubs.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.runtime
+
+@Suppress("NOTHING_TO_INLINE")
+internal inline fun implementedInJetBrainsFork(): Nothing =
+    throw NotImplementedError(
+        """
+        Implemented only in JetBrains fork.
+        Please use `org.jetbrains.compose.runtime:runtime` package instead.
+        """
+            .trimIndent()
+    )
diff --git a/compose/runtime/runtime/src/jvmStubsMain/kotlin/androidx/compose/runtime/internal/Utils.jvmStubs.kt b/compose/runtime/runtime/src/jvmStubsMain/kotlin/androidx/compose/runtime/internal/Utils.jvmStubs.kt
new file mode 100644
index 0000000..74c5291
--- /dev/null
+++ b/compose/runtime/runtime/src/jvmStubsMain/kotlin/androidx/compose/runtime/internal/Utils.jvmStubs.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.runtime.internal
+
+import androidx.compose.runtime.implementedInJetBrainsFork
+
+internal actual fun logError(message: String, e: Throwable): Unit = implementedInJetBrainsFork()
diff --git a/compose/runtime/runtime/src/desktopTest/kotlin/kotlinx/test/IgnoreAndroidUnitTestTarget.kt b/compose/runtime/runtime/src/jvmStubsTest/kotlin/kotlinx/test/IgnoreAndroidUnitTestTarget.kt
similarity index 100%
rename from compose/runtime/runtime/src/desktopTest/kotlin/kotlinx/test/IgnoreAndroidUnitTestTarget.kt
rename to compose/runtime/runtime/src/jvmStubsTest/kotlin/kotlinx/test/IgnoreAndroidUnitTestTarget.kt
diff --git a/compose/runtime/runtime/src/jvmTest/kotlin/androidx/compose/runtime/changelist/OperationsTest.kt b/compose/runtime/runtime/src/jvmTest/kotlin/androidx/compose/runtime/changelist/OperationsTest.kt
new file mode 100644
index 0000000..99e72a1
--- /dev/null
+++ b/compose/runtime/runtime/src/jvmTest/kotlin/androidx/compose/runtime/changelist/OperationsTest.kt
@@ -0,0 +1,709 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.runtime.changelist
+
+import androidx.compose.runtime.changelist.Operation.IntParameter
+import androidx.compose.runtime.changelist.Operation.ObjectParameter
+import androidx.compose.runtime.changelist.TestOperations.MixedOperation
+import androidx.compose.runtime.changelist.TestOperations.NoArgsOperation
+import androidx.compose.runtime.changelist.TestOperations.OneIntOperation
+import androidx.compose.runtime.changelist.TestOperations.OneObjectOperation
+import androidx.compose.runtime.changelist.TestOperations.ThreeIntsOperation
+import androidx.compose.runtime.changelist.TestOperations.ThreeObjectsOperation
+import androidx.compose.runtime.changelist.TestOperations.TwoIntsOperation
+import androidx.compose.runtime.changelist.TestOperations.TwoObjectsOperation
+import kotlin.reflect.KProperty1
+import kotlin.reflect.full.declaredMembers
+import kotlin.reflect.jvm.isAccessible
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+import kotlin.test.fail
+
+class OperationsTest {
+
+    private val stack = Operations()
+
+    @Test
+    fun testInitialization() {
+        assertStackState(
+            message = "OpStack did not initialize in the expected state",
+            stack = stack
+        )
+    }
+
+    @Test
+    fun testPush_withNoBlock_writesOperationWithNoArgs() {
+        stack.push(NoArgsOperation)
+        assertStackState(
+            message =
+                "OpStack was not in the expected state " +
+                    "after pushing an operation with no arguments",
+            stack = stack,
+            expectedOperations = listOf(NoArgsOperation)
+        )
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun testPush_withNoBlock_failsIfOperationHasArguments() {
+        stack.push(MixedOperation)
+    }
+
+    @Test
+    fun testPush_intArguments() {
+        stack.push(OneIntOperation) {
+            val (int1) = OneIntOperation.intParams
+            setInt(int1, 42)
+        }
+        assertStackState(
+            stack = stack,
+            expectedOperations = listOf(OneIntOperation),
+            expectedIntArgs = listOf(42)
+        )
+
+        stack.push(TwoIntsOperation) {
+            val (int1, int2) = TwoIntsOperation.intParams
+            setInt(int1, 1234)
+            setInt(int2, 5678)
+        }
+        assertStackState(
+            stack = stack,
+            expectedOperations = listOf(OneIntOperation, TwoIntsOperation),
+            expectedIntArgs = listOf(42, 1234, 5678)
+        )
+
+        stack.push(ThreeIntsOperation) {
+            val (int1, int2, int3) = ThreeIntsOperation.intParams
+            setInt(int1, 11)
+            setInt(int2, 22)
+            setInt(int3, 33)
+        }
+        assertStackState(
+            stack = stack,
+            expectedOperations = listOf(OneIntOperation, TwoIntsOperation, ThreeIntsOperation),
+            expectedIntArgs = listOf(42, 1234, 5678, 11, 22, 33)
+        )
+    }
+
+    @Test
+    fun testPush_objectArguments() {
+        stack.push(OneObjectOperation) {
+            val (obj1) = OneObjectOperation.objParams
+            setObject(obj1, null)
+        }
+        assertStackState(
+            stack = stack,
+            expectedOperations = listOf(OneObjectOperation),
+            expectedObjArgs = listOf(null)
+        )
+
+        stack.push(TwoObjectsOperation) {
+            val (obj1, obj2) = TwoObjectsOperation.objParams
+            setObject(obj1, "Hello")
+            setObject(obj2, "World")
+        }
+        assertStackState(
+            stack = stack,
+            expectedOperations = listOf(OneObjectOperation, TwoObjectsOperation),
+            expectedObjArgs = listOf(null, "Hello", "World")
+        )
+
+        stack.push(ThreeObjectsOperation) {
+            val (obj1, obj2, obj3) = ThreeObjectsOperation.objParams
+            setObject(obj1, Unit)
+            setObject(obj2, "Another string")
+            setObject(obj3, 123.456)
+        }
+        assertStackState(
+            stack = stack,
+            expectedOperations =
+                listOf(OneObjectOperation, TwoObjectsOperation, ThreeObjectsOperation),
+            expectedObjArgs = listOf(null, "Hello", "World", Unit, "Another string", 123.456)
+        )
+    }
+
+    @Test
+    fun testPush_mixedArguments() {
+        stack.push(MixedOperation) {
+            val (int1, int2) = MixedOperation.intParams
+            val (obj1, obj2) = MixedOperation.objParams
+
+            setInt(int1, 999)
+            setInt(int2, -1)
+            setObject(obj1, "String 1")
+            setObject(obj2, "String 2")
+        }
+
+        assertStackState(
+            stack = stack,
+            expectedOperations = listOf(MixedOperation),
+            expectedIntArgs = listOf(999, -1),
+            expectedObjArgs = listOf("String 1", "String 2")
+        )
+    }
+
+    @Test
+    fun testPush_variousOperations() {
+        pushVariousOperations(stack)
+        assertStackInVariousOperationState(stack = stack)
+    }
+
+    @Test
+    fun testPush_withResizingRequired() {
+        check(
+            stack.opCodes.size == Operations.InitialCapacity &&
+                stack.intArgs.size == Operations.InitialCapacity &&
+                stack.objectArgs.size == Operations.InitialCapacity
+        ) {
+            "OpStack did not initialize one or more of its backing arrays (opCodes, intArgs, " +
+                "or objectArgs) to `OpStack.InitialCapacity`. Please use the constant or update " +
+                "this test with the correct capacity to ensure that resizing is being tested."
+        }
+
+        val itemsToForceResize = Operations.InitialCapacity + 1
+        repeat(itemsToForceResize) { opNumber ->
+            stack.push(TwoIntsOperation) {
+                val (int1, int2) = TwoIntsOperation.intParams
+                setInt(int1, opNumber * 10 + 1)
+                setInt(int2, opNumber * 10 + 2)
+            }
+        }
+
+        repeat(itemsToForceResize) { opNumber ->
+            stack.push(TwoObjectsOperation) {
+                val (obj1, obj2) = TwoObjectsOperation.objParams
+                setObject(obj1, "op $opNumber, obj 1")
+                setObject(obj2, "op $opNumber, obj 2")
+            }
+        }
+
+        assertStackState(
+            message =
+                "Stack was not in the expected state after pushing " +
+                    "$itemsToForceResize operations, requiring that the stack resize all " +
+                    "of its internal arrays.",
+            stack = stack,
+            expectedOperations =
+                List(itemsToForceResize) { TwoIntsOperation } +
+                    List(itemsToForceResize) { TwoObjectsOperation },
+            expectedIntArgs =
+                generateSequence(0) { it + 1 }
+                    .flatMap { sequenceOf(it * 10 + 1, it * 10 + 2) }
+                    .take(itemsToForceResize * TwoIntsOperation.ints)
+                    .toList(),
+            expectedObjArgs =
+                generateSequence(0) { it + 1 }
+                    .flatMap { sequenceOf("op $it, obj 1", "op $it, obj 2") }
+                    .take(itemsToForceResize * TwoObjectsOperation.objects)
+                    .toList()
+        )
+    }
+
+    @Test
+    fun testPush_throwsIfAnyIntArgsNotProvided() {
+        try {
+            stack.push(TwoIntsOperation) {
+                val (_, intArg2) = TwoIntsOperation.intParams
+                setInt(intArg2, 42)
+            }
+            fail(
+                "Pushing an operation that defines two parameters should fail " +
+                    "if only one of the arguments is set"
+            )
+        } catch (e: IllegalStateException) {
+            assertTrue(
+                message =
+                    "The thrown exception does not appear to have reported the expected " +
+                        "error (its message is '${e.message}')",
+                actual = e.message.orEmpty().contains("Not all arguments were provided")
+            )
+        }
+    }
+
+    @Test
+    fun testPush_throwsIfAnyObjectArgsNotProvided() {
+        try {
+            stack.push(TwoObjectsOperation) {
+                val (_, objectArg2) = TwoObjectsOperation.objParams
+                setObject(objectArg2, Any())
+            }
+            fail(
+                "Pushing an operation that defines two parameters should fail " +
+                    "if only one of the arguments is set"
+            )
+        } catch (e: IllegalStateException) {
+            assertTrue(
+                message =
+                    "The thrown exception does not appear to have reported the expected " +
+                        "error (its message is '${e.message}')",
+                actual = e.message.orEmpty().contains("Not all arguments were provided")
+            )
+        }
+    }
+
+    @Test
+    fun testPush_throwsIfIntArgProvidedTwice() {
+        try {
+            stack.push(ThreeIntsOperation) {
+                val (_, intArg2, _) = ThreeIntsOperation.intParams
+                setInt(intArg2, 2)
+                setInt(intArg2, 2)
+            }
+            fail("Pushing an operation should fail if an argument is set twice")
+        } catch (e: IllegalStateException) {
+            assertTrue(
+                message =
+                    "The thrown exception does not appear to have reported the expected " +
+                        "error (its message is '${e.message}')",
+                actual = e.message.orEmpty().contains("Already pushed argument")
+            )
+        }
+    }
+
+    @Test
+    fun testPush_throwsIfObjectArgProvidedTwice() {
+        try {
+            stack.push(ThreeObjectsOperation) {
+                val (_, objectArg2, _) = ThreeObjectsOperation.objParams
+                setObject(objectArg2, Any())
+                setObject(objectArg2, Any())
+            }
+            fail("Pushing an operation should fail if an argument is set twice")
+        } catch (e: IllegalStateException) {
+            assertTrue(
+                message =
+                    "The thrown exception does not appear to have reported the expected " +
+                        "error (its message is '${e.message}')",
+                actual = e.message.orEmpty().contains("Already pushed argument")
+            )
+        }
+    }
+
+    @Test(expected = NoSuchElementException::class)
+    fun testPop_throwsIfStackIsEmpty() {
+        stack.pop()
+    }
+
+    @Test
+    fun testPop_removesOnlyOperation() {
+        stack.push(MixedOperation) {
+            val (int1, int2) = MixedOperation.intParams
+            val (obj1, obj2) = MixedOperation.objParams
+
+            setInt(int1, 20)
+            setInt(int2, 30)
+            setObject(obj1, "obj1")
+            setObject(obj2, "obj2")
+        }
+
+        stack.pop()
+        assertStackState(
+            message = "Stack should be empty after popping the only item",
+            stack = stack
+        )
+    }
+
+    @Test
+    fun testPop_removesMostRecentlyPushedOperation() {
+        stack.push(MixedOperation) {
+            val (int1, int2) = MixedOperation.intParams
+            val (obj1, obj2) = MixedOperation.objParams
+
+            setInt(int1, 20)
+            setInt(int2, 30)
+            setObject(obj1, "obj1")
+            setObject(obj2, "obj2")
+        }
+
+        stack.pop()
+        assertStackState(
+            message = "Stack should be empty after popping the only item",
+            stack = stack
+        )
+    }
+
+    @Test(expected = NoSuchElementException::class)
+    fun testPopInto_throwsIfStackIsEmpty() {
+        stack.pop()
+    }
+
+    @Test
+    fun testPopInto_copiesAndRemovesOperationToNewTarget() {
+        repeat(40) { opNumber ->
+            stack.push(ThreeObjectsOperation) {
+                val (obj1, obj2, obj3) = ThreeObjectsOperation.objParams
+                setObject(obj1, "${opNumber}A")
+                setObject(obj2, "${opNumber}B")
+                setObject(obj3, "${opNumber}C")
+            }
+        }
+
+        val destinationStack = Operations()
+        repeat(20) { opNumber ->
+            destinationStack.push(ThreeIntsOperation) {
+                val (int1, int2, int3) = ThreeIntsOperation.intParams
+                setInt(int1, opNumber * 10)
+                setInt(int2, opNumber * 20)
+                setInt(int3, opNumber * 30)
+            }
+        }
+
+        assertStackState(
+            message = "Source stack did not initialize to the expected state",
+            stack = stack,
+            expectedOperations = List(40) { ThreeObjectsOperation },
+            expectedObjArgs =
+                generateSequence(0) { it + 1 }
+                    .flatMap { sequenceOf("${it}A", "${it}B", "${it}C") }
+                    .take(40 * ThreeObjectsOperation.objects)
+                    .toList()
+        )
+
+        assertStackState(
+            message = "Destination stack did not initialize to the expected state",
+            stack = destinationStack,
+            expectedOperations = List(20) { ThreeIntsOperation },
+            expectedIntArgs =
+                generateSequence(0) { it + 1 }
+                    .flatMap { sequenceOf(it * 10, it * 20, it * 30) }
+                    .take(20 * ThreeIntsOperation.ints)
+                    .toList()
+        )
+
+        stack.popInto(destinationStack)
+
+        assertStackState(
+            message = "The last pushed operation was not removed from the source stack as expected",
+            stack = stack,
+            expectedOperations = List(39) { ThreeObjectsOperation },
+            expectedObjArgs =
+                generateSequence(0) { it + 1 }
+                    .flatMap { sequenceOf("${it}A", "${it}B", "${it}C") }
+                    .take(39 * ThreeObjectsOperation.objects)
+                    .toList()
+        )
+
+        assertStackState(
+            message = "The popped item was not added to the destination stack as expected",
+            stack = destinationStack,
+            expectedOperations = List(20) { ThreeIntsOperation } + ThreeObjectsOperation,
+            expectedIntArgs =
+                generateSequence(0) { it + 1 }
+                    .flatMap { sequenceOf(it * 10, it * 20, it * 30) }
+                    .take(20 * ThreeIntsOperation.ints)
+                    .toList(),
+            expectedObjArgs = listOf("39A", "39B", "39C")
+        )
+    }
+
+    @Test
+    fun testClear_resetsToInitialState() {
+        val operationCount = Operations.InitialCapacity * 4
+        repeat(operationCount) { opNumber ->
+            stack.push(MixedOperation) {
+                val (int1, int2) = MixedOperation.intParams
+                val (obj1, obj2) = MixedOperation.objParams
+
+                setInt(int1, opNumber)
+                setInt(int2, -opNumber)
+                setObject(obj1, "obj1:$opNumber")
+                setObject(obj2, "obj2:$opNumber")
+            }
+        }
+
+        assertStackState(
+            message = "Stack was not seeded into the expected state",
+            stack = stack,
+            expectedOperations = List(operationCount) { MixedOperation },
+            expectedIntArgs =
+                generateSequence(0) { it + 1 }
+                    .flatMap { sequenceOf(it, -it) }
+                    .take(operationCount * MixedOperation.ints)
+                    .toList(),
+            expectedObjArgs =
+                generateSequence(0) { it + 1 }
+                    .flatMap { sequenceOf("obj1:$it", "obj2:$it") }
+                    .take(operationCount * MixedOperation.objects)
+                    .toList(),
+        )
+
+        stack.clear()
+        assertStackState(
+            message = "Stack did not properly reset after calling clear()",
+            stack = stack,
+        )
+    }
+
+    @Test
+    fun testDrain_iteratesThroughAllElements_inPushOrder_andClearsStack() {
+        pushVariousOperations(stack)
+
+        val capturedOperations = mutableListOf<Operation>()
+        val capturedInts = mutableListOf<Int>()
+        val capturedObjects = mutableListOf<Any?>()
+        stack.drain {
+            capturedOperations += operation
+            repeat(operation.ints) { offset -> capturedInts += getInt(IntParameter(offset)) }
+            repeat(operation.objects) { offset ->
+                capturedObjects += getObject(ObjectParameter<Any?>(offset))
+            }
+        }
+
+        assertEquals(
+            message = "The stack's operations were not received in the expected order.",
+            expected =
+                listOf<Operation>(
+                    MixedOperation,
+                    NoArgsOperation,
+                    TwoIntsOperation,
+                    ThreeObjectsOperation,
+                    NoArgsOperation
+                ),
+            actual = capturedOperations
+        )
+
+        assertEquals(
+            message = "The stack's int arguments were not received in the expected order.",
+            expected = listOf(999, -1, 0xABCDEF, 0x123456),
+            actual = capturedInts
+        )
+
+        assertEquals(
+            message = "The stack's object arguments were not received in the expected order.",
+            expected = listOf("String 1", "String 2", 1.0, Unit, null),
+            actual = capturedObjects
+        )
+
+        assertStackState(message = "Stack should be empty after calling drain()", stack = stack)
+    }
+
+    @Test
+    fun testForEach_iteratesThroughOperations_inPushOrder() {
+        pushVariousOperations(stack)
+
+        val capturedOperations = mutableListOf<Operation>()
+        val capturedInts = mutableListOf<Int>()
+        val capturedObjects = mutableListOf<Any?>()
+        stack.forEach {
+            capturedOperations += operation
+            repeat(operation.ints) { offset -> capturedInts += getInt(IntParameter(offset)) }
+            repeat(operation.objects) { offset ->
+                capturedObjects += getObject(ObjectParameter<Any?>(offset))
+            }
+        }
+
+        assertEquals(
+            message = "The stack's operations were not received in the expected order.",
+            expected =
+                listOf<Operation>(
+                    MixedOperation,
+                    NoArgsOperation,
+                    TwoIntsOperation,
+                    ThreeObjectsOperation,
+                    NoArgsOperation
+                ),
+            actual = capturedOperations
+        )
+
+        assertEquals(
+            message = "The stack's int arguments were not received in the expected order.",
+            expected = listOf(999, -1, 0xABCDEF, 0x123456),
+            actual = capturedInts
+        )
+
+        assertEquals(
+            message = "The stack's object arguments were not received in the expected order.",
+            expected = listOf("String 1", "String 2", 1.0, Unit, null),
+            actual = capturedObjects
+        )
+
+        assertStackInVariousOperationState(
+            message = "Stack should not be modified after iterating",
+            stack = stack
+        )
+    }
+
+    private fun pushVariousOperations(stack: Operations) {
+        stack.apply {
+            push(MixedOperation) {
+                val (int1, int2) = MixedOperation.intParams
+                val (obj1, obj2) = MixedOperation.objParams
+
+                setInt(int1, 999)
+                setInt(int2, -1)
+                setObject(obj1, "String 1")
+                setObject(obj2, "String 2")
+            }
+
+            push(NoArgsOperation)
+
+            push(TwoIntsOperation) {
+                val (int1, int2) = TwoIntsOperation.intParams
+
+                setInt(int1, 0xABCDEF)
+                setInt(int2, 0x123456)
+            }
+
+            push(ThreeObjectsOperation) {
+                val (obj1, obj2, obj3) = ThreeObjectsOperation.objParams
+
+                setObject(obj1, 1.0)
+                setObject(obj2, Unit)
+                setObject(obj3, null)
+            }
+
+            push(NoArgsOperation)
+        }
+    }
+
+    private fun assertStackInVariousOperationState(message: String = "", stack: Operations) {
+        assertStackState(
+            message = message,
+            stack = stack,
+            expectedOperations =
+                listOf(
+                    MixedOperation,
+                    NoArgsOperation,
+                    TwoIntsOperation,
+                    ThreeObjectsOperation,
+                    NoArgsOperation
+                ),
+            expectedIntArgs = listOf(999, -1, 0xABCDEF, 0x123456),
+            expectedObjArgs = listOf("String 1", "String 2", 1.0, Unit, null)
+        )
+    }
+
+    private fun assertStackState(
+        message: String = "",
+        stack: Operations,
+        expectedOperations: List<Operation> = emptyList(),
+        expectedIntArgs: List<Int> = emptyList(),
+        expectedObjArgs: List<Any?> = emptyList()
+    ) {
+        val errors = mutableListOf<String>()
+
+        val size = stack.size
+        val isEmpty = stack.isEmpty()
+        val isNotEmpty = stack.isNotEmpty()
+        if (size != expectedOperations.size) {
+            errors +=
+                "Stack did not report correct size " +
+                    "(expected ${expectedOperations.size}, was $size)"
+        }
+
+        if (isEmpty != expectedOperations.isEmpty()) {
+            errors +=
+                "isEmpty() did not return expected value " +
+                    "(expected ${expectedOperations.isEmpty()}, was $isEmpty)"
+        }
+
+        if (isNotEmpty != expectedOperations.isNotEmpty()) {
+            errors +=
+                "isNotEmpty() did not return expected value " +
+                    "(expected ${expectedOperations.isNotEmpty()}, was $isNotEmpty)"
+        }
+
+        val actualOpCodes = stack.opCodes
+        if (!actualOpCodes.asIterable().startsWith(expectedOperations)) {
+            errors +=
+                "opCodes array did not match expected operations " +
+                    "(expected [${expectedOperations.joinToString()}], was " +
+                    "[${actualOpCodes.joinToString()}])"
+        }
+
+        val actualIntArgs = stack.intArgs
+        if (!actualIntArgs.asIterable().startsWith(expectedIntArgs)) {
+            errors +=
+                "intArgs array did not match expected operations " +
+                    "(expected [${expectedIntArgs.joinToString()}], was " +
+                    "[${actualIntArgs.joinToString()}])"
+        }
+
+        val actualObjectArgs = stack.objectArgs
+        if (!actualObjectArgs.asIterable().startsWith(expectedObjArgs, null)) {
+            errors +=
+                "objectArgs array did not match expected operations " +
+                    "(expected [${expectedObjArgs.joinToString()}], was " +
+                    "[${actualObjectArgs.joinToString()}])"
+        }
+
+        if (errors.isNotEmpty()) {
+            fail(
+                message.takeIf { it.isNotBlank() }?.let { "$it\n" }.orEmpty() +
+                    "Failed with the following validation errors:" +
+                    errors.joinToString { "\n    - $it" }
+            )
+        }
+    }
+
+    private fun <T> Iterable<T>.startsWith(other: Iterable<T>): Boolean {
+        val thisIterator = iterator()
+        val otherIterator = other.iterator()
+
+        while (otherIterator.hasNext()) {
+            if (!thisIterator.hasNext() || thisIterator.next() != otherIterator.next()) {
+                return false
+            }
+        }
+
+        return true
+    }
+
+    private fun <T> Iterable<T>.startsWith(other: Iterable<T>, endFill: T): Boolean {
+        val thisIterator = iterator()
+        val otherIterator = other.iterator()
+
+        while (otherIterator.hasNext()) {
+            if (!thisIterator.hasNext() || thisIterator.next() != otherIterator.next()) {
+                return false
+            }
+        }
+
+        while (thisIterator.hasNext()) {
+            if (thisIterator.next() != endFill) {
+                return false
+            }
+        }
+
+        return true
+    }
+
+    private val Operations.opCodes: Array<Operation?>
+        get() = readPropertyReflectively("opCodes")
+
+    private val Operations.intArgs: IntArray
+        get() = readPropertyReflectively("intArgs")
+
+    private val Operations.objectArgs: Array<Any?>
+        get() = readPropertyReflectively("objectArgs")
+
+    private inline fun <reified T : Any, reified R> T.readPropertyReflectively(
+        propertyName: String
+    ): R {
+        val property =
+            this::class
+                .declaredMembers
+                .mapNotNull {
+                    @Suppress("UNCHECKED_CAST")
+                    it as? KProperty1<T, R>
+                }
+                .single { it.name == propertyName }
+
+        property.isAccessible = true
+        return property.get(this)
+    }
+}
diff --git a/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/MonotonicFrameClock.linuxx64Stubs.kt b/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/MonotonicFrameClock.linuxx64Stubs.kt
new file mode 100644
index 0000000..2cf85ce
--- /dev/null
+++ b/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/MonotonicFrameClock.linuxx64Stubs.kt
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.runtime
+
+actual val DefaultMonotonicFrameClock: MonotonicFrameClock
+    get() = implementedInJetBrainsFork()
diff --git a/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/NotImplemented.linuxx64Stubs.kt b/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/NotImplemented.linuxx64Stubs.kt
new file mode 100644
index 0000000..c1b2c07
--- /dev/null
+++ b/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/NotImplemented.linuxx64Stubs.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.runtime
+
+@Suppress("NOTHING_TO_INLINE")
+internal inline fun implementedInJetBrainsFork(): Nothing =
+    throw NotImplementedError(
+        """
+        Implemented only in JetBrains fork.
+        Please use `org.jetbrains.compose.runtime:runtime` package instead.
+        """
+            .trimIndent()
+    )
diff --git a/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/SynchronizedObject.linuxx64Stubs.kt b/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/SynchronizedObject.linuxx64Stubs.kt
new file mode 100644
index 0000000..10a1a5f
--- /dev/null
+++ b/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/SynchronizedObject.linuxx64Stubs.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.runtime
+
+@Suppress("ACTUAL_WITHOUT_EXPECT") // https://youtrack.jetbrains.com/issue/KT-37316
+internal actual typealias SynchronizedObject = Any
+
+@PublishedApi
+internal actual inline fun <R> synchronized(lock: SynchronizedObject, block: () -> R): R = block()
diff --git a/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/TestOnly.linuxx64Stubs.kt b/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/TestOnly.linuxx64Stubs.kt
new file mode 100644
index 0000000..49d5da72
--- /dev/null
+++ b/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/TestOnly.linuxx64Stubs.kt
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.runtime
+
+actual annotation class TestOnly
diff --git a/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/internal/Atomic.linuxx64Stubs.kt b/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/internal/Atomic.linuxx64Stubs.kt
new file mode 100644
index 0000000..a0ae660
--- /dev/null
+++ b/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/internal/Atomic.linuxx64Stubs.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.runtime.internal
+
+import androidx.compose.runtime.implementedInJetBrainsFork
+
+internal actual class AtomicReference<V> actual constructor(value: V) {
+    actual fun get(): V = implementedInJetBrainsFork()
+
+    actual fun set(value: V): Unit = implementedInJetBrainsFork()
+
+    actual fun getAndSet(value: V): V = implementedInJetBrainsFork()
+
+    actual fun compareAndSet(expect: V, newValue: V): Boolean = implementedInJetBrainsFork()
+}
+
+internal actual class AtomicInt actual constructor(value: Int) {
+    actual fun get(): Int = implementedInJetBrainsFork()
+
+    actual fun set(value: Int): Unit = implementedInJetBrainsFork()
+
+    actual fun compareAndSet(expect: Int, newValue: Int): Boolean = implementedInJetBrainsFork()
+
+    actual fun add(amount: Int): Int = implementedInJetBrainsFork()
+}
diff --git a/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/internal/ComposableLambda.linuxx64Stubs.kt b/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/internal/ComposableLambda.linuxx64Stubs.kt
new file mode 100644
index 0000000..157540c
--- /dev/null
+++ b/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/internal/ComposableLambda.linuxx64Stubs.kt
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.runtime.internal
+
+import androidx.compose.runtime.ComposeCompilerApi
+import androidx.compose.runtime.Composer
+import androidx.compose.runtime.Stable
+
+@ComposeCompilerApi
+@Stable
+actual interface ComposableLambda :
+    Function2<Composer, Int, Any?>,
+    Function3<Any?, Composer, Int, Any?>,
+    Function4<Any?, Any?, Composer, Int, Any?>,
+    Function5<Any?, Any?, Any?, Composer, Int, Any?>,
+    Function6<Any?, Any?, Any?, Any?, Composer, Int, Any?>,
+    Function7<Any?, Any?, Any?, Any?, Any?, Composer, Int, Any?>,
+    Function8<Any?, Any?, Any?, Any?, Any?, Any?, Composer, Int, Any?>,
+    Function9<Any?, Any?, Any?, Any?, Any?, Any?, Any?, Composer, Int, Any?>,
+    Function10<Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Composer, Int, Any?>,
+    Function11<Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Composer, Int, Any?>,
+    Function13<
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Composer,
+        Int,
+        Int,
+        Any?
+    >,
+    Function14<
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Composer,
+        Int,
+        Int,
+        Any?
+    >,
+    Function15<
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Composer,
+        Int,
+        Int,
+        Any?
+    >,
+    Function16<
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Composer,
+        Int,
+        Int,
+        Any?
+    >,
+    Function17<
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Composer,
+        Int,
+        Int,
+        Any?
+    >,
+    Function18<
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Composer,
+        Int,
+        Int,
+        Any?
+    >,
+    Function19<
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Composer,
+        Int,
+        Int,
+        Any?
+    >,
+    Function20<
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Composer,
+        Int,
+        Int,
+        Any?
+    >,
+    Function21<
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Any?,
+        Composer,
+        Int,
+        Int,
+        Any?
+    >
diff --git a/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/internal/JvmDefaultWithCompatibility.linuxx64Stubs.kt b/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/internal/JvmDefaultWithCompatibility.linuxx64Stubs.kt
new file mode 100644
index 0000000..4b0eb263
--- /dev/null
+++ b/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/internal/JvmDefaultWithCompatibility.linuxx64Stubs.kt
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.runtime.internal
+
+internal actual annotation class JvmDefaultWithCompatibility
diff --git a/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/internal/Thread.linuxx64Stubs.kt b/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/internal/Thread.linuxx64Stubs.kt
new file mode 100644
index 0000000..cb567d9
--- /dev/null
+++ b/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/internal/Thread.linuxx64Stubs.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.runtime.internal
+
+import androidx.compose.runtime.implementedInJetBrainsFork
+
+internal actual fun currentThreadId(): Long = implementedInJetBrainsFork()
+
+internal actual fun currentThreadName(): String = implementedInJetBrainsFork()
diff --git a/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/internal/Utils.linuxx64Stubs.kt b/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/internal/Utils.linuxx64Stubs.kt
new file mode 100644
index 0000000..9f90a05
--- /dev/null
+++ b/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/internal/Utils.linuxx64Stubs.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.runtime.internal
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Composer
+import androidx.compose.runtime.implementedInJetBrainsFork
+import kotlinx.coroutines.CancellationException
+
+internal actual fun identityHashCode(instance: Any?): Int = implementedInJetBrainsFork()
+
+internal actual fun invokeComposable(composer: Composer, composable: @Composable () -> Unit): Unit =
+    implementedInJetBrainsFork()
+
+internal actual abstract class PlatformOptimizedCancellationException
+actual constructor(message: String?) : CancellationException(message)
+
+internal actual fun logError(message: String, e: Throwable): Unit = implementedInJetBrainsFork()
diff --git a/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/internal/WeakReference.linuxx64Stubs.kt b/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/internal/WeakReference.linuxx64Stubs.kt
new file mode 100644
index 0000000..aaaf786
--- /dev/null
+++ b/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/internal/WeakReference.linuxx64Stubs.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.runtime.internal
+
+import androidx.compose.runtime.implementedInJetBrainsFork
+
+internal actual class WeakReference<T : Any> actual constructor(reference: T) {
+    actual fun get(): T? = implementedInJetBrainsFork()
+}
diff --git a/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/snapshots/SnapshotContextElement.linuxx64Stubs.kt b/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/snapshots/SnapshotContextElement.linuxx64Stubs.kt
new file mode 100644
index 0000000..fdae6f6
--- /dev/null
+++ b/compose/runtime/runtime/src/linuxx64StubsMain/kotlin/androidx/compose/runtime/snapshots/SnapshotContextElement.linuxx64Stubs.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.runtime.snapshots
+
+import androidx.compose.runtime.ExperimentalComposeApi
+import androidx.compose.runtime.implementedInJetBrainsFork
+import kotlin.coroutines.CoroutineContext
+
+@OptIn(ExperimentalComposeApi::class)
+internal actual class SnapshotContextElementImpl
+actual constructor(private val snapshot: Snapshot) : SnapshotContextElement {
+    override val key: CoroutineContext.Key<*>
+        get() = implementedInJetBrainsFork()
+}
diff --git a/compose/runtime/runtime/src/linuxx64StubsTest/kotlin/kotlinx/test/IgnoreAndroidUnitTestTarget.linuxx64Stubs.kt b/compose/runtime/runtime/src/linuxx64StubsTest/kotlin/kotlinx/test/IgnoreAndroidUnitTestTarget.linuxx64Stubs.kt
new file mode 100644
index 0000000..b07c105
--- /dev/null
+++ b/compose/runtime/runtime/src/linuxx64StubsTest/kotlin/kotlinx/test/IgnoreAndroidUnitTestTarget.linuxx64Stubs.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package kotlinx.test
+
+annotation class NotIgnored
+
+actual typealias IgnoreAndroidUnitTestTarget = NotIgnored
diff --git a/compose/runtime/runtime/src/linuxx64StubsTest/kotlin/kotlinx/test/IgnoreJsTarget.linuxx64Stubs.kt b/compose/runtime/runtime/src/linuxx64StubsTest/kotlin/kotlinx/test/IgnoreJsTarget.linuxx64Stubs.kt
new file mode 100644
index 0000000..3edd2d9
--- /dev/null
+++ b/compose/runtime/runtime/src/linuxx64StubsTest/kotlin/kotlinx/test/IgnoreJsTarget.linuxx64Stubs.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package kotlinx.test
+
+annotation class DoNothing
+
+actual typealias IgnoreJsTarget = DoNothing
diff --git a/compose/runtime/runtime/src/nonEmulatorCommonTest/kotlin/androidx/compose/runtime/CompositionObserverTests.kt b/compose/runtime/runtime/src/nonEmulatorCommonTest/kotlin/androidx/compose/runtime/CompositionObserverTests.kt
index ae62ad3..9c7036a 100644
--- a/compose/runtime/runtime/src/nonEmulatorCommonTest/kotlin/androidx/compose/runtime/CompositionObserverTests.kt
+++ b/compose/runtime/runtime/src/nonEmulatorCommonTest/kotlin/androidx/compose/runtime/CompositionObserverTests.kt
@@ -194,7 +194,7 @@
             object : CompositionObserver {
                 override fun onBeginComposition(
                     composition: Composition,
-                    invalidationMap: Map<RecomposeScope, Set<Any>?>
+                    invalidationMap: Map<RecomposeScope, Set<Any>>
                 ) {
                     beginCount++
                 }
@@ -237,7 +237,7 @@
             object : CompositionObserver {
                 override fun onBeginComposition(
                     composition: Composition,
-                    invalidationMap: Map<RecomposeScope, Set<Any>?>
+                    invalidationMap: Map<RecomposeScope, Set<Any>>
                 ) {
                     beginCount++
                 }
@@ -281,7 +281,7 @@
             object : CompositionObserver {
                 override fun onBeginComposition(
                     composition: Composition,
-                    invalidationMap: Map<RecomposeScope, Set<Any>?>
+                    invalidationMap: Map<RecomposeScope, Set<Any>>
                 ) {
                     compositionsSeen.add(composition)
                     beginCount++
@@ -332,7 +332,7 @@
             object : CompositionObserver {
                 override fun onBeginComposition(
                     composition: Composition,
-                    invalidationMap: Map<RecomposeScope, Set<Any>?>
+                    invalidationMap: Map<RecomposeScope, Set<Any>>
                 ) {
                     compositionsSeen.add(composition)
                     beginCount++
@@ -385,7 +385,7 @@
             object : CompositionObserver {
                 override fun onBeginComposition(
                     composition: Composition,
-                    invalidationMap: Map<RecomposeScope, Set<Any>?>
+                    invalidationMap: Map<RecomposeScope, Set<Any>>
                 ) {
                     compositionsSeen.add(composition)
                     beginCountOne++
@@ -399,7 +399,7 @@
             object : CompositionObserver {
                 override fun onBeginComposition(
                     composition: Composition,
-                    invalidationMap: Map<RecomposeScope, Set<Any>?>
+                    invalidationMap: Map<RecomposeScope, Set<Any>>
                 ) {
                     beginCountTwo++
                 }
@@ -521,7 +521,7 @@
                     object : CompositionObserver {
                         override fun onBeginComposition(
                             composition: Composition,
-                            invalidationMap: Map<RecomposeScope, Set<Any>?>
+                            invalidationMap: Map<RecomposeScope, Set<Any>>
                         ) {
                             validatedSomething = true
                             for (index in indexes) {
diff --git a/compose/test-utils/build.gradle b/compose/test-utils/build.gradle
index 52bac39..7745525 100644
--- a/compose/test-utils/build.gradle
+++ b/compose/test-utils/build.gradle
@@ -82,14 +82,8 @@
             }
         }
 
-        jvmTest {
-            dependsOn(commonTest)
-            dependencies {
-            }
-        }
-
         androidInstrumentedTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(libs.truth)
                 implementation(projectOrArtifact(":compose:material:material"))
@@ -97,17 +91,11 @@
         }
 
         androidUnitTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(libs.truth)
             }
         }
-
-        desktopTest {
-            dependsOn(jvmTest)
-            dependencies {
-            }
-        }
     }
 }
 
diff --git a/compose/ui/ui-android-stubs/build.gradle b/compose/ui/ui-android-stubs/build.gradle
index 168677e..7b4498e 100644
--- a/compose/ui/ui-android-stubs/build.gradle
+++ b/compose/ui/ui-android-stubs/build.gradle
@@ -38,6 +38,7 @@
     inceptionYear = "2020"
     description = "Stubs for classes in older Android APIs"
     metalavaK2UastEnabled = true
+    doNotDocumentReason = "Not published to maven"
 }
 
 android {
diff --git a/compose/ui/ui-geometry/build.gradle b/compose/ui/ui-geometry/build.gradle
index 1b10ce8..09ce7be 100644
--- a/compose/ui/ui-geometry/build.gradle
+++ b/compose/ui/ui-geometry/build.gradle
@@ -73,24 +73,14 @@
             }
         }
 
-        jvmTest {
+        androidInstrumentedTest {
             dependsOn(commonTest)
             dependencies {
             }
         }
 
-        androidInstrumentedTest {
-            dependsOn(jvmTest)
-            dependencies {
-            }
-        }
-
         androidUnitTest {
-            dependsOn(jvmTest)
-        }
-
-        desktopTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
         }
     }
 }
diff --git a/compose/ui/ui-graphics/build.gradle b/compose/ui/ui-graphics/build.gradle
index de2634e3..7988ac5 100644
--- a/compose/ui/ui-graphics/build.gradle
+++ b/compose/ui/ui-graphics/build.gradle
@@ -91,14 +91,7 @@
             }
         }
 
-        jvmTest {
-            dependsOn(commonTest)
-            dependencies {
-            }
-        }
-
         androidInstrumentedTest {
-            dependsOn(jvmTest)
             dependencies {
                 implementation(project(":compose:ui:ui-graphics:ui-graphics-samples"))
                 implementation(project(":compose:ui:ui-test-junit4"))
@@ -112,7 +105,6 @@
         }
 
         androidUnitTest {
-            dependsOn(jvmTest)
             dependencies {
                 implementation(libs.testRules)
                 implementation(libs.testRunner)
@@ -122,17 +114,6 @@
                 implementation(project(":compose:test-utils"))
             }
         }
-
-        desktopTest {
-            resources.srcDirs += "src/desktopTest/res"
-            dependsOn(jvmTest)
-            dependencies {
-                implementation(project(":compose:ui:ui-test-junit4"))
-                implementation(libs.junit)
-                implementation(libs.truth)
-                implementation(libs.skikoCurrentOs)
-            }
-        }
     }
 }
 
@@ -156,11 +137,3 @@
 android {
     namespace "androidx.compose.ui.graphics"
 }
-
-if (KmpPlatformsKt.enableDesktop(project)) {
-    tasks.withType(Test).configureEach {
-        if (name.equals("desktopTest")) {
-            systemProperties["GOLDEN_PATH"] = project.rootDir.absolutePath + "/../../golden"
-        }
-    }
-}
diff --git a/compose/ui/ui-graphics/src/androidInstrumentedTest/kotlin/androidx/compose/ui/graphics/layer/AndroidGraphicsLayerTest.kt b/compose/ui/ui-graphics/src/androidInstrumentedTest/kotlin/androidx/compose/ui/graphics/layer/AndroidGraphicsLayerTest.kt
index 350d763..c2e994f 100644
--- a/compose/ui/ui-graphics/src/androidInstrumentedTest/kotlin/androidx/compose/ui/graphics/layer/AndroidGraphicsLayerTest.kt
+++ b/compose/ui/ui-graphics/src/androidInstrumentedTest/kotlin/androidx/compose/ui/graphics/layer/AndroidGraphicsLayerTest.kt
@@ -49,6 +49,7 @@
 import androidx.compose.ui.graphics.drawscope.inset
 import androidx.compose.ui.graphics.drawscope.translate
 import androidx.compose.ui.graphics.isLayerManagerInitialized
+import androidx.compose.ui.graphics.isLayerPersistenceEnabled
 import androidx.compose.ui.graphics.nativeCanvas
 import androidx.compose.ui.graphics.toArgb
 import androidx.compose.ui.graphics.toPixelMap
@@ -173,6 +174,28 @@
     }
 
     @Test
+    fun testDrawLayerAfterDiscard() {
+        var layer: GraphicsLayer? = null
+        graphicsLayerTest(
+            block = { graphicsContext ->
+                layer =
+                    graphicsContext.createGraphicsLayer().apply {
+                        assertEquals(IntSize.Zero, this.size)
+                        record { drawRect(Color.Red) }
+                    }
+                layer!!.discardDisplayList()
+                layer!!.record { drawRect(Color.Red) }
+                drawLayer(layer!!)
+            },
+            verify = {
+                assertEquals(TEST_SIZE, layer!!.size)
+                assertEquals(IntOffset.Zero, layer!!.topLeft)
+                it.verifyQuadrants(Color.Red, Color.Red, Color.Red, Color.Red)
+            }
+        )
+    }
+
+    @Test
     fun testDrawAfterDiscard() {
         var layer: GraphicsLayer? = null
         graphicsLayerTest(
@@ -181,7 +204,7 @@
                     graphicsContext.createGraphicsLayer().apply {
                         assertEquals(IntSize.Zero, this.size)
                         record { drawRect(Color.Red) }
-                        discardDisplayList()
+                        emulateTrimMemory()
                     }
                 drawLayer(layer!!)
             },
@@ -1440,6 +1463,28 @@
     }
 
     @Test
+    fun testReleaseWithNoReferencesDiscardsDisplaylist() {
+        graphicsLayerTest(
+            block = { graphicsContext ->
+                val layer = graphicsContext.createGraphicsLayer()
+                layer.record {
+                    // Intentionally cause an exception to be thrown during recording
+                    drawRect(Color.Red)
+                }
+
+                graphicsContext.releaseGraphicsLayer(layer)
+                // View layers don't have a hasDisplayList method to verify and by default
+                // returns true all the time. So if we have a RenderNode backed layer verify that
+                // the displaylist is discarded after it has been released
+                if (layer.impl !is GraphicsViewLayer) {
+                    assertFalse(layer.impl.hasDisplayList)
+                }
+            },
+            verify = { /* NO-OP */ }
+        )
+    }
+
+    @Test
     fun testEndRecordingAlwaysCalled() {
         graphicsLayerTest(
             block = { graphicsContext ->
@@ -1461,6 +1506,31 @@
         )
     }
 
+    @Test
+    fun testReleasingLayerDuringPersistenceLogicIsNotCrashing() {
+        lateinit var layer1: GraphicsLayer
+        lateinit var layer2: GraphicsLayer
+        graphicsLayerTest(
+            block = { context ->
+                // creating new layers will also schedule a persistence pass in Handler
+                layer1 = context.createGraphicsLayer()
+                layer2 = context.createGraphicsLayer()
+                layer2.record(Density(1f), Ltr, IntSize(10, 10)) { drawRect(Color.Red) }
+                layer1.record(Density(1f), Ltr, IntSize(10, 10)) { drawLayer(layer2) }
+                // we release layer2, but as it is drawn into layer1 its content is not discarded.
+                context.releaseGraphicsLayer(layer2)
+                // layer1 loses its content without us updating the dependency tracking
+                layer1.emulateTrimMemory()
+            },
+            verify = {
+                // just verifying there is no crash in layer persistence logic
+                // there was an issue where the next persistence logic will re-draw layer1 content
+                // and during this draw we fully release layer2. this was removing an item from
+                // a set which is currently being iterated on.
+            }
+        )
+    }
+
     private fun PixelMap.verifyQuadrants(
         topLeft: Color,
         topRight: Color,
@@ -1540,7 +1610,9 @@
                 testActivity = activity
                 activity.runOnUiThread {
                     // Layer persistence is only required on M+
-                    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
+                    if (
+                        Build.VERSION.SDK_INT > Build.VERSION_CODES.M && isLayerPersistenceEnabled
+                    ) {
                         assertTrue(androidGraphicsContext!!.isLayerManagerInitialized())
                     }
                     resumed.countDown()
@@ -1588,7 +1660,7 @@
             }
             assertTrue(detachLatch.await(3000, TimeUnit.MILLISECONDS))
             // Layer persistence is only required on M+
-            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
+            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M && isLayerPersistenceEnabled) {
                 assertFalse(androidGraphicsContext!!.isLayerManagerInitialized())
             }
             scenario?.moveToState(Lifecycle.State.DESTROYED)
diff --git a/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/AndroidGraphicsContext.android.kt b/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/AndroidGraphicsContext.android.kt
index 5081429..4b1ac8b 100644
--- a/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/AndroidGraphicsContext.android.kt
+++ b/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/AndroidGraphicsContext.android.kt
@@ -45,74 +45,89 @@
 private class AndroidGraphicsContext(private val ownerView: ViewGroup) : GraphicsContext {
 
     private val lock = Any()
-    private val layerManager = LayerManager(CanvasHolder())
+    private val layerManager: LayerManager?
     private var viewLayerContainer: DrawChildContainer? = null
     private var componentCallbackRegistered = false
     private var predrawListenerRegistered = false
 
-    private val componentCallback =
-        object : ComponentCallbacks2 {
-            override fun onConfigurationChanged(newConfig: Configuration) {
-                // NO-OP
-            }
-
-            override fun onLowMemory() {
-                // NO-OP
-            }
-
-            override fun onTrimMemory(level: Int) {
-                // See CacheManager.cpp. HWUI releases graphics resources whenever the trim memory
-                // callback exceed the level of TRIM_MEMORY_BACKGROUND so do the same here to
-                // release and recreate the internal ImageReader used to increment the ref count
-                // of internal RenderNodes
-                // Some devices skip straight to TRIM_COMPLETE so ensure we persist layers if
-                // we receive any trim memory callback that exceeds TRIM_MEMORY_BACKGROUND
-                if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) {
-                    // HardwareRenderer instances would be discarded by HWUI so we need to discard
-                    // the existing underlying ImageReader instance and do a placeholder render
-                    // to increment the refcount of any outstanding layers again the next time the
-                    // content is drawn
-                    if (!predrawListenerRegistered) {
-                        layerManager.destroy()
-                        ownerView.viewTreeObserver.addOnPreDrawListener(
-                            object : ViewTreeObserver.OnPreDrawListener {
-                                override fun onPreDraw(): Boolean {
-                                    layerManager.updateLayerPersistence()
-                                    ownerView.viewTreeObserver.removeOnPreDrawListener(this)
-                                    predrawListenerRegistered = false
-                                    return true
-                                }
-                            }
-                        )
-                        predrawListenerRegistered = true
-                    }
-                }
-            }
-        }
+    private val componentCallback: ComponentCallbacks2?
 
     init {
         // Register the component callbacks when the GraphicsContext is created
-        if (ownerView.isAttachedToWindow) {
-            registerComponentCallback(ownerView.context)
-        }
-        ownerView.addOnAttachStateChangeListener(
-            object : OnAttachStateChangeListener {
-                override fun onViewAttachedToWindow(v: View) {
-                    // If the View is attached to the window again, re-add the component callbacks
-                    registerComponentCallback(v.context)
-                }
+        if (enableLayerPersistence) {
+            layerManager = LayerManager(CanvasHolder())
+            componentCallback =
+                object : ComponentCallbacks2 {
+                    override fun onConfigurationChanged(newConfig: Configuration) {
+                        // NO-OP
+                    }
 
-                override fun onViewDetachedFromWindow(v: View) {
-                    // When the View is detached from the window, remove the component callbacks
-                    // used to listen to trim memory signals
-                    unregisterComponentCallback(v.context)
-                    layerManager.destroy()
+                    override fun onLowMemory() {
+                        // NO-OP
+                    }
+
+                    override fun onTrimMemory(level: Int) {
+                        // See CacheManager.cpp. HWUI releases graphics resources whenever the trim
+                        // memory
+                        // callback exceed the level of TRIM_MEMORY_BACKGROUND so do the same here
+                        // to
+                        // release and recreate the internal ImageReader used to increment the ref
+                        // count
+                        // of internal RenderNodes
+                        // Some devices skip straight to TRIM_COMPLETE so ensure we persist layers
+                        // if
+                        // we receive any trim memory callback that exceeds TRIM_MEMORY_BACKGROUND
+                        if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) {
+                            // HardwareRenderer instances would be discarded by HWUI so we need to
+                            // discard
+                            // the existing underlying ImageReader instance and do a placeholder
+                            // render
+                            // to increment the refcount of any outstanding layers again the next
+                            // time the
+                            // content is drawn
+                            if (!predrawListenerRegistered) {
+                                layerManager.destroy()
+                                ownerView.viewTreeObserver.addOnPreDrawListener(
+                                    object : ViewTreeObserver.OnPreDrawListener {
+                                        override fun onPreDraw(): Boolean {
+                                            layerManager.updateLayerPersistence()
+                                            ownerView.viewTreeObserver.removeOnPreDrawListener(this)
+                                            predrawListenerRegistered = false
+                                            return true
+                                        }
+                                    }
+                                )
+                                predrawListenerRegistered = true
+                            }
+                        }
+                    }
                 }
+            if (ownerView.isAttachedToWindow) {
+                registerComponentCallback(ownerView.context)
             }
-        )
+            ownerView.addOnAttachStateChangeListener(
+                object : OnAttachStateChangeListener {
+                    override fun onViewAttachedToWindow(v: View) {
+                        // If the View is attached to the window again, re-add the component
+                        // callbacks
+                        registerComponentCallback(v.context)
+                    }
+
+                    override fun onViewDetachedFromWindow(v: View) {
+                        // When the View is detached from the window, remove the component callbacks
+                        // used to listen to trim memory signals
+                        unregisterComponentCallback(v.context)
+                        layerManager.destroy()
+                    }
+                }
+            )
+        } else {
+            layerManager = null
+            componentCallback = null
+        }
     }
 
-    fun isLayerManagerInitialized(): Boolean = layerManager.hasImageReader()
+    fun isLayerManagerInitialized(): Boolean = layerManager?.hasImageReader() ?: false
 
     private fun registerComponentCallback(context: Context) {
         if (!componentCallbackRegistered) {
@@ -154,7 +169,9 @@
                     GraphicsViewLayer(obtainViewLayerContainer(ownerView), ownerId)
                 }
             val layer = GraphicsLayer(layerImpl, layerManager)
-            layerManager.persist(layer)
+            if (enableLayerPersistence) {
+                layerManager?.persist(layer)
+            }
             return layer
         }
     }
@@ -184,6 +201,8 @@
 
     internal companion object {
         var isRenderNodeCompatible: Boolean = true
+
+        const val enableLayerPersistence = false
     }
 
     @RequiresApi(29)
@@ -196,3 +215,6 @@
 
 internal fun GraphicsContext.isLayerManagerInitialized(): Boolean =
     (this as AndroidGraphicsContext).isLayerManagerInitialized()
+
+internal val isLayerPersistenceEnabled: Boolean
+    get() = AndroidGraphicsContext.enableLayerPersistence
diff --git a/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/layer/AndroidGraphicsLayer.android.kt b/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/layer/AndroidGraphicsLayer.android.kt
index bbd27e7..ddcd1a2 100644
--- a/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/layer/AndroidGraphicsLayer.android.kt
+++ b/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/layer/AndroidGraphicsLayer.android.kt
@@ -46,10 +46,14 @@
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.toSize
 import androidx.compose.ui.util.fastRoundToInt
+import org.jetbrains.annotations.TestOnly
 
 @Suppress("NotCloseable")
 actual class GraphicsLayer
-internal constructor(internal val impl: GraphicsLayerImpl, private val layerManager: LayerManager) {
+internal constructor(
+    internal val impl: GraphicsLayerImpl,
+    private val layerManager: LayerManager?
+) {
     private var density = DefaultDensity
     private var layoutDirection = LayoutDirection.Ltr
     private var drawBlock: DrawScope.() -> Unit = {}
@@ -638,7 +642,11 @@
 
     private fun discardContentIfReleasedAndHaveNoParentLayerUsages() {
         if (isReleased && parentLayerUsages == 0) {
-            layerManager.release(this)
+            if (layerManager != null) {
+                layerManager.release(this)
+            } else {
+                discardDisplayList()
+            }
         }
     }
 
@@ -653,6 +661,16 @@
     }
 
     /**
+     * When the system is sending trim memory request all the render nodes will discard their
+     * display list. in this case we are not being notified about that and don't update
+     * [childDependenciesTracker], as it is done when we call [discardDisplayList] manually
+     */
+    @TestOnly
+    internal fun emulateTrimMemory() {
+        impl.discardDisplayList()
+    }
+
+    /**
      * The ID of the layer. This is used by tooling to match a layer to the associated LayoutNode.
      */
     val layerId: Long
diff --git a/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/layer/GraphicsViewLayer.android.kt b/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/layer/GraphicsViewLayer.android.kt
index 26389c5..6ae9971 100644
--- a/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/layer/GraphicsViewLayer.android.kt
+++ b/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/layer/GraphicsViewLayer.android.kt
@@ -419,6 +419,9 @@
         layer: GraphicsLayer,
         block: DrawScope.() -> Unit
     ) {
+        if (viewLayer.parent == null) {
+            layerContainer.addView(viewLayer)
+        }
         viewLayer.setDrawParams(density, layoutDirection, layer, block)
         // According to View#canHaveDisplaylist, a View can only have a displaylist
         // if it is attached and there is a valid ThreadedRenderer instance on the corresponding
diff --git a/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/layer/LayerManager.android.kt b/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/layer/LayerManager.android.kt
index ce86b5f..5b59be4 100644
--- a/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/layer/LayerManager.android.kt
+++ b/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/layer/LayerManager.android.kt
@@ -23,7 +23,9 @@
 import android.os.Message
 import android.view.Surface
 import androidx.annotation.RequiresApi
+import androidx.collection.MutableObjectList
 import androidx.collection.ScatterSet
+import androidx.collection.mutableObjectListOf
 import androidx.collection.mutableScatterSetOf
 import androidx.compose.ui.graphics.CanvasHolder
 import androidx.core.os.HandlerCompat
@@ -51,6 +53,9 @@
             true
         }
 
+    private var postponedReleaseRequests: MutableObjectList<GraphicsLayer>? = null
+    private var persistenceIterationInProgress = false
+
     fun persist(layer: GraphicsLayer) {
         layerSet.add(layer)
         if (!handler.hasMessages(0)) {
@@ -65,8 +70,17 @@
     }
 
     fun release(layer: GraphicsLayer) {
-        if (layerSet.remove(layer)) {
-            layer.discardDisplayList()
+        if (!persistenceIterationInProgress) {
+            if (layerSet.remove(layer)) {
+                layer.discardDisplayList()
+            }
+        } else {
+            // we can't remove an item from a list, which is currently being iterated.
+            // so we use a second list to remember such requests
+            val requests =
+                postponedReleaseRequests
+                    ?: mutableObjectListOf<GraphicsLayer>().also { postponedReleaseRequests = it }
+            requests.add(layer)
         }
     }
 
@@ -88,7 +102,9 @@
         if (shouldPersistLayers) {
             val reader =
                 imageReader
-                    ?: ImageReader.newInstance(1, 1, PixelFormat.RGBA_8888, 1)
+                    // 3 buffers is the default max buffers amount for a swapchain. The buffers are
+                    // lazily allocated only if one is not available when it is requested.
+                    ?: ImageReader.newInstance(1, 1, PixelFormat.RGBA_8888, 3)
                         .apply {
                             // We don't care about the result, but release the buffer back to the
                             // queue
@@ -103,12 +119,19 @@
             val surface = reader.surface
             val canvas = LockHardwareCanvasHelper.lockHardwareCanvas(surface)
 
+            persistenceIterationInProgress = true
             canvasHolder.drawInto(canvas) {
                 canvas.save()
                 canvas.clipRect(0, 0, 1, 1)
                 layers.forEach { layer -> layer.drawForPersistence(this) }
                 canvas.restore()
             }
+            persistenceIterationInProgress = false
+            val requests = postponedReleaseRequests
+            if (requests != null && requests.isNotEmpty()) {
+                requests.forEach { release(it) }
+                requests.clear()
+            }
             surface.unlockCanvasAndPost(canvas)
         }
     }
diff --git a/compose/ui/ui-graphics/src/androidUnitTest/kotlin/androidx/compose/ui/graphics/layer/RobolectricGraphicsLayerTest.kt b/compose/ui/ui-graphics/src/androidUnitTest/kotlin/androidx/compose/ui/graphics/layer/RobolectricGraphicsLayerTest.kt
index 851a970..087a18c 100644
--- a/compose/ui/ui-graphics/src/androidUnitTest/kotlin/androidx/compose/ui/graphics/layer/RobolectricGraphicsLayerTest.kt
+++ b/compose/ui/ui-graphics/src/androidUnitTest/kotlin/androidx/compose/ui/graphics/layer/RobolectricGraphicsLayerTest.kt
@@ -152,7 +152,7 @@
                     graphicsContext.createGraphicsLayer().apply {
                         assertEquals(IntSize.Zero, this.size)
                         record { drawRect(Color.Red) }
-                        discardDisplayList()
+                        emulateTrimMemory()
                     }
                 drawLayer(layer!!)
             },
diff --git a/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/DesktopGraphicsTest.kt b/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/DesktopGraphicsTest.kt
deleted file mode 100644
index a8613f6..0000000
--- a/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/DesktopGraphicsTest.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.graphics
-
-import androidx.compose.ui.test.InternalTestApi
-import androidx.compose.ui.test.junit4.DesktopScreenshotTestRule
-import org.jetbrains.skia.Surface
-import org.junit.After
-import org.junit.Rule
-
-@OptIn(InternalTestApi::class)
-abstract class DesktopGraphicsTest {
-    @get:Rule val screenshotRule = DesktopScreenshotTestRule("compose/ui/ui-desktop/graphics")
-
-    private var _surface: Surface? = null
-    protected val surface
-        get() = _surface!!
-
-    protected val redPaint = Paint().apply { color = Color.Red }
-    protected val bluePaint = Paint().apply { color = Color.Blue }
-    protected val greenPaint = Paint().apply { color = Color.Green }
-    protected val cyanPaint = Paint().apply { color = Color.Cyan }
-    protected val magentaPaint = Paint().apply { color = Color.Magenta }
-    protected val yellowPaint = Paint().apply { color = Color.Yellow }
-
-    @Suppress("SameParameterValue")
-    protected fun initCanvas(widthPx: Int, heightPx: Int): Canvas {
-        require(_surface == null)
-        _surface = Surface.makeRasterN32Premul(widthPx, heightPx)
-        return SkiaBackedCanvas(_surface!!.canvas)
-    }
-
-    @After
-    fun teardown() {
-        _surface?.close()
-    }
-}
diff --git a/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/DesktopImageBitmapTest.kt b/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/DesktopImageBitmapTest.kt
deleted file mode 100644
index 0c4dbec..0000000
--- a/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/DesktopImageBitmapTest.kt
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.graphics
-
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.graphics.colorspace.ColorSpaces
-import androidx.compose.ui.test.InternalTestApi
-import com.google.common.truth.Truth.assertThat
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertTrue
-import org.junit.Test
-
-@OptIn(InternalTestApi::class)
-class DesktopImageBitmapTest : DesktopGraphicsTest() {
-    private val canvas: Canvas = initCanvas(widthPx = 16, heightPx = 16)
-
-    @Test
-    fun drawOnImageBitmapAlpha8() {
-        val asset = ImageBitmap(width = 8, height = 8, config = ImageBitmapConfig.Alpha8)
-        val assetCanvas = Canvas(asset)
-        assetCanvas.drawImage(
-            loadResourceBitmap("androidx/compose/desktop/test.png"),
-            Offset(4f, 4f),
-            Paint()
-        )
-        canvas.drawImage(asset, Offset(4f, 4f), Paint())
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun drawOnImageBitmapDisplayP3() {
-        val asset = ImageBitmap(width = 8, height = 8, colorSpace = ColorSpaces.DisplayP3)
-        val assetCanvas = Canvas(asset)
-        assetCanvas.drawImage(
-            loadResourceBitmap("androidx/compose/desktop/test.png"),
-            Offset(4f, 4f),
-            Paint()
-        )
-        canvas.drawImage(asset, Offset(4f, 4f), Paint())
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun drawOnImageBitmap() {
-        val asset = ImageBitmap(width = 8, height = 8)
-        val assetCanvas = Canvas(asset)
-        assetCanvas.drawImage(
-            loadResourceBitmap("androidx/compose/desktop/test.png"),
-            Offset(4f, 4f),
-            Paint()
-        )
-        canvas.drawImage(asset, Offset(4f, 4f), Paint())
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test(expected = RuntimeException::class)
-    fun `cannot draw on loaded ImageBitmap`() {
-        val asset = loadResourceBitmap("androidx/compose/desktop/test.png")
-        Canvas(asset)
-    }
-
-    @Test
-    fun `attributes of loaded asset`() {
-        val asset = loadResourceBitmap("androidx/compose/desktop/test.png")
-        assertEquals(8, asset.width)
-        assertEquals(8, asset.height)
-        assertTrue(asset.hasAlpha)
-        assertEquals(ImageBitmapConfig.Argb8888, asset.config)
-        assertEquals(ColorSpaces.Srgb, asset.colorSpace)
-    }
-
-    @Test
-    fun `read pixels of loaded asset`() {
-        val asset = loadResourceBitmap("androidx/compose/desktop/test.png")
-
-        val array = IntArray(5)
-        asset.readPixels(array, startX = 0, startY = 0, width = 1, height = 1, bufferOffset = 0)
-        assertThat(array.map(::toHexString))
-            .isEqualTo(listOf("ffff0000", "00000000", "00000000", "00000000", "00000000"))
-
-        asset.readPixels(array, startX = 3, startY = 3, width = 2, height = 2, bufferOffset = 1)
-        assertThat(array.map(::toHexString))
-            .isEqualTo(listOf("ffff0000", "ffff00ff", "ffffff00", "ff000000", "80000000"))
-    }
-
-    @Test
-    fun `read pixels of loaded asset with different stride`() {
-        val asset = loadResourceBitmap("androidx/compose/desktop/test.png")
-
-        val array = IntArray(6)
-        asset.readPixels(array, startX = 3, startY = 3, width = 2, height = 2, stride = 3)
-        assertThat(array.map(::toHexString))
-            .isEqualTo(
-                listOf("ffff00ff", "ffffff00", "00000000", "ff000000", "80000000", "00000000")
-            )
-    }
-
-    private fun toHexString(num: Int) = "%08x".format(num)
-}
diff --git a/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/DesktopPaintTest.kt b/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/DesktopPaintTest.kt
deleted file mode 100644
index 548aebc..0000000
--- a/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/DesktopPaintTest.kt
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.graphics
-
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.test.InternalTestApi
-import androidx.compose.ui.unit.IntOffset
-import androidx.compose.ui.unit.IntSize
-import org.junit.Assert.assertEquals
-import org.junit.Assume.assumeTrue
-import org.junit.Test
-
-@OptIn(InternalTestApi::class)
-class DesktopPaintTest : DesktopGraphicsTest() {
-    private val canvas: Canvas = initCanvas(widthPx = 16, heightPx = 16)
-
-    @Test
-    fun initialParameters() {
-        val paint = Paint()
-
-        assertEquals(Color.Black, paint.color)
-        assertEquals(1f, paint.alpha)
-        assertEquals(PaintingStyle.Fill, paint.style)
-        assertEquals(0f, paint.strokeWidth)
-        assertEquals(StrokeCap.Butt, paint.strokeCap)
-        assertEquals(0f, paint.strokeMiterLimit)
-        assertEquals(StrokeJoin.Round, paint.strokeJoin)
-        assertEquals(true, paint.isAntiAlias)
-        assertEquals(FilterQuality.Medium, paint.filterQuality)
-        assertEquals(BlendMode.SrcOver, paint.blendMode)
-        assertEquals(null, paint.colorFilter)
-        assertEquals(null, paint.shader)
-    }
-
-    @Test
-    fun blendModePlus() {
-        canvas.drawRect(left = 0f, top = 0f, right = 16f, bottom = 16f, paint = redPaint)
-        canvas.drawRect(
-            left = 4f,
-            top = 4f,
-            right = 12f,
-            bottom = 12f,
-            paint =
-                Paint().apply {
-                    color = Color.Blue
-                    blendMode = BlendMode.Plus
-                }
-        )
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun blendModeMultiply() {
-        canvas.drawRect(left = 0f, top = 0f, right = 16f, bottom = 16f, paint = redPaint)
-        canvas.drawRect(
-            left = 4f,
-            top = 4f,
-            right = 12f,
-            bottom = 12f,
-            paint =
-                Paint().apply {
-                    color = Color.Gray
-                    blendMode = BlendMode.Multiply
-                }
-        )
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun colorFilter() {
-        canvas.drawRect(left = 0f, top = 0f, right = 16f, bottom = 16f, paint = redPaint)
-
-        canvas.drawImage(
-            image = loadResourceBitmap("androidx/compose/desktop/test.png"),
-            topLeftOffset = Offset(2f, 4f),
-            paint = Paint().apply { colorFilter = ColorFilter.tint(Color.Blue, BlendMode.Plus) }
-        )
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun filterQuality() {
-        assumeTrue(isWindows || isLinux)
-
-        canvas.drawImageRect(
-            image = loadResourceBitmap("androidx/compose/desktop/test.png"),
-            srcOffset = IntOffset(0, 2),
-            srcSize = IntSize(2, 4),
-            dstOffset = IntOffset(0, 4),
-            dstSize = IntSize(4, 12),
-            paint = redPaint.apply { filterQuality = FilterQuality.None }
-        )
-        canvas.drawImageRect(
-            image = loadResourceBitmap("androidx/compose/desktop/test.png"),
-            srcOffset = IntOffset(0, 2),
-            srcSize = IntSize(2, 4),
-            dstOffset = IntOffset(4, 4),
-            dstSize = IntSize(4, 12),
-            paint = redPaint.apply { filterQuality = FilterQuality.Low }
-        )
-        canvas.drawImageRect(
-            image = loadResourceBitmap("androidx/compose/desktop/test.png"),
-            srcOffset = IntOffset(0, 2),
-            srcSize = IntSize(2, 4),
-            dstOffset = IntOffset(8, 4),
-            dstSize = IntSize(4, 12),
-            paint = redPaint.apply { filterQuality = FilterQuality.High }
-        )
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun `filterQuality with scaled Canvas`() {
-        assumeTrue(isWindows || isLinux)
-
-        canvas.scale(2f, 2f)
-
-        canvas.drawImageRect(
-            image = loadResourceBitmap("androidx/compose/desktop/test.png"),
-            srcOffset = IntOffset(0, 2),
-            srcSize = IntSize(2, 4),
-            dstOffset = IntOffset(0, 2),
-            dstSize = IntSize(2, 6),
-            paint = redPaint.apply { filterQuality = FilterQuality.None }
-        )
-        canvas.drawImageRect(
-            image = loadResourceBitmap("androidx/compose/desktop/test.png"),
-            srcOffset = IntOffset(0, 2),
-            srcSize = IntSize(2, 4),
-            dstOffset = IntOffset(2, 2),
-            dstSize = IntSize(2, 6),
-            paint = redPaint.apply { filterQuality = FilterQuality.Low }
-        )
-        canvas.drawImageRect(
-            image = loadResourceBitmap("androidx/compose/desktop/test.png"),
-            srcOffset = IntOffset(0, 2),
-            srcSize = IntSize(2, 4),
-            dstOffset = IntOffset(4, 2),
-            dstSize = IntSize(2, 6),
-            paint = redPaint.apply { filterQuality = FilterQuality.High }
-        )
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun linearGradientShader() {
-        canvas.drawRect(left = 0f, top = 0f, right = 16f, bottom = 16f, paint = redPaint)
-
-        canvas.drawRect(
-            left = 2f,
-            top = 2f,
-            right = 14f,
-            bottom = 14f,
-            paint =
-                Paint().apply {
-                    shader =
-                        LinearGradientShader(
-                            from = Offset(0f, 0f),
-                            to = Offset(6f, 6f),
-                            colors = listOf(Color.Blue, Color.Green),
-                            tileMode = TileMode.Mirror
-                        )
-                }
-        )
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun linearGradientShaderWithStops() {
-        canvas.drawRect(left = 0f, top = 0f, right = 16f, bottom = 16f, paint = redPaint)
-
-        canvas.drawRect(
-            left = 1f,
-            top = 2f,
-            right = 14f,
-            bottom = 15f,
-            paint =
-                Paint().apply {
-                    shader =
-                        LinearGradientShader(
-                            from = Offset(0f, 0f),
-                            to = Offset(12f, 0f),
-                            colorStops = listOf(0f, 0.25f, 1f),
-                            colors = listOf(Color.Blue, Color.Green, Color.Yellow),
-                            tileMode = TileMode.Mirror
-                        )
-                }
-        )
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun radialGradientShader() {
-        canvas.drawRect(left = 0f, top = 0f, right = 16f, bottom = 16f, paint = redPaint)
-
-        canvas.drawRect(
-            left = 2f,
-            top = 2f,
-            right = 14f,
-            bottom = 14f,
-            paint =
-                Paint().apply {
-                    shader =
-                        RadialGradientShader(
-                            center = Offset(4f, 8f),
-                            radius = 8f,
-                            colors = listOf(Color.Blue, Color.Green),
-                            tileMode = TileMode.Clamp
-                        )
-                }
-        )
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun sweepGradientShader() {
-        canvas.drawRect(left = 0f, top = 0f, right = 16f, bottom = 16f, paint = redPaint)
-
-        canvas.drawRect(
-            left = 2f,
-            top = 2f,
-            right = 14f,
-            bottom = 14f,
-            paint =
-                Paint().apply {
-                    shader =
-                        SweepGradientShader(
-                            center = Offset(4f, 8f),
-                            colors = listOf(Color.Blue, Color.Green)
-                        )
-                }
-        )
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun imageShader() {
-        canvas.drawRect(left = 0f, top = 0f, right = 16f, bottom = 16f, paint = redPaint)
-
-        canvas.drawRect(
-            left = 2f,
-            top = 2f,
-            right = 14f,
-            bottom = 14f,
-            paint =
-                Paint().apply {
-                    shader =
-                        ImageShader(
-                            loadResourceBitmap("androidx/compose/desktop/test.png"),
-                            tileModeX = TileMode.Clamp,
-                            tileModeY = TileMode.Repeated
-                        )
-                }
-        )
-
-        screenshotRule.snap(surface)
-    }
-}
diff --git a/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/DesktopPathTest.kt b/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/DesktopPathTest.kt
deleted file mode 100644
index c2c1789..0000000
--- a/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/DesktopPathTest.kt
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.graphics
-
-import androidx.compose.ui.geometry.Rect
-import androidx.compose.ui.geometry.RoundRect
-import androidx.compose.ui.test.InternalTestApi
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertFalse
-import org.junit.Assert.assertTrue
-import org.junit.Test
-
-@OptIn(InternalTestApi::class)
-class DesktopPathTest : DesktopGraphicsTest() {
-    private val canvas: Canvas = initCanvas(widthPx = 16, heightPx = 16)
-
-    @Test
-    fun arc() {
-        val path =
-            Path().apply {
-                addArc(Rect(0f, 0f, 16f, 16f), 0f, 90f)
-                arcTo(Rect(0f, 0f, 16f, 16f), 90f, 90f, true)
-            }
-
-        canvas.drawPath(path, redPaint)
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun clipPath() {
-        val path = Path().apply { addOval(Rect(0f, 0f, 16f, 8f)) }
-
-        canvas.withSave {
-            canvas.clipPath(path, ClipOp.Intersect)
-            canvas.drawRect(0f, 0f, 16f, 16f, redPaint)
-        }
-
-        canvas.withSave {
-            canvas.clipPath(path, ClipOp.Difference)
-            canvas.drawRect(0f, 0f, 16f, 16f, bluePaint)
-        }
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun bezier() {
-        val path = Path().apply { quadraticTo(0f, 16f, 16f, 16f) }
-
-        canvas.drawPath(path, redPaint)
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun cubic() {
-        val path = Path().apply { cubicTo(0f, 12f, 0f, 16f, 16f, 16f) }
-
-        canvas.drawPath(path, redPaint)
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun figures() {
-        val path =
-            Path().apply {
-                addOval(Rect(0f, 0f, 8f, 4f))
-                addRect(Rect(12f, 0f, 16f, 8f))
-                addRoundRect(RoundRect(0f, 8f, 4f, 16f, 4f, 4f))
-            }
-
-        canvas.drawPath(path, redPaint)
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun fillTypeEvenOdd() {
-        val path =
-            Path().apply {
-                fillType = PathFillType.EvenOdd
-                addRect(Rect(0f, 0f, 8f, 8f))
-                addRect(Rect(4f, 4f, 12f, 12f))
-            }
-
-        canvas.drawPath(path, redPaint)
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun fillTypeNonZero() {
-        val path =
-            Path().apply {
-                addRect(Rect(0f, 0f, 8f, 8f))
-                addRect(Rect(4f, 4f, 12f, 12f))
-            }
-
-        assertEquals(PathFillType.NonZero, path.fillType)
-        canvas.drawPath(path, redPaint)
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun linesFill() {
-        val path =
-            Path().apply {
-                moveTo(0f, 0f)
-                lineTo(8f, 8f)
-                lineTo(0f, 8f)
-
-                moveTo(8f, 8f)
-                lineTo(8f, 16f)
-                lineTo(16f, 16f)
-                relativeLineTo(0f, -8f)
-            }
-
-        assertEquals(PaintingStyle.Fill, redPaint.style)
-        canvas.drawPath(path, redPaint)
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun linesStroke() {
-        val path =
-            Path().apply {
-                moveTo(0f, 0f)
-                lineTo(8f, 8f)
-                lineTo(0f, 8f)
-                close()
-
-                moveTo(8f, 8f)
-                lineTo(8f, 16f)
-                lineTo(16f, 16f)
-                relativeLineTo(0f, -8f)
-            }
-
-        canvas.drawPath(
-            path,
-            redPaint.apply {
-                style = PaintingStyle.Stroke
-                strokeWidth = 2f
-            }
-        )
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun isEmpty() {
-        val path = Path()
-        assertEquals(true, path.isEmpty)
-
-        path.addRect(Rect(0f, 0f, 16f, 16f))
-        assertEquals(false, path.isEmpty)
-    }
-
-    @Test
-    fun isConvex() {
-        val path = Path()
-        assertEquals(true, path.isConvex)
-
-        path.addRect(Rect(0f, 0f, 8f, 8f))
-        assertEquals(true, path.isConvex)
-
-        path.addRect(Rect(8f, 8f, 16f, 16f))
-        assertEquals(false, path.isConvex)
-    }
-
-    @Test
-    fun getBounds() {
-        val path = Path()
-        assertEquals(Rect(0f, 0f, 0f, 0f), path.getBounds())
-
-        path.addRect(Rect(0f, 0f, 8f, 8f))
-        assertEquals(Rect(0f, 0f, 8f, 8f), path.getBounds())
-
-        path.addRect(Rect(8f, 8f, 16f, 16f))
-        assertEquals(Rect(0f, 0f, 16f, 16f), path.getBounds())
-    }
-
-    @Test
-    fun `initial parameters`() {
-        val path = Path()
-
-        assertEquals(PathFillType.NonZero, path.fillType)
-    }
-
-    @Test
-    fun `reset should preserve fillType`() {
-        val path = Path()
-
-        path.fillType = PathFillType.EvenOdd
-        path.reset()
-
-        assertEquals(PathFillType.EvenOdd, path.fillType)
-    }
-
-    @Test
-    fun testRewind() {
-        val path = Path().apply { addRect(Rect(0f, 0f, 100f, 200f)) }
-        assertFalse(path.isEmpty)
-
-        path.rewind()
-
-        assertTrue(path.isEmpty)
-    }
-
-    @Test
-    fun testTransform() {
-        val width = 100
-        val height = 100
-        val image = ImageBitmap(width, height)
-        val canvas = Canvas(image)
-
-        val path =
-            Path().apply {
-                addRect(Rect(0f, 0f, 50f, 50f))
-                transform(Matrix().apply { translate(50f, 50f) })
-            }
-
-        val paint = Paint().apply { color = Color.Black }
-        canvas.drawRect(0f, 0f, width.toFloat(), height.toFloat(), paint)
-        paint.color = Color.Red
-        canvas.drawPath(path, paint)
-
-        image.toPixelMap().apply {
-            assertEquals(Color.Black, this[width / 2 - 3, height / 2 - 3])
-            assertEquals(Color.Black, this[width / 2, height / 2 - 3])
-            assertEquals(Color.Black, this[width / 2 - 3, height / 2])
-
-            assertEquals(Color.Red, this[width / 2 + 2, height / 2 + 2])
-            assertEquals(Color.Red, this[width - 2, height / 2 + 2])
-            assertEquals(Color.Red, this[width - 2, height - 2])
-            assertEquals(Color.Red, this[width / 2 + 2, height - 2])
-        }
-    }
-}
diff --git a/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/TestUtils.kt b/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/TestUtils.kt
deleted file mode 100644
index 13aedbe..0000000
--- a/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/TestUtils.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.graphics
-
-import androidx.compose.ui.res.loadImageBitmap
-import androidx.compose.ui.res.useResource
-
-private val os = System.getProperty("os.name")!!.lowercase()
-internal val isLinux = os.startsWith("linux")
-internal val isWindows = os.startsWith("win")
-internal val isMacOs = os.startsWith("mac")
-
-fun loadResourceBitmap(path: String) = useResource(path, ::loadImageBitmap)
diff --git a/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/canvas/DesktopCanvasPointsTest.kt b/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/canvas/DesktopCanvasPointsTest.kt
deleted file mode 100644
index 803f8a7..0000000
--- a/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/canvas/DesktopCanvasPointsTest.kt
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.graphics.canvas
-
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.graphics.Canvas
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.DesktopGraphicsTest
-import androidx.compose.ui.graphics.Paint
-import androidx.compose.ui.graphics.PointMode
-import androidx.compose.ui.graphics.StrokeCap
-import androidx.compose.ui.test.InternalTestApi
-import org.junit.Test
-
-@OptIn(InternalTestApi::class)
-class DesktopCanvasPointsTest : DesktopGraphicsTest() {
-    private val canvas: Canvas = initCanvas(widthPx = 16, heightPx = 16)
-
-    @Test
-    fun drawLines() {
-        canvas.drawPoints(
-            pointMode = PointMode.Lines,
-            points = listOf(Offset(0f, 8f), Offset(8f, 0f), Offset(8f, 8f), Offset(0f, 8f)),
-            paint =
-                Paint().apply {
-                    color = Color.Red
-                    strokeWidth = 2f
-                }
-        )
-
-        canvas.translate(6f, 6f)
-        canvas.drawPoints(
-            pointMode = PointMode.Lines,
-            points = listOf(Offset(0f, 8f), Offset(8f, 0f), Offset(8f, 8f), Offset(0f, 8f)),
-            paint =
-                Paint().apply {
-                    color = Color.Green
-                    strokeWidth = 2f
-                    strokeCap = StrokeCap.Round
-                }
-        )
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun drawPoints() {
-        canvas.drawPoints(
-            pointMode = PointMode.Points,
-            points = listOf(Offset(0f, 2f), Offset(2f, 0f)),
-            paint =
-                Paint().apply {
-                    color = Color.Red
-                    strokeWidth = 2f
-                    strokeCap = StrokeCap.Butt
-                }
-        )
-        canvas.drawRawPoints(
-            pointMode = PointMode.Points,
-            points = floatArrayOf(4f, 4f, 8f, 8f),
-            paint =
-                Paint().apply {
-                    color = Color.Blue
-                    strokeWidth = 4f
-                    strokeCap = StrokeCap.Round
-                }
-        )
-        canvas.drawPoints(
-            pointMode = PointMode.Points,
-            points = listOf(Offset(4f, 0f)),
-            paint =
-                Paint().apply {
-                    color = Color.Green
-                    strokeWidth = 2f
-                    strokeCap = StrokeCap.Square
-                }
-        )
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun drawPolygons() {
-        canvas.drawPoints(
-            pointMode = PointMode.Polygon,
-            points = listOf(Offset(0f, 8f), Offset(8f, 0f), Offset(8f, 8f), Offset(0f, 8f)),
-            paint =
-                Paint().apply {
-                    color = Color.Red
-                    strokeWidth = 2f
-                }
-        )
-
-        canvas.translate(6f, 6f)
-        canvas.drawPoints(
-            pointMode = PointMode.Polygon,
-            points = listOf(Offset(0f, 8f), Offset(8f, 0f), Offset(8f, 8f), Offset(0f, 8f)),
-            paint =
-                Paint().apply {
-                    color = Color.Green
-                    strokeWidth = 2f
-                    strokeCap = StrokeCap.Round
-                }
-        )
-
-        screenshotRule.snap(surface)
-    }
-}
diff --git a/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/canvas/DesktopCanvasTest.kt b/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/canvas/DesktopCanvasTest.kt
deleted file mode 100644
index 4cc39f3..0000000
--- a/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/canvas/DesktopCanvasTest.kt
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.graphics.canvas
-
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.geometry.Rect
-import androidx.compose.ui.graphics.BlendMode
-import androidx.compose.ui.graphics.Canvas
-import androidx.compose.ui.graphics.ClipOp
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.DesktopGraphicsTest
-import androidx.compose.ui.graphics.FilterQuality
-import androidx.compose.ui.graphics.Matrix
-import androidx.compose.ui.graphics.Paint
-import androidx.compose.ui.graphics.StrokeCap
-import androidx.compose.ui.graphics.VertexMode
-import androidx.compose.ui.graphics.Vertices
-import androidx.compose.ui.graphics.loadResourceBitmap
-import androidx.compose.ui.graphics.withSave
-import androidx.compose.ui.graphics.withSaveLayer
-import androidx.compose.ui.test.InternalTestApi
-import androidx.compose.ui.unit.IntOffset
-import androidx.compose.ui.unit.IntSize
-import org.junit.Test
-
-@OptIn(InternalTestApi::class)
-class DesktopCanvasTest : DesktopGraphicsTest() {
-    private val canvas: Canvas = initCanvas(widthPx = 16, heightPx = 16)
-
-    @Test
-    fun drawArc() {
-        canvas.drawArc(
-            left = 0f,
-            top = 0f,
-            right = 16f,
-            bottom = 16f,
-            startAngle = 0f,
-            sweepAngle = 90f,
-            useCenter = true,
-            paint = redPaint
-        )
-        canvas.drawArc(
-            left = 0f,
-            top = 0f,
-            right = 16f,
-            bottom = 16f,
-            startAngle = 90f,
-            sweepAngle = 90f,
-            useCenter = true,
-            paint = bluePaint
-        )
-        canvas.drawArc(
-            left = 0f,
-            top = 0f,
-            right = 16f,
-            bottom = 16f,
-            startAngle = 180f,
-            sweepAngle = 90f,
-            useCenter = false,
-            paint = greenPaint
-        )
-        canvas.drawArc(
-            left = 0f,
-            top = 0f,
-            right = 16f,
-            bottom = 16f,
-            startAngle = 270f,
-            sweepAngle = 90f,
-            useCenter = false,
-            paint = cyanPaint
-        )
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun drawCircle() {
-        canvas.drawCircle(Offset(8f, 8f), radius = 4f, paint = redPaint)
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun drawImage() {
-        canvas.drawImage(
-            image = loadResourceBitmap("androidx/compose/desktop/test.png"),
-            topLeftOffset = Offset(2f, 4f),
-            paint = redPaint
-        )
-        canvas.drawImage(
-            image = loadResourceBitmap("androidx/compose/desktop/test.png"),
-            topLeftOffset = Offset(-2f, 0f),
-            paint = redPaint
-        )
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun drawImageRect() {
-        canvas.drawImageRect(
-            image = loadResourceBitmap("androidx/compose/desktop/test.png"),
-            srcOffset = IntOffset(0, 2),
-            srcSize = IntSize(2, 4),
-            dstOffset = IntOffset(0, 4),
-            dstSize = IntSize(4, 12),
-            paint = redPaint.apply { filterQuality = FilterQuality.None }
-        )
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun drawLine() {
-        canvas.drawLine(
-            Offset(-4f, -4f),
-            Offset(4f, 4f),
-            Paint().apply {
-                color = Color.Red
-                strokeWidth = 1f
-                strokeCap = StrokeCap.Butt
-            }
-        )
-        canvas.drawLine(
-            Offset(8f, 4f),
-            Offset(8f, 12f),
-            Paint().apply {
-                color = Color.Blue
-                strokeWidth = 4f
-                strokeCap = StrokeCap.Butt
-            }
-        )
-        canvas.drawLine(
-            Offset(12f, 4f),
-            Offset(12f, 12f),
-            Paint().apply {
-                color = Color.Green
-                strokeWidth = 4f
-                strokeCap = StrokeCap.Round
-            }
-        )
-        canvas.drawLine(
-            Offset(4f, 4f),
-            Offset(4f, 12f),
-            Paint().apply {
-                color = Color.Black.copy(alpha = 0.5f)
-                strokeWidth = 4f
-                strokeCap = StrokeCap.Square
-            }
-        )
-
-        // should draw antialiased two-pixel line
-        canvas.drawLine(
-            Offset(4f, 4f),
-            Offset(4f, 12f),
-            Paint().apply {
-                color = Color.Yellow
-                strokeWidth = 1f
-                strokeCap = StrokeCap.Butt
-            }
-        )
-
-        // should draw aliased one-pixel line
-        canvas.drawLine(
-            Offset(4f, 4f),
-            Offset(4f, 12f),
-            Paint().apply {
-                color = Color.Yellow
-                strokeWidth = 1f
-                strokeCap = StrokeCap.Butt
-                isAntiAlias = false
-            }
-        )
-
-        // shouldn't draw any line
-        canvas.drawLine(
-            Offset(4f, 4f),
-            Offset(4f, 12f),
-            Paint().apply {
-                color = Color.Yellow
-                strokeWidth = 0f
-                strokeCap = StrokeCap.Butt
-                isAntiAlias = false
-            }
-        )
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun drawOval() {
-        canvas.drawOval(left = 0f, top = 4f, right = 16f, bottom = 12f, paint = redPaint)
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun drawRect() {
-        canvas.drawRect(left = 2f, top = 0f, right = 6f, bottom = 8f, paint = redPaint)
-        canvas.drawRect(left = -4f, top = -4f, right = 4f, bottom = 4f, paint = bluePaint)
-        canvas.drawRect(left = 1f, top = 1f, right = 1f, bottom = 1f, paint = bluePaint)
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun drawRoundRect() {
-        canvas.drawRoundRect(
-            left = 0f,
-            top = 4f,
-            right = 16f,
-            bottom = 12f,
-            radiusX = 6f,
-            radiusY = 4f,
-            paint = redPaint
-        )
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun saveLayer() {
-        canvas.drawRect(0f, 0f, 16f, 16f, redPaint)
-
-        canvas.withSaveLayer(
-            Rect(left = 4f, top = 8f, right = 12f, bottom = 16f),
-            redPaint.apply { blendMode = BlendMode.Plus }
-        ) {
-            canvas.drawLine(Offset(4f, 0f), Offset(4f, 16f), bluePaint)
-        }
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun transform() {
-        canvas.withSave {
-            canvas.translate(4f, 2f)
-            canvas.drawRect(left = 0f, top = 0f, right = 4f, bottom = 4f, paint = redPaint)
-
-            canvas.rotate(45f)
-            canvas.drawLine(Offset(0f, 0f), Offset(4f, 0f), paint = bluePaint)
-        }
-
-        canvas.withSave {
-            canvas.rotate(90f)
-            canvas.translate(8f, 0f)
-            canvas.drawRect(left = 0f, top = -4f, right = 4f, bottom = 0f, paint = greenPaint)
-        }
-
-        canvas.withSave {
-            canvas.translate(8f, 8f)
-            canvas.skew(1f, 0f)
-            canvas.drawRect(left = 0f, top = 0f, right = 4f, bottom = 4f, paint = yellowPaint)
-        }
-
-        canvas.withSave {
-            canvas.translate(8f, 8f)
-            canvas.skew(0f, 1f)
-            canvas.drawRect(left = 0f, top = 0f, right = 4f, bottom = 4f, paint = magentaPaint)
-        }
-
-        canvas.withSave {
-            canvas.concat(Matrix().apply { translate(12f, 2f) })
-            canvas.drawRect(left = 0f, top = 0f, right = 4f, bottom = 4f, paint = cyanPaint)
-        }
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun clipRect() {
-        canvas.withSave {
-            canvas.clipRect(
-                left = 4f,
-                top = 4f,
-                right = 12f,
-                bottom = 12f,
-                clipOp = ClipOp.Intersect
-            )
-            canvas.drawRect(left = -4f, top = -4f, right = 20f, bottom = 20f, paint = redPaint)
-        }
-
-        canvas.drawRect(left = 4f, top = 0f, right = 8f, bottom = 4f, paint = bluePaint)
-
-        canvas.clipRect(left = 2f, top = 2f, right = 14f, bottom = 14f, clipOp = ClipOp.Difference)
-        canvas.drawRect(left = -4f, top = -4f, right = 20f, bottom = 20f, paint = greenPaint)
-
-        screenshotRule.snap(surface)
-    }
-
-    @Test
-    fun drawVertices() {
-        val positions =
-            listOf(
-                Offset(0f, 0f),
-                Offset(16f, 0f),
-                Offset(8f, 8f),
-                Offset(16f, 8f),
-                Offset(0f, 16f),
-                Offset(16f, 16f),
-            )
-        val colors =
-            listOf(Color.Red, Color.Green, Color.Blue, Color.Cyan, Color.Magenta, Color.Yellow)
-        val indices = listOf(0, 1, 2, 3, 4, 5)
-
-        canvas.drawVertices(
-            Vertices(VertexMode.Triangles, positions, positions, colors, indices),
-            BlendMode.DstOver,
-            Paint()
-        )
-
-        screenshotRule.snap(surface)
-    }
-}
diff --git a/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/layer/DesktopGraphicsLayerTest.kt b/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/layer/DesktopGraphicsLayerTest.kt
deleted file mode 100644
index be43813..0000000
--- a/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/layer/DesktopGraphicsLayerTest.kt
+++ /dev/null
@@ -1,1041 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.graphics.layer
-
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.geometry.Rect
-import androidx.compose.ui.geometry.Size
-import androidx.compose.ui.geometry.center
-import androidx.compose.ui.graphics.BlendMode
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.ColorFilter
-import androidx.compose.ui.graphics.GraphicsContext
-import androidx.compose.ui.graphics.Path
-import androidx.compose.ui.graphics.PixelMap
-import androidx.compose.ui.graphics.asComposeCanvas
-import androidx.compose.ui.graphics.compositeOver
-import androidx.compose.ui.graphics.drawscope.CanvasDrawScope
-import androidx.compose.ui.graphics.drawscope.DrawScope
-import androidx.compose.ui.graphics.drawscope.inset
-import androidx.compose.ui.graphics.drawscope.translate
-import androidx.compose.ui.graphics.toComposeImageBitmap
-import androidx.compose.ui.graphics.toPixelMap
-import androidx.compose.ui.unit.Density
-import androidx.compose.ui.unit.IntOffset
-import androidx.compose.ui.unit.IntSize
-import androidx.compose.ui.unit.LayoutDirection
-import androidx.compose.ui.unit.center
-import androidx.compose.ui.unit.toIntSize
-import androidx.compose.ui.unit.toOffset
-import androidx.compose.ui.unit.toSize
-import kotlin.math.roundToInt
-import kotlin.test.Test
-import org.jetbrains.skia.IRect
-import org.jetbrains.skia.Surface
-import org.junit.Assert
-import org.junit.Assert.assertEquals
-
-class DesktopGraphicsLayerTest {
-
-    @Test
-    fun testDrawLayer() {
-        var layer: GraphicsLayer? = null
-        graphicsLayerTest(
-            block = { graphicsContext ->
-                layer =
-                    graphicsContext.createGraphicsLayer().apply { record { drawRect(Color.Red) } }
-                drawLayer(layer!!)
-            },
-            verify = {
-                Assert.assertEquals(TEST_SIZE, layer!!.size)
-                Assert.assertEquals(IntOffset.Zero, layer!!.topLeft)
-                it.verifyQuadrants(Color.Red, Color.Red, Color.Red, Color.Red)
-            }
-        )
-    }
-
-    @Test
-    fun testRecordWithSize() {
-        graphicsLayerTest(
-            block = { graphicsContext ->
-                val layer =
-                    graphicsContext.createGraphicsLayer().apply {
-                        record(size = IntSize(TEST_WIDTH / 2, TEST_HEIGHT / 2)) {
-                            drawRect(Color.Red)
-                        }
-                    }
-                drawLayer(layer)
-            },
-            verify = { it.verifyQuadrants(Color.Red, Color.Black, Color.Black, Color.Black) }
-        )
-    }
-
-    @Test
-    fun testRecordWithOffset() {
-        var layer: GraphicsLayer? = null
-        val topLeft = IntOffset(TEST_WIDTH / 2, TEST_HEIGHT / 2)
-        val size = IntSize(TEST_WIDTH, TEST_HEIGHT)
-        graphicsLayerTest(
-            block = { graphicsContext ->
-                layer =
-                    graphicsContext.createGraphicsLayer().apply {
-                        record { drawRect(Color.Red) }
-                        this.topLeft = topLeft
-                    }
-                drawLayer(layer!!)
-            },
-            verify = {
-                Assert.assertEquals(topLeft, layer!!.topLeft)
-                Assert.assertEquals(size, layer!!.size)
-                it.verifyQuadrants(Color.Black, Color.Black, Color.Black, Color.Red)
-            }
-        )
-    }
-
-    @Test
-    fun testSetOffset() {
-        var layer: GraphicsLayer? = null
-        val topLeft = IntOffset(4, 4)
-        val size = IntSize(TEST_WIDTH, TEST_HEIGHT)
-        graphicsLayerTest(
-            block = { graphicsContext ->
-                layer =
-                    graphicsContext.createGraphicsLayer().apply {
-                        record { inset(0f, 0f, -4f, -4f) { drawRect(Color.Red) } }
-                        this.topLeft = topLeft
-                    }
-                drawLayer(layer!!)
-            },
-            verify = {
-                Assert.assertEquals(topLeft, layer!!.topLeft)
-                Assert.assertEquals(size, layer!!.size)
-                Assert.assertEquals(Color.Red, it[topLeft.x + 1, topLeft.y + 1])
-                Assert.assertEquals(Color.Black, it[topLeft.x + 1, topLeft.y - 1])
-                Assert.assertEquals(Color.Black, it[topLeft.x - 1, topLeft.y + 1])
-                Assert.assertEquals(Color.Red, it[size.width - 2, size.height - 2])
-            }
-        )
-    }
-
-    @Test
-    fun testSetScaleX() {
-        var layer: GraphicsLayer? = null
-        val topLeft = IntOffset.Zero
-        val size = TEST_SIZE
-        graphicsLayerTest(
-            block = { graphicsContext ->
-                layer =
-                    graphicsContext.createGraphicsLayer().apply {
-                        record {
-                            drawRect(
-                                Color.Red,
-                                size = Size(this.size.width / 2, this.size.height / 2)
-                            )
-                        }
-                        scaleX = 2f
-                        pivotOffset = Offset.Zero
-                    }
-                drawLayer(layer!!)
-            },
-            verify = {
-                Assert.assertEquals(topLeft, layer!!.topLeft)
-                Assert.assertEquals(size, layer!!.size)
-                it.verifyQuadrants(Color.Red, Color.Red, Color.Black, Color.Black)
-            }
-        )
-    }
-
-    @Test
-    fun testSetScaleY() {
-        var layer: GraphicsLayer? = null
-        val topLeft = IntOffset.Zero
-        val size = TEST_SIZE
-        graphicsLayerTest(
-            block = { graphicsContext ->
-                layer =
-                    graphicsContext.createGraphicsLayer().apply {
-                        record {
-                            drawRect(
-                                Color.Red,
-                                size = Size(this.size.width / 2, this.size.height / 2)
-                            )
-                        }
-                        scaleY = 2f
-                        pivotOffset = Offset.Zero
-                    }
-                drawLayer(layer!!)
-            },
-            verify = {
-                Assert.assertEquals(topLeft, layer!!.topLeft)
-                Assert.assertEquals(size, layer!!.size)
-                it.verifyQuadrants(Color.Red, Color.Black, Color.Red, Color.Black)
-            }
-        )
-    }
-
-    @Test
-    fun testDefaultPivot() {
-        var layer: GraphicsLayer? = null
-        val topLeft = IntOffset.Zero
-        val size = TEST_SIZE
-        graphicsLayerTest(
-            block = { graphicsContext ->
-                layer =
-                    graphicsContext.createGraphicsLayer().apply {
-                        record {
-                            inset(this.size.width / 4, this.size.height / 4) { drawRect(Color.Red) }
-                        }
-                        scaleY = 2f
-                        scaleX = 2f
-                    }
-                drawLayer(layer!!)
-            },
-            verify = {
-                Assert.assertEquals(topLeft, layer!!.topLeft)
-                Assert.assertEquals(size, layer!!.size)
-                it.verifyQuadrants(Color.Red, Color.Red, Color.Red, Color.Red)
-            }
-        )
-    }
-
-    @Test
-    fun testBottomRightPivot() {
-        var layer: GraphicsLayer? = null
-        val topLeft = IntOffset.Zero
-        val size = TEST_SIZE
-        graphicsLayerTest(
-            block = { graphicsContext ->
-                layer =
-                    graphicsContext.createGraphicsLayer().apply {
-                        record { drawRect(Color.Red) }
-                        scaleY = 0.5f
-                        scaleX = 0.5f
-                        pivotOffset = Offset(this.size.width.toFloat(), this.size.height.toFloat())
-                    }
-                drawLayer(layer!!)
-            },
-            verify = {
-                Assert.assertEquals(topLeft, layer!!.topLeft)
-                Assert.assertEquals(size, layer!!.size)
-                it.verifyQuadrants(Color.Black, Color.Black, Color.Black, Color.Red)
-            }
-        )
-    }
-
-    @Test
-    fun testTranslationX() {
-        var layer: GraphicsLayer? = null
-        val topLeft = IntOffset.Zero
-        val size = TEST_SIZE
-        graphicsLayerTest(
-            block = { graphicsContext ->
-                layer =
-                    graphicsContext.createGraphicsLayer().apply {
-                        record { drawRect(Color.Red, size = this.size / 2f) }
-                        translationX = this.size.width / 2f
-                    }
-                drawLayer(layer!!)
-            },
-            verify = {
-                Assert.assertEquals(topLeft, layer!!.topLeft)
-                Assert.assertEquals(size, layer!!.size)
-                it.verifyQuadrants(Color.Black, Color.Red, Color.Black, Color.Black)
-            }
-        )
-    }
-
-    @Test
-    fun testRectOutlineWithNonZeroTopLeft() {
-        graphicsLayerTest(
-            block = { graphicsContext ->
-                var layerSize = Size.Zero
-                val layer =
-                    graphicsContext.createGraphicsLayer().apply {
-                        record {
-                            layerSize = this.size
-                            drawRect(Color.Red, size = this.size / 2f)
-                        }
-                        topLeft = IntOffset(20, 30)
-                        setRectOutline()
-                    }
-                drawLayer(layer)
-                val outline = layer.outline
-                assertEquals(Rect(0f, 0f, layerSize.width, layerSize.height), outline.bounds)
-            }
-        )
-    }
-
-    @Test
-    fun testRoundRectOutlineWithNonZeroTopLeft() {
-        graphicsLayerTest(
-            block = { graphicsContext ->
-                var layerSize = Size.Zero
-                val layer =
-                    graphicsContext.createGraphicsLayer().apply {
-                        record {
-                            layerSize = this.size
-                            drawRect(Color.Red, size = this.size / 2f)
-                        }
-                        topLeft = IntOffset(20, 30)
-                        setRoundRectOutline()
-                    }
-                drawLayer(layer)
-                val outline = layer.outline
-                assertEquals(Rect(0f, 0f, layerSize.width, layerSize.height), outline.bounds)
-            }
-        )
-    }
-
-    @Test
-    fun testTranslationY() {
-        var layer: GraphicsLayer? = null
-        val topLeft = IntOffset.Zero
-        val size = TEST_SIZE
-        graphicsLayerTest(
-            block = { graphicsContext ->
-                layer =
-                    graphicsContext.createGraphicsLayer().apply {
-                        record { drawRect(Color.Red, size = this.size / 2f) }
-                        translationY = this.size.height / 2f
-                    }
-                drawLayer(layer!!)
-            },
-            verify = {
-                Assert.assertEquals(topLeft, layer!!.topLeft)
-                Assert.assertEquals(size, layer!!.size)
-                it.verifyQuadrants(Color.Black, Color.Black, Color.Red, Color.Black)
-            }
-        )
-    }
-
-    @Test
-    fun testUnboundedClip() {
-        var layer: GraphicsLayer?
-        graphicsLayerTest(
-            block = { graphicsContext ->
-                layer =
-                    graphicsContext.createGraphicsLayer().apply {
-                        record { drawRect(Color.Red, size = Size(100000f, 100000f)) }
-                        // Layer clipping is disabled by default
-                    }
-                drawLayer(layer!!)
-            },
-            verify = {
-                Assert.assertEquals(Color.Red, it[0, 0])
-                Assert.assertEquals(Color.Red, it[it.width - 1, 0])
-                Assert.assertEquals(Color.Red, it[0, it.height - 1])
-                Assert.assertEquals(Color.Red, it[it.width - 1, it.height - 1])
-                Assert.assertEquals(Color.Red, it[it.width / 2, it.height / 2])
-            },
-            entireScene = true
-        )
-    }
-
-    @Test
-    fun testBoundedClip() {
-        var layer: GraphicsLayer?
-        graphicsLayerTest(
-            block = { graphicsContext ->
-                layer =
-                    graphicsContext.createGraphicsLayer().apply {
-                        record { drawRect(Color.Red, size = Size(100000f, 100000f)) }
-                        clip = true
-                    }
-                drawLayer(layer!!)
-            },
-            verify = {
-                Assert.assertEquals(Color.Red, it[0, 0])
-                Assert.assertEquals(Color.Red, it[TEST_WIDTH - 1, 0])
-                Assert.assertEquals(Color.Red, it[0, TEST_HEIGHT - 1])
-                Assert.assertEquals(Color.Red, it[TEST_WIDTH - 1, TEST_HEIGHT - 1])
-                Assert.assertEquals(Color.Red, it[TEST_WIDTH / 2, 0])
-                Assert.assertEquals(Color.Red, it[TEST_WIDTH / 2, TEST_HEIGHT / 2])
-
-                Assert.assertEquals(Color.White, it[0, TEST_HEIGHT + 2])
-                Assert.assertEquals(Color.White, it[0, it.height - 1])
-                Assert.assertEquals(Color.White, it[TEST_WIDTH - 1, TEST_HEIGHT + 2])
-                Assert.assertEquals(Color.White, it[TEST_WIDTH + 1, TEST_HEIGHT])
-                Assert.assertEquals(Color.White, it[it.width - 1, TEST_HEIGHT - 2])
-            },
-            entireScene = true
-        )
-    }
-
-    @Test
-    fun testElevation() {
-        var layer: GraphicsLayer?
-        var left = 0
-        var top = 0
-        var right = 0
-        var bottom = 0
-        val targetColor = Color.White
-        graphicsLayerTest(
-            block = { graphicsContext ->
-                val halfSize =
-                    IntSize((this.size.width / 2f).toInt(), (this.size.height / 2f).toInt())
-
-                layer =
-                    graphicsContext.createGraphicsLayer().apply {
-                        record(halfSize) { drawRect(targetColor) }
-                        shadowElevation = 10f
-                    }
-                drawRect(targetColor)
-
-                left = (this.size.width / 4f).toInt()
-                top = (this.size.width / 4f).toInt()
-                right = left + halfSize.width
-                bottom = top + halfSize.height
-                translate(this.size.width / 4, this.size.height / 4) { drawLayer(layer!!) }
-            },
-            verify = { pixmap ->
-                var shadowPixelCount = 0
-                with(pixmap) {
-                    for (x in left until right) {
-                        for (y in top until bottom) {
-                            if (this[x, y] != targetColor) {
-                                shadowPixelCount++
-                            }
-                        }
-                    }
-                }
-                Assert.assertTrue(shadowPixelCount > 0)
-            }
-        )
-    }
-
-    @org.junit.Test
-    fun testElevationPath() {
-        var layer: GraphicsLayer?
-        var left = 0
-        var top = 0
-        var right = 0
-        var bottom = 0
-        val targetColor = Color.White
-        graphicsLayerTest(
-            block = { graphicsContext ->
-                val halfSize =
-                    IntSize((this.size.width / 2f).toInt(), (this.size.height / 2f).toInt())
-
-                layer =
-                    graphicsContext.createGraphicsLayer().apply {
-                        record(halfSize) { drawRect(targetColor) }
-                        setPathOutline(
-                            Path().apply {
-                                addRect(
-                                    Rect(
-                                        0f,
-                                        0f,
-                                        halfSize.width.toFloat(),
-                                        halfSize.height.toFloat()
-                                    )
-                                )
-                            }
-                        )
-                        shadowElevation = 10f
-                    }
-                drawRect(targetColor)
-
-                left = (this.size.width / 4f).toInt()
-                top = (this.size.width / 4f).toInt()
-                right = left + halfSize.width
-                bottom = top + halfSize.height
-                translate(this.size.width / 4, this.size.height / 4) { drawLayer(layer!!) }
-            },
-            verify = { pixmap ->
-                var shadowPixelCount = 0
-                with(pixmap) {
-                    for (x in left until right) {
-                        for (y in top until bottom) {
-                            if (this[x, y] != targetColor) {
-                                shadowPixelCount++
-                            }
-                        }
-                    }
-                }
-                Assert.assertTrue(shadowPixelCount > 0)
-            }
-        )
-    }
-
-    @org.junit.Test
-    fun testElevationRoundRect() {
-        var layer: GraphicsLayer?
-        var left = 0
-        var top = 0
-        var right = 0
-        var bottom = 0
-        val targetColor = Color.White
-        val radius = 50f
-        graphicsLayerTest(
-            block = { graphicsContext ->
-                val halfSize =
-                    IntSize((this.size.width / 2f).toInt(), (this.size.height / 2f).toInt())
-
-                left = (this.size.width / 4f).toInt()
-                top = (this.size.width / 4f).toInt()
-                right = left + halfSize.width
-                bottom = top + halfSize.height
-
-                layer =
-                    graphicsContext.createGraphicsLayer().apply {
-                        record(halfSize) { drawRect(targetColor) }
-                        setRoundRectOutline(Offset.Zero, halfSize.toSize(), radius)
-                        shadowElevation = 20f
-                    }
-
-                drawRect(targetColor)
-                translate(left.toFloat(), top.toFloat()) { drawLayer(layer!!) }
-            },
-            verify = { pixmap ->
-                fun PixelMap.hasShadowPixels(
-                    targetColor: Color,
-                    l: Int,
-                    t: Int,
-                    r: Int,
-                    b: Int
-                ): Boolean {
-                    var shadowCount = 0
-                    for (i in l until r) {
-                        for (j in t until b) {
-                            if (this[i, j] != targetColor) {
-                                shadowCount++
-                            }
-                        }
-                    }
-                    return shadowCount > 0
-                }
-                with(pixmap) {
-                    Assert.assertTrue(
-                        hasShadowPixels(
-                            targetColor,
-                            left,
-                            top,
-                            left + radius.toInt(),
-                            top + radius.toInt()
-                        )
-                    )
-                    Assert.assertTrue(
-                        hasShadowPixels(
-                            targetColor,
-                            right - radius.toInt(),
-                            top,
-                            right,
-                            top + radius.toInt()
-                        )
-                    )
-                    Assert.assertTrue(
-                        hasShadowPixels(
-                            targetColor,
-                            left,
-                            bottom - radius.toInt(),
-                            left + radius.toInt(),
-                            bottom
-                        )
-                    )
-                    Assert.assertTrue(
-                        hasShadowPixels(
-                            targetColor,
-                            right - radius.toInt(),
-                            bottom - radius.toInt(),
-                            right,
-                            bottom
-                        )
-                    )
-                }
-            }
-        )
-    }
-
-    @Test
-    fun testCompositingStrategyAuto() {
-        var layer: GraphicsLayer?
-        val bgColor = Color.Black
-        graphicsLayerTest(
-            block = { graphicsContext ->
-                layer =
-                    graphicsContext.createGraphicsLayer().apply {
-                        compositingStrategy = CompositingStrategy.Auto
-                        alpha = 0.5f
-                        record {
-                            inset(0f, 0f, size.width / 3, size.height / 3) {
-                                drawRect(color = Color.Red)
-                            }
-                            inset(size.width / 3, size.height / 3, 0f, 0f) {
-                                drawRect(color = Color.Blue)
-                            }
-                        }
-                    }
-                drawRect(bgColor)
-                drawLayer(layer!!)
-            },
-            verify = { pixelMap ->
-                with(pixelMap) {
-                    val redWithAlpha = Color.Red.copy(alpha = 0.5f)
-                    val blueWithAlpha = Color.Blue.copy(alpha = 0.5f)
-                    val expectedTopLeft = redWithAlpha.compositeOver(bgColor)
-                    val expectedBottomRight = blueWithAlpha.compositeOver(bgColor)
-                    val expectedCenter = blueWithAlpha.compositeOver(bgColor)
-                    assertPixelColor(expectedTopLeft, 0, 0)
-                    assertPixelColor(Color.Black, width - 1, 0)
-                    assertPixelColor(expectedBottomRight, width - 1, height - 1)
-                    assertPixelColor(Color.Black, 0, height - 1)
-                    assertPixelColor(expectedCenter, width / 2, height / 2)
-                }
-            }
-        )
-    }
-
-    @Test
-    fun testCompositingStrategyOffscreen() {
-        var layer: GraphicsLayer?
-        val bgColor = Color.LightGray
-        graphicsLayerTest(
-            block = { graphicsContext ->
-                layer =
-                    graphicsContext.createGraphicsLayer().apply {
-                        compositingStrategy = CompositingStrategy.Offscreen
-                        record {
-                            inset(0f, 0f, size.width / 3, size.height / 3) {
-                                drawRect(color = Color.Red)
-                            }
-                            inset(size.width / 3, size.height / 3, 0f, 0f) {
-                                drawRect(color = Color.Blue, blendMode = BlendMode.Xor)
-                            }
-                        }
-                    }
-                drawRect(bgColor)
-                drawLayer(layer!!)
-            },
-            verify = { pixelMap ->
-                with(pixelMap) {
-                    assertPixelColor(Color.Red, 0, 0)
-                    assertPixelColor(bgColor, width - 1, 0)
-                    assertPixelColor(Color.Blue, width - 1, height - 1)
-                    assertPixelColor(bgColor, 0, height - 1)
-                    assertPixelColor(bgColor, width / 2, height / 2)
-                }
-            }
-        )
-    }
-
-    @Test
-    fun testCompositingStrategyModulateAlpha() {
-        var layer: GraphicsLayer?
-        val bgColor = Color.Black
-        graphicsLayerTest(
-            block = { graphicsContext ->
-                layer =
-                    graphicsContext.createGraphicsLayer().apply {
-                        compositingStrategy = CompositingStrategy.ModulateAlpha
-                        alpha = 0.5f
-                        record {
-                            inset(0f, 0f, size.width / 3, size.height / 3) {
-                                drawRect(color = Color.Red)
-                            }
-                            inset(size.width / 3, size.height / 3, 0f, 0f) {
-                                drawRect(color = Color.Blue)
-                            }
-                        }
-                    }
-                drawRect(bgColor)
-                drawLayer(layer!!)
-            },
-            verify = { pixelMap ->
-                with(pixelMap) {
-                    println("Pixmap size: " + this.width + " height: " + this.height)
-                    val redWithAlpha = Color.Red.copy(alpha = 0.5f)
-                    val blueWithAlpha = Color.Blue.copy(alpha = 0.5f)
-                    val bg = Color.Black
-                    val expectedTopLeft = redWithAlpha.compositeOver(bg)
-                    val expectedBottomRight = blueWithAlpha.compositeOver(bg)
-                    val expectedCenter = blueWithAlpha.compositeOver(redWithAlpha).compositeOver(bg)
-                    assertPixelColor(expectedTopLeft, 0, 0)
-                    assertPixelColor(Color.Black, width - 1, 0)
-                    assertPixelColor(expectedBottomRight, width - 1, height - 1)
-                    assertPixelColor(Color.Black, 0, height - 1)
-                    assertPixelColor(expectedCenter, width / 2, height / 2)
-                }
-            }
-        )
-    }
-
-    @Test
-    fun testTintColorFilter() {
-        var layer: GraphicsLayer?
-        graphicsLayerTest(
-            block = { graphicsContext ->
-                layer =
-                    graphicsContext.createGraphicsLayer().apply {
-                        record { drawRect(Color.Red) }
-                            .apply { colorFilter = ColorFilter.tint(Color.Blue) }
-                    }
-                drawLayer(layer!!)
-            },
-            verify = { pixelMap ->
-                with(pixelMap) {
-                    assertPixelColor(Color.Blue, 0, 0)
-                    assertPixelColor(Color.Blue, width - 1, 0)
-                    assertPixelColor(Color.Blue, 0, height - 1)
-                    assertPixelColor(Color.Blue, width - 1, height - 1)
-                    assertPixelColor(Color.Blue, width / 2, height / 2)
-                }
-            }
-        )
-    }
-
-    @Test
-    fun testBlendMode() {
-        var layer: GraphicsLayer?
-        graphicsLayerTest(
-            block = { graphicsContext ->
-                val drawScopeSize = this.size
-                layer =
-                    graphicsContext.createGraphicsLayer().apply {
-                        val topLeft =
-                            IntOffset(
-                                (drawScopeSize.width / 4).toInt(),
-                                (drawScopeSize.height / 4).toInt()
-                            )
-                        val layerSize =
-                            IntSize(
-                                (drawScopeSize.width / 2).toInt(),
-                                (drawScopeSize.height / 2).toInt()
-                            )
-                        record(layerSize) { drawRect(Color.Red) }
-                        this.topLeft = topLeft
-                        this.blendMode = BlendMode.Xor
-                    }
-                drawRect(Color.Green)
-                drawLayer(layer!!)
-                // The layer should clear the original pixels in the destination rendered by the
-                // layer. Draw blue underneath the destination to fill the transparent pixels
-                // cleared by the layer
-                drawRect(Color.Blue, blendMode = BlendMode.DstOver)
-            },
-            verify = { pixelMap ->
-                with(pixelMap) {
-                    assertPixelColor(Color.Green, 0, 0)
-                    assertPixelColor(Color.Green, width - 1, 0)
-                    assertPixelColor(Color.Green, 0, height - 1)
-                    assertPixelColor(Color.Green, width - 1, height - 1)
-
-                    val insetLeft = width / 4 + 2
-                    val insetTop = height / 4 + 2
-                    val insetRight = width - width / 4 - 2
-                    val insetBottom = height - height / 4 - 2
-
-                    assertPixelColor(Color.Blue, insetLeft, insetTop)
-                    assertPixelColor(Color.Blue, insetRight, insetTop)
-                    assertPixelColor(Color.Blue, insetLeft, insetBottom)
-                    assertPixelColor(Color.Blue, insetRight, insetBottom)
-                    assertPixelColor(Color.Blue, width / 2, height / 2)
-                }
-            }
-        )
-    }
-
-    @Test
-    fun testRectOutlineClip() {
-        var layer: GraphicsLayer?
-        var left = 0
-        var top = 0
-        var right = 0
-        var bottom = 0
-        val bgColor = Color.Black
-        val targetColor = Color.Red
-        graphicsLayerTest(
-            block = { graphicsContext ->
-                layer =
-                    graphicsContext.createGraphicsLayer().apply {
-                        record { drawRect(targetColor) }
-                        setRectOutline(this.size.center.toOffset(), (this.size / 2).toSize())
-                        clip = true
-                    }
-                drawRect(bgColor)
-
-                left = this.size.center.x.toInt()
-                top = this.size.center.y.toInt()
-                right = this.size.width.toInt()
-                bottom = this.size.height.toInt()
-
-                drawLayer(layer!!)
-            },
-            verify = { pixmap ->
-                with(pixmap) {
-                    for (x in 0 until width) {
-                        for (y in 0 until height) {
-                            val expected =
-                                if (x in left until right && y in top until bottom) {
-                                    targetColor
-                                } else {
-                                    bgColor
-                                }
-                            Assert.assertEquals(this[x, y], expected)
-                        }
-                    }
-                }
-            }
-        )
-    }
-
-    @Test
-    fun testPathOutlineClip() {
-        var layer: GraphicsLayer?
-        var left = 0
-        var top = 0
-        var right = 0
-        var bottom = 0
-        val bgColor = Color.Black
-        val targetColor = Color.Red
-        graphicsLayerTest(
-            block = { graphicsContext ->
-                layer =
-                    graphicsContext.createGraphicsLayer().apply {
-                        record { drawRect(targetColor) }
-                        setPathOutline(
-                            Path().apply {
-                                addRect(
-                                    Rect(
-                                        size.center.x.toFloat(),
-                                        size.center.y.toFloat(),
-                                        size.center.x + size.width.toFloat(),
-                                        size.center.y + size.height.toFloat()
-                                    )
-                                )
-                            }
-                        )
-                        clip = true
-                    }
-                drawRect(bgColor)
-
-                left = this.size.center.x.toInt()
-                top = this.size.center.y.toInt()
-                right = this.size.width.toInt()
-                bottom = this.size.height.toInt()
-
-                drawLayer(layer!!)
-            },
-            verify = { pixmap ->
-                with(pixmap) {
-                    for (x in 0 until width) {
-                        for (y in 0 until height) {
-                            val expected =
-                                if (x in left until right && y in top until bottom) {
-                                    targetColor
-                                } else {
-                                    bgColor
-                                }
-                            Assert.assertEquals(this[x, y], expected)
-                        }
-                    }
-                }
-            }
-        )
-    }
-
-    @org.junit.Test
-    fun testRoundRectOutlineClip() {
-        var layer: GraphicsLayer?
-        var left = 0
-        var top = 0
-        var right = 0
-        var bottom = 0
-        val radius = 50
-        val bgColor = Color.Black
-        val targetColor = Color.Red
-        graphicsLayerTest(
-            block = { graphicsContext ->
-                layer =
-                    graphicsContext.createGraphicsLayer().apply {
-                        record { drawRect(targetColor) }
-                        setRoundRectOutline(
-                            this.size.center.toOffset(),
-                            (this.size / 2).toSize(),
-                            radius.toFloat()
-                        )
-                        clip = true
-                    }
-                drawRect(bgColor)
-
-                left = this.size.center.x.toInt()
-                top = this.size.center.y.toInt()
-                right = (left + this.size.width / 2).toInt()
-                bottom = (top + this.size.height / 2).toInt()
-
-                drawLayer(layer!!)
-            },
-            verify = { pixmap ->
-                with(pixmap) {
-                    val offset = 5
-                    val startX = left + radius + offset
-                    val startY = top + radius + offset
-                    val endX = right - radius - offset
-                    val endY = bottom - radius - offset
-                    for (x in 0 until width) {
-                        for (y in 0 until height) {
-                            if (x in startX until endX && y in startY until endY) {
-                                Assert.assertEquals(targetColor, this[x, y])
-                            }
-                        }
-                    }
-                    Assert.assertEquals(bgColor, this[offset, offset])
-                    Assert.assertEquals(bgColor, this[width - offset, offset])
-                    Assert.assertEquals(bgColor, this[offset, height - offset])
-                    Assert.assertEquals(bgColor, this[width - offset, height - offset])
-                }
-            }
-        )
-    }
-
-    @org.junit.Test
-    fun testSwitchingFromClipToBoundsToClipToOutline() {
-        val targetColor = Color.Red
-        val inset = 50f
-        graphicsLayerTest(
-            block = { graphicsContext ->
-                val fullSize = size
-                val layerSize =
-                    Size(
-                            fullSize.width.roundToInt() - inset * 2,
-                            fullSize.height.roundToInt() - inset * 2
-                        )
-                        .toIntSize()
-
-                val layer =
-                    graphicsContext.createGraphicsLayer().apply {
-                        record(size = layerSize) { inset(-inset) { drawRect(targetColor) } }
-                        // as no outline is provided yet, this command will enable clipToBounds
-                        clip = true
-                        // then with providing an outline we should disable clipToBounds and start
-                        // using clipToOutline instead
-                        setRectOutline(Offset(-inset, -inset), fullSize)
-                    }
-
-                drawRect(Color.Black)
-                inset(inset) { drawLayer(layer) }
-            },
-            verify = { pixmap ->
-                with(pixmap) {
-                    for (x in 0 until width) {
-                        for (y in 0 until height) {
-                            Assert.assertEquals(this[x, y], targetColor)
-                        }
-                    }
-                }
-            }
-        )
-    }
-
-    @org.junit.Test
-    fun testEndRecordingAlwaysCalled() {
-        graphicsLayerTest(
-            block = { graphicsContext ->
-                val layer = graphicsContext.createGraphicsLayer()
-                try {
-                    layer.record {
-                        // Intentionally cause an exception to be thrown during recording
-                        throw Exception()
-                    }
-                } catch (_: Throwable) {
-                    // NO-OP
-                }
-
-                // Attempts to record after an exception is thrown should still succeed
-                layer.record { drawRect(Color.Red) }
-                drawLayer(layer)
-            },
-            verify = { it.verifyQuadrants(Color.Red, Color.Red, Color.Red, Color.Red) }
-        )
-    }
-
-    private fun graphicsLayerTest(
-        block: DrawScope.(GraphicsContext) -> Unit,
-        verify: ((PixelMap) -> Unit)? = null,
-        entireScene: Boolean = false
-    ) {
-        val graphicsContext = GraphicsContext()
-        val surfaceWidth = TEST_WIDTH * 2
-        val surfaceHeight = TEST_HEIGHT * 2
-        val surface = Surface.makeRasterN32Premul(surfaceWidth, surfaceHeight)
-        val canvas = surface.canvas
-        val drawScope = CanvasDrawScope()
-        try {
-            drawScope.draw(
-                Density(1f),
-                LayoutDirection.Ltr,
-                canvas.asComposeCanvas(),
-                Size(surfaceWidth.toFloat(), surfaceHeight.toFloat())
-            ) {
-                drawRect(Color.White)
-                inset(0f, 0f, TEST_WIDTH.toFloat(), TEST_HEIGHT.toFloat()) {
-                    drawRect(Color.Black)
-                    block(graphicsContext)
-                }
-            }
-            surface.flushAndSubmit(true)
-            val area =
-                IRect.makeWH(
-                    if (entireScene) TEST_WIDTH * 2 else TEST_WIDTH,
-                    if (entireScene) TEST_HEIGHT * 2 else TEST_HEIGHT
-                )
-            val imageBitmap = surface.makeImageSnapshot(area)!!.toComposeImageBitmap()
-            verify?.invoke(imageBitmap.toPixelMap())
-        } finally {
-            surface.close()
-        }
-    }
-
-    private fun PixelMap.verifyQuadrants(
-        topLeft: Color,
-        topRight: Color,
-        bottomLeft: Color,
-        bottomRight: Color
-    ) {
-        val left = this.width / 4
-        val right = this.width / 4 + this.width / 2
-        val top = this.height / 4
-        val bottom = this.height / 4 + this.height / 2
-        assertPixelColor(topLeft, left, top) { "$left, $top is incorrect color" }
-        assertPixelColor(topRight, right, top) { "$right, $top is incorrect color" }
-        assertPixelColor(bottomLeft, left, bottom) { "$left, $bottom is incorrect color" }
-        assertPixelColor(bottomRight, right, bottom) { "$right, $bottom is incorrect color" }
-    }
-
-    /** Asserts that the color at a specific pixel in the bitmap at ([x], [y]) is [expected]. */
-    private fun PixelMap.assertPixelColor(
-        expected: Color,
-        x: Int,
-        y: Int,
-        error: (Color) -> String = { color ->
-            "Pixel($x, $y) expected to be $expected, but was $color"
-        }
-    ) {
-        val color = this[x, y]
-        val errorString = error(color)
-        Assert.assertEquals(errorString, expected.red, color.red, 0.02f)
-        Assert.assertEquals(errorString, expected.green, color.green, 0.02f)
-        Assert.assertEquals(errorString, expected.blue, color.blue, 0.02f)
-        Assert.assertEquals(errorString, expected.alpha, color.alpha, 0.02f)
-    }
-
-    companion object {
-        const val TEST_WIDTH = 600
-        const val TEST_HEIGHT = 400
-
-        val TEST_SIZE = IntSize(TEST_WIDTH, TEST_HEIGHT)
-    }
-}
diff --git a/compose/ui/ui-graphics/src/desktopTest/res/androidx/compose/desktop/test.png b/compose/ui/ui-graphics/src/desktopTest/res/androidx/compose/desktop/test.png
deleted file mode 100644
index b1859b9..0000000
--- a/compose/ui/ui-graphics/src/desktopTest/res/androidx/compose/desktop/test.png
+++ /dev/null
Binary files differ
diff --git a/compose/ui/ui-inspection/src/androidTest/java/androidx/compose/ui/inspection/inspector/LayoutInspectorTreeTest.kt b/compose/ui/ui-inspection/src/androidTest/java/androidx/compose/ui/inspection/inspector/LayoutInspectorTreeTest.kt
index 5b2bda1..0fafc4ba 100644
--- a/compose/ui/ui-inspection/src/androidTest/java/androidx/compose/ui/inspection/inspector/LayoutInspectorTreeTest.kt
+++ b/compose/ui/ui-inspection/src/androidTest/java/androidx/compose/ui/inspection/inspector/LayoutInspectorTreeTest.kt
@@ -698,6 +698,7 @@
                 name = "ComposeNode",
                 fileName = "AndroidView.android.kt",
                 hasViewIdUnder = composeView,
+                isRenderNode = true,
                 inlined = true,
             )
         }
@@ -739,6 +740,7 @@
                 name = "ReusableComposeNode",
                 fileName = "AndroidView.android.kt",
                 hasViewIdUnder = composeView,
+                isRenderNode = true,
                 inlined = true,
             )
         }
diff --git a/compose/ui/ui-inspection/src/main/java/androidx/compose/ui/inspection/inspector/LayoutInspectorTree.kt b/compose/ui/ui-inspection/src/main/java/androidx/compose/ui/inspection/inspector/LayoutInspectorTree.kt
index de2aa05..82f3110 100644
--- a/compose/ui/ui-inspection/src/main/java/androidx/compose/ui/inspection/inspector/LayoutInspectorTree.kt
+++ b/compose/ui/ui-inspection/src/main/java/androidx/compose/ui/inspection/inspector/LayoutInspectorTree.kt
@@ -392,7 +392,7 @@
             .singleOrNull { it.viewId != UNDEFINED_ID }
             ?.takeIf { node ->
                 // Take if the node has been marked as unwanted
-                node.id == UNDEFINED_ID
+                node.name.isEmpty()
             }
             ?.let { nodeWithView -> parentNode.viewId = nodeWithView.viewId }
 
diff --git a/compose/ui/ui-lint/src/main/java/androidx/compose/ui/lint/ReturnFromAwaitPointerEventScopeDetector.kt b/compose/ui/ui-lint/src/main/java/androidx/compose/ui/lint/ReturnFromAwaitPointerEventScopeDetector.kt
index 1168ecf..cfdc8a0 100644
--- a/compose/ui/ui-lint/src/main/java/androidx/compose/ui/lint/ReturnFromAwaitPointerEventScopeDetector.kt
+++ b/compose/ui/ui-lint/src/main/java/androidx/compose/ui/lint/ReturnFromAwaitPointerEventScopeDetector.kt
@@ -28,27 +28,36 @@
 import com.android.tools.lint.detector.api.Scope
 import com.android.tools.lint.detector.api.Severity
 import com.android.tools.lint.detector.api.SourceCodeScanner
-import com.android.tools.lint.detector.api.isIncorrectImplicitReturnInLambda
 import com.intellij.psi.PsiMethod
 import java.util.EnumSet
+import org.jetbrains.kotlin.analysis.api.analyze
+import org.jetbrains.kotlin.analysis.api.types.KtFunctionalType
+import org.jetbrains.kotlin.psi.KtLambdaExpression
 import org.jetbrains.uast.UCallExpression
+import org.jetbrains.uast.UElement
+import org.jetbrains.uast.UExpression
+import org.jetbrains.uast.ULambdaExpression
 import org.jetbrains.uast.ULocalVariable
 import org.jetbrains.uast.UReturnExpression
+import org.jetbrains.uast.UVariable
 import org.jetbrains.uast.skipParenthesizedExprUp
 
 class ReturnFromAwaitPointerEventScopeDetector : Detector(), SourceCodeScanner {
-
     override fun getApplicableMethodNames(): List<String> =
         listOf(Names.Ui.Pointer.AwaitPointerEventScope.shortName)
 
     override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) {
         if (!method.isInPackageName(Names.Ui.Pointer.PackageName)) return
+
         val methodParent = skipParenthesizedExprUp(node.uastParent)
         val isAssignedToVariable = methodParent is ULocalVariable
-        val isReturnExpression =
-            methodParent is UReturnExpression && !methodParent.isIncorrectImplicitReturnInLambda()
 
-        if (isAssignedToVariable || isReturnExpression) {
+        val isReturnExpression = methodParent is UReturnExpression
+
+        val invalidUseOfAwaitPointerEventScopeWithReturn =
+            isReturnExpression && !validUseOfAwaitPointerEventScopeWithReturn(node)
+
+        if (isAssignedToVariable || invalidUseOfAwaitPointerEventScopeWithReturn) {
             context.report(
                 ExitAwaitPointerEventScope,
                 node,
@@ -58,7 +67,63 @@
         }
     }
 
+    private fun validUseOfAwaitPointerEventScopeWithReturn(
+        awaitPointerEventScopeNode: UCallExpression
+    ): Boolean {
+        // Traverse up the UAST tree
+        var currentNode: UElement? = awaitPointerEventScopeNode.uastParent
+        while (currentNode != null) {
+            // Check if awaitPointerEventScope is within a PointerInputEventHandler or a
+            // pointerInput method call (making it a valid use of return).
+            if (
+                currentNode is UCallExpression &&
+                    (currentNode.methodName == POINTER_INPUT_HANDLER ||
+                        currentNode.methodName == POINTER_INPUT_METHOD ||
+                        currentNode.methodName == COROUTINE_METHOD)
+            ) {
+                return true
+            }
+
+            // For backward compatibility, checks if awaitPointerEventScopeNode is returned to a
+            // "suspend PointerInputScope.() -> Unit" type variable (see test
+            // awaitPointerEventScope_assignedFromContainingLambdaMethod_shouldNotWarn() ).
+            if (currentNode is UVariable) {
+                val variable = currentNode
+                val lambda: UExpression? = variable.uastInitializer
+
+                // Check if the initializer is a suspend lambda with the correct type
+                if (lambda is ULambdaExpression) {
+                    val ktLambdaExpression = lambda.sourcePsi
+                    if (
+                        ktLambdaExpression is KtLambdaExpression &&
+                            isSuspendPointerInputLambda(ktLambdaExpression)
+                    ) {
+                        return true
+                    }
+                }
+            }
+            currentNode = currentNode.uastParent
+        }
+        return false
+    }
+
+    // Helper function for lambda type check
+    private fun isSuspendPointerInputLambda(ktLambdaExpression: KtLambdaExpression): Boolean {
+        return analyze(ktLambdaExpression) {
+            val type = ktLambdaExpression.getExpectedType() as? KtFunctionalType ?: return false
+            type.isSuspendFunctionType &&
+                type.receiverType?.expandedClassSymbol?.classIdIfNonLocal?.asFqNameString() ==
+                    POINTER_INPUT_SCOPE
+        }
+    }
+
     companion object {
+        private const val POINTER_INPUT_SCOPE =
+            "androidx.compose.ui.input.pointer.PointerInputScope"
+        private const val POINTER_INPUT_HANDLER = "PointerInputEventHandler"
+        private const val POINTER_INPUT_METHOD = "pointerInput"
+        private const val COROUTINE_METHOD = "coroutineScope"
+
         const val IssueId: String = "ReturnFromAwaitPointerEventScope"
         const val ErrorMessage =
             "Returning from awaitPointerEventScope may cause some input " + "events to be dropped"
diff --git a/compose/ui/ui-lint/src/test/java/androidx/compose/ui/lint/CoroutineStubs.kt b/compose/ui/ui-lint/src/test/java/androidx/compose/ui/lint/CoroutineStubs.kt
new file mode 100644
index 0000000..1165b64
--- /dev/null
+++ b/compose/ui/ui-lint/src/test/java/androidx/compose/ui/lint/CoroutineStubs.kt
@@ -0,0 +1,236 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package androidx.compose.ui.lint
+
+import androidx.compose.lint.test.bytecodeStub
+import com.android.tools.lint.checks.infrastructure.TestFile
+
+object CoroutineStubs {
+
+    val coroutineContextTestFile: TestFile =
+        bytecodeStub(
+            filename = "CoroutineContext.kt",
+            filepath = "kotlinx/coroutines",
+            checksum = 0x2eedf37a,
+            source =
+                """
+    package kotlinx.coroutines
+
+    public interface CoroutineContext {
+        public operator fun plus(context: CoroutineContext): CoroutineContext = context
+        public operator fun <E : CoroutineContext.Element> get(key: CoroutineContext.Key<E>): E? = null
+        public interface Key<E : Element>
+        public interface Element : CoroutineContext {
+            public val key: Key<*>
+        }
+    }
+    """
+                    .trimIndent(),
+            """
+                META-INF/main.kotlin_module:
+                H4sIAAAAAAAA/2WNQQvCMAyFI4pgDyL9AYIiHjz07H04kV2E+QfGVmdwJqVN
+                wZ9vy/Rk4IXHC3kfAEwBYJK0gO+oo9o11HnG7m1afjkO1tw5UtcIMpneBone
+                Br0q2Z+a9nEeg0pUoTZ/nxENkotiHCOJ9Xpdx+AsdUj9dYwu+V7ikGwq2Sv9
+                ZBmQcofnKEgZVvx83bLLsKWaSSLr+S3tSrZwgA8/eWd6zwAAAA==
+                """,
+            """
+                kotlinx/coroutines/CoroutineContext$DefaultImpls.class:
+                H4sIAAAAAAAA/61UW08TQRT+poVui0VuUgUULxRprbLg5YUSElMx2VjRCOHF
+                p+kylml3Z3F3toEH/4C/xkfjgz/AH2U8066I9ZIl4WHPbb7znZ1zZubb9y9f
+                ATzGE4a1bqA9qY5tNwiDWEslIrvx02wESotjXX4m3vHY045/5EUWGMNkh/e4
+                7XHVtl+1OsLVFrIMI0deHDG8rzRTkNZTgaqpUAxLzSBs2x2hWyGXKrK5UoHm
+                WgZk7wR6J/Y8QlnuICGPPMPigNnu9HxbUjhU3LMdpUPKly7tc4xh1j0Ubjch
+                eM1D7gsCMqxUmsMdqJ+J7BqSdr26X0QR42O4hMsMo2V9KKk9yym3lG0LzfDh
+                4ppZfiFO0jW0vO0JXyjzFx83tzc2zpWzdbF/vLm3Xd+qV0kylP83ZZoQb3nC
+                dK4rTvIoMaTbrGkLw1SCtV8KzQ+45hTL+L0sXRRmRMEIMLCuMei0Z46lsdbo
+                8KWoYuEOQ/HsRWKonaOtFpbp/CYOHcCUG7NQoX6QwTAzvL7aJaKRRnAgGCaa
+                FN+J/ZYI90wXGaabgcu9fR5K4yfBhTex0tIXjurJSFLo6a8J0HiGV09vzG+w
+                wq5sK67jkAiLjlIibHg8igQtje0GceiK59IUm0vo9v8ohXVkMGLmQbqAUeSQ
+                xX3yNsnPkM7XpgufMVH71Ec8IJmj0eUoZ5Xs0gCDSUz1Oeg5IIvBTnCWGSt9
+                45nEGcgCpjFDFEOFrlIhNlxo9B+FSrhG6+t99JXTgrN/L5jFQ5LzpDNYQhlz
+                uEt6JVdAlfQ90o/6RDV6yoFFypoj7PxbZB0sOLju4AYWHdzELQe3fwB+y2cT
+                9QUAAA==
+                """,
+            """
+                kotlinx/coroutines/CoroutineContext$Element$DefaultImpls.class:
+                H4sIAAAAAAAA/7VUS1MTQRD+JoFsEoPhISiiUSEIIcKCoiJBqqyI1pYRLaG4
+                eJosY9hkdxZ3Z1Nw8Ogf8Jd4pDxYnv1Rlr1J5BEta2PhYfu13V/3dPfM9x9f
+                vgJYxjrDSsNVtiUPdNP13EBZUvh6+ZdYdqUSByq/YQtHSJV/Kt7xwFaGs2/7
+                GhjDYJ03uW5zWdNfVevCVBriDH37duAzHM5WegAvRXEuFSJ5MUxVXK+m14Wq
+                etySvs6ldBVXlkvypqs2A9smL81sBySRZMi1kfV609EtMnuS27ohlUfxlknn
+                TTOMmnvCbHQAXnOPO4IcGWZmK92dKJ2ybIUgtVJhJ4MMBtK4gItUYoSTaBhk
+                WIzSxbOjGWZ4H6n759n1DPpxKY0RjDL059WeRTsw39MKMExHnG+8JhTDx/Pf
+                sPwLcRjtvKeq/rS2sbraU8z6/6l8bXujtF4qEGXI/+0K0Pryqi3CTjbEYRI5
+                hg/ntzD/0MQMruJmuDy3GKJFhjkYhjq++kuh+C5XnGwxpxmn942FJBUSMLBG
+                KNDjFDuwQmmRIXP6zjAUeyhXwwK9Hh2Frn/EejUsUcNJYBjp/r/QIKC+srsr
+                GLIVsm8GTlV42+GYGIYrrsntHe5Zod4xTrwJpLIcYcim5VtkenIyYpp/99/j
+                9+qMW2rLqkmuAo8AM4aUwivb3PcF/UpvuYFnimdWmGy8A7fzWyosIYa+sM3E
+                U/QIJBDHfdKekx4jni0Op46QnfuGoeIRxj63HB8QTRNPQMNFCntI+ljbHZdx
+                pQWXRRLjNLwVkhPENeKP6BuIdZQ2TdHuTFAFXTlvnOSc7CVnDlMEvNqKuHac
+                +/qfc8dRIjpJ2UcwhHkqVye+mEhRsN7S75J+j/S1FuAyHhPPUXSeYqffIm7g
+                toEZA7MoGJhD0cCdn3hWRYahBwAA
+                """,
+            """
+                kotlinx/coroutines/CoroutineContext$Element.class:
+                H4sIAAAAAAAA/5VSTW/TQBB9aye2EwqkKZQk5askpXyIOlQcQHxIKIBkUYrU
+                ShVSTpt0G22yWSPvOgq3/BYO/AgOKOqRH4UYhyAQXNyDZ968nZl9ntnvP75+
+                A/AI2wz3R7FVUk/DfpzEqZVamLDzG3ZibcXUtl4rMRba+mAMlSGf8FBxPQjf
+                94aiT6zL0MzRxkeRwRsI+1Z8oovv3N3LczclP2XYyZ/97N4LKmjuxckgHArb
+                S7jUJuRax5ZbGRPej+1+qhRlrS6bhu+E5cfccuKc8cSl6bDMlDIDBjYifiqz
+                qE3o+CHDk/msWnZqzuKbz37BwAlOavPZrtNmB+sVp+FVncBtux9OvxROP3te
+                oxAUKsWswS7Dg1w/tBw96drKk0957igb71mG6y8vYXh8BkmtV+KEp8pG44/K
+                +NhgWPmbYdjOqcDHdVK9eBRr/57vjEhV6VAONLdpIhg2DlJt5VhEeiKN7Cnx
+                8s9iSUGktUg6ihsjKCwfxmnSF2+kosr6svLovzqPNoICrdnLll2ggSAg5hZF
+                DkpokvfotEzeRYtsg7xDXMMr4Sqha6jjBsU3Kd5aVG3iNvnnVHUORax04UY4
+                H+FChIuoEMRqhCrWumAGl3C5C89g3eCKQc2gbuAbBD8B9Tm4oacDAAA=
+                """,
+            """
+                kotlinx/coroutines/CoroutineContext$Key.class:
+                H4sIAAAAAAAA/5VQy0oDQRCs3o3ZJL7iO74FBVHRjUEQoggSIwQVQcFLTpM4
+                ypjNLGQmEm/7XR5kz36U2BvjxVOcQ1d1TddQPZ9f7x8AjrBB2G6FNlC65zfD
+                Tti1SkvjV35pJdRW9uzWlXzzQISL02q5fD2MoxrIttT25Oz6RbwKPxD62b9t
+                vMimPSHk/2oeUoSpwcP+jbTiUVjBk0771eWklJRsUkCgFus9lXRFZo+HvEQc
+                TeScgpOLoz44+TjKPBXiaDeTiaM87TpFp+QU3WS8RNgZagVemhNQlbD/r5Up
+                Cbn3D4eHOcLmEAYPCwRv4CK4nJAw83fqoMV3YzWtZacSCGOkIWTv1bMWttuR
+                hNx92O005aUKuFm862qr2vJBGdUI5LnWoRVWhdqk+bMwgp+TwgrXaVbmUcBi
+                OsusgCXGVdYduFjr4zLWGY/5A9Ls9epwa8jUkK0hh1GmnAvjmKiDDCaRryNl
+                MGUwbTBjMPsNX1GO1pgCAAA=
+                """,
+            """
+                kotlinx/coroutines/CoroutineContext.class:
+                H4sIAAAAAAAA/5VSW08TQRT+Zrbd3ZaqW/BSioJCkZuwlfgEhMRgDQsVjBhj
+                0qehDM3S7S7ZmSXw1l/hD/Bn+GAaHv1RxrOAN0zM8jDn+p3vnMk5375/+Qrg
+                BZYYprqRDvzw1G1HcZRoP5TK3fhpbkShlqfaAmNwjsSJcAMRdtzd/SPZpqjB
+                kDsOEsXQnG1m4Fmdy4SioZpR3HGPpN6PhR8qV4RhpIX2I7J3Ir2TBAGhjI7U
+                DB8zta5ty7Ns7WuNQPZkmI4h1xorKzeqWc88zNr7xur66hxJhtr/vkt/FfuB
+                JFj5itt9I7U4EFpQjPdODFolS0UhFWBgXYqf+qlXJ+vgOUM06FeLvMKL3Bn0
+                i9zmF05qpjE7bx9WBv1lXmcrvDi0Nevwaq7CNo1J2x70HWOe13PLJSdftYdz
+                w3zTqJub55/4+WeTO9ZW2bGrvE7VplO4MNJc2naZYTrjvtOhGwyLN9yP0ZVn
+                DNm2mu6fwWpfumRd0RDLdspSz0LySh6KJNBe7zhQFh4zlP6MMCzcYH4LUwwz
+                GUe3MM0wcj2z1KXxx94lofZ70gtPfOXTpbz8fT10Wtezb0UselLL+C9YYc/v
+                hEInsaQ/eWEo441AKCUpVdyLkrgtX/sB5Uav6D7808qklSOXHiB4jiEPk/xZ
+                8kxarkV6jp7FLh0C2CjAwHwKR/EXcOgakCALJKuknxBwEqOokR43C3hKeoL0
+                swuKGSyS3qWqEvW+1YLh4baHOx4clMnEsIcR3G2BKdzD/RZKCg8UKgq2wqhC
+                VWFM4aFCQSGv8EhhXGHiBxzlJBgpBQAA
+                """
+        )
+
+    val coroutineScopeTestFile: TestFile =
+        bytecodeStub(
+            filename = "CoroutineScope.kt",
+            filepath = "kotlinx/coroutines",
+            checksum = 0x2041f1c4,
+            source =
+                """
+    package kotlinx.coroutines
+
+    public interface CoroutineScope {
+        public val coroutineContext: CoroutineContext
+    }
+
+    class ContextScopeImp(context: CoroutineContext) : CoroutineScope {
+        override val coroutineContext: CoroutineContext = context
+    }
+
+
+    public suspend fun <R> coroutineScope(block: suspend CoroutineScope.() -> R): R {
+        val newScope = ContextScopeImp(EmptyCoroutineContext)
+        return newScope.block()
+    }
+
+    public object EmptyCoroutineContext : CoroutineContext
+    """
+                    .trimIndent(),
+            """
+                META-INF/main.kotlin_module:
+                H4sIAAAAAAAA/2WNQQvCMAyFI4pgDyL9AYIiHjz07H04kV2E+QfGVmdwJqVN
+                wZ9vy/Rk4IXHC3kfAEwBYJK0gO+oo9o11HnG7m1afjkO1tw5UtcIMpneBone
+                Br0q2Z+a9nEeg0pUoTZ/nxENkotiHCOJ9Xpdx+AsdUj9dYwu+V7ikGwq2Sv9
+                ZBmQcofnKEgZVvx83bLLsKWaSSLr+S3tSrZwgA8/eWd6zwAAAA==
+                """,
+            """
+                kotlinx/coroutines/ContextScopeImp.class:
+                H4sIAAAAAAAA/41SXU8TQRQ9sy3dZS10KR+WgihfUoqyhfiGMVESkk0qGjDE
+                hKfpsinTbnfJ7rThkV/hD/AXaKLR+GAIj/4o453tBm0lysPMvffknnPn3js/
+                fn77DuAJthiW2qH0RXBuu2EUdqUIvNjeDQPpnctDNzzznM6ZDsZgtXiP2z4P
+                mvarRstzpY4Mw+KN7NRN+DpGGHJPRSDkM4ZKpf4vRlp4Z/2IYbkeRk275clG
+                xEUQ2zwIQsmlCMnfD+V+1/d3GHS3TzFgMiz0te1Wr2MLgqOA+7YTyIj4wo11
+                5Bmm3VPPbacCr3nEOx4lMqxV6sMd7vyBHCqRJj0sj3EUTIzBYshUVKyjaCKL
+                SZqRO9QIw+qt+s1jGjOj0HCXIStPRcywcjNxYDHU/2TTk8Nyqpn1W9VlmEjz
+                7Jee5CdccsK0Ti9D34Opa1RdYGBtws+FimrkndDP2bu8KJpaSUvO5UXfNbKl
+                y4ttrcZejBVzllbWapmr9znNyh5MWSMqenv1LkuIQYxy1shZulLbVuv+71dS
+                zx1ENtvU7NxBN5Ci4zlBT8Si4XvPf/8UGudueOIxFOrE2e92Gl70hlMOQ7Ee
+                utw/4pFQcQquDGtd/5ABUfMw7EautycUZzblHP1VHVu00ixNL0enqHZMtkoj
+                VPEoWY2sDoPsBkV1shpZa6N45ysmql8wVd34jNLHJPMR3ePIEFeHSZwC2ceE
+                zfQ5mEVZrYo8M6mzST4Nt1+IpoT5tIyt1kl2pPoJpQ/X2rkENBLNfD8h1Rx8
+                sZ3c66iR3SX0HuUtHCPj4L6DBw4WsUQulh2sYPUYLMZDrB3DiFGOUYlhxpiJ
+                VTgdYy7G/C9SSg1BjQQAAA==
+                """,
+            """
+                kotlinx/coroutines/CoroutineScope.class:
+                H4sIAAAAAAAA/41QTWsbMRB9ktdrZ5Mma7tN/HEqJSS9dF1Teik9FENhwXXA
+                hhDwSd6oRvZGKivZ+Ojf0kN/RA/F5NgfVTpr3IZgSAJi5s3w5mnm/f7z8xeA
+                d2gxvJwZlyq9jBKTmblTWtqo+w8OE/NNlsAYwqlYiCgVehJdjKcycSUUGGoT
+                6f6Tu0Y7uXQMZ+evew+pbokfGF71TDaJptKNM6G0jYTWxgmnDOG+cf15mhKr
+                slWLvkgnroUT1OM3iwKdwPKwlwcwsBn1lyqv2oSu3zK8X6+qAa/zgIfrVUBv
+                g8u8/LW+XnV4mw2qIW/yduHq9od3+933m17ZC4v5dCdf71FzaBX6OUx2TDh9
+                ogWV+3pvZjTbGsy1Uzcy1gtl1TiVn+58YQiGZp4l8rNKJUNjS73cIfp0BDxs
+                rPEYivBp0TpVeS5R5mhs4gmalD9St0ysvREKMYIY+zEO8IwgDmMcIRyBWVRQ
+                HcG3qFk8t3hhcWxRtPD/AoCSp91SAgAA
+                """,
+            """
+                kotlinx/coroutines/CoroutineScopeKt.class:
+                H4sIAAAAAAAA/41TW08TURD+zrb0iqXUS7koIq1SrlsQFWkhEgKhsVTTNiSE
+                p+2ykqXtLtk9rfDGkz/EX2B8MWpiGh598hcZ5yytUFqp2ew538x8c2bmzJmf
+                v7/9ALCENYZY2eQV3TiRVdMya1w3NFveaMGCah5rr7kXjCF8pNQVuaIYh/Kb
+                0pGmktbFEFLbuAzFRPbiRPmoXpXf1QyV66Zhy1tNtJhq2dsCGgRqiiCkprLX
+                I6UYfqXzK536tV7B0nPZnvWl5npklJ4r5lNrqZku8XsV03TtWlI8a1qH8pHG
+                S5aiU9KKYZhcuSggV6tUlFJFI1rsJprJBZNYE13LNLh2wp0iM9VjLwIMiS68
+                zeoxP/17J00vL/oZfJlcobie29hkmO52kV09U/0IYcCPWwj3eF5/Q0UYPGnd
+                0Dk9yETixpa1gkzt9uMO7gYQxD2GsZufgRdDFEE36maZnuhyorMdnZouPevH
+                CEaDGMZ9uhpDe9988vHuCbddPrWor1Qx1TLDeK8BYQjGVbN6XNGEfMXhXxPD
+                MNii7GhcOVC4QjqpWnfRlDOx+MUCBlYWQCLjiS5QktDBAoPaOBsJSD5XQBqS
+                Lv9w48wBZFwlPCJtswm3r3EWZouTYWkk5mMRd0RKuiOBiE+gbZbsi3gi7iGW
+                9CRd5x89ks+7ff7hlUBhnwi1SCnkGSKtdK8WHfuPUWWiiLGW9+YJ1wyb3FvH
+                FE8dzmC713yZM7g3zAPq1UCWtLlataRZRTFgIhdTVSq7iqULuan0F/RDQ+E1
+                i/BovkZ3XdUyRl23dTKvX04gNf+69a1iKVWNa1YbLVAwa5aqbeni9OGmz27H
+                eViABDcumjWMPnhIek7SHlwQDYt+R3DvMwYbuP0F0Z3p2ZmveODCJ9FVvKA1
+                QDto9kL0LRMaJ7cQ/BjDQ8cSJc0jJ0AUE4hRmJeOrxcrtHtI9tGeEmdIJPid
+                TPwOJe2sz7BK+xZp45Tf4324MniSwWQGCUxlMI2ZDGYxtw9mYx7yPvw2+mwk
+                bYxTeTYWbcRsPLWxZMPzBwVwSvaKBgAA
+                """,
+            """
+                kotlinx/coroutines/EmptyCoroutineContext.class:
+                H4sIAAAAAAAA/61VW08TQRT+ZgvdtixyUbl6p0oLyhbEG60o1ppsqNVYQjQ8
+                DWXEhe0u7k4JPJjw5A/xF0h8wGhiiL75o4xnSkWhxCzGh5kz58z5zjl7vpnZ
+                7z8+fQEwiRmG1KonHdvdMCue79Wk7YrALFTX5Gb+l573XCk2pA7G0LnC17np
+                cHfZfLK4IipkjTAMHRGjGd7KEM3Zri2nGSKp9LwBHbEEWhBnaJGv7IBhpBi2
+                mixh1pwaYYqpo0BN/ulQXvQtRc9fNleEXPS57QYmd11Pcml7tC55slRzHPLK
+                hAiWfChe8pojreqaE+joZHgdrtT/+D0G2tGdQBdOMuiVPSPD5ZC9iCwL8n4e
+                qurkrNgMV1Sy4IiqcFUCkStMTR0LMx26mNxcITudTdPMkPwbqcQoX3QEub35
+                f/z8QzsM9GJQcXWGOr8qNhnC4VUmhliu4tQvVwKaulExq1SemynlCwYuwYiT
+                cYihqxHQfCwkX+KSE1CrrkfoMWBqiqsJDGyV7Bu20jK0Whqne7G7lUhofVp9
+                7G7Fvr3V+na3JrQMe6DHtK/volqnplwnGIw/Dz7D6DGaoINS6Q2FYTjk9+uY
+                pJ7Nqp517e+XK96aGFulMIPPaq60q8Jy1+3AJq5nfvNP70jeWxIMHUXClGrV
+                ReHPqfPA0F30KtyZ576t9IYxeTjWU+7zqpDCPxA0XraXXS5rPkEMy3WFn3d4
+                EAjaSpS9ml8Rj2wVrr8Rbr6pMIwTZy1ERpRGvyKR5G1iROkdJFton15Q0u6Q
+                ZiraSLaO7CCxTQsNUw1n0JnK0mzsOaCNVorldpxApA6eIm9NeY+MfsSp90ei
+                e/Y8Gmi1Ok22gyXlaOisoTA6z31UZVOCs2ETnMN52r9b9+7fTzRwOFEMF/bb
+                0FsPArR9hvZiBxc/ILldN0QwTfMAyS6KkqF4EySvR+O4QfImyXv1PLdwv/5r
+                pFeSWnVlARELwxZSFtIYoSVGLVzFtQWwAGMwaT+AEaAnQOwn9GRn5FcHAAA=
+                """
+        )
+}
diff --git a/compose/ui/ui-lint/src/test/java/androidx/compose/ui/lint/ReturnFromAwaitPointerEventScopeDetectorTest.kt b/compose/ui/ui-lint/src/test/java/androidx/compose/ui/lint/ReturnFromAwaitPointerEventScopeDetectorTest.kt
index a562f5f..8a69674 100644
--- a/compose/ui/ui-lint/src/test/java/androidx/compose/ui/lint/ReturnFromAwaitPointerEventScopeDetectorTest.kt
+++ b/compose/ui/ui-lint/src/test/java/androidx/compose/ui/lint/ReturnFromAwaitPointerEventScopeDetectorTest.kt
@@ -87,6 +87,8 @@
             UiStubs.PointerEvent,
             ForEachGestureStub,
             UiStubs.Alignment,
+            CoroutineStubs.coroutineContextTestFile,
+            CoroutineStubs.coroutineScopeTestFile
         )
 
     @Test
@@ -110,6 +112,126 @@
         )
     }
 
+    // Current way to create a handler for the pointer input type
+    @Test
+    fun awaitPointerEventScope_assignedFromContainingPointerInputEventHandler_shouldNotWarn() {
+        expectClean(
+            """
+                package test
+                import androidx.compose.runtime.Composable
+                import androidx.compose.ui.input.pointer.PointerInputEventHandler
+
+                @Composable
+                fun SomeFunction() {
+                        val blockNew = PointerInputEventHandler {
+                            awaitPointerEventScope { }
+                        }
+                }
+            """
+        )
+    }
+
+    // Current way to create a handler for the pointer input type
+    @Test
+    fun awaitPointerEventScope_assignedFromContainingPointerInputEventHandlerAfter_shouldNotWarn() {
+        expectClean(
+            """
+                package test
+                import androidx.compose.runtime.Composable
+                import androidx.compose.ui.input.pointer.PointerInputEventHandler
+
+                @Composable
+                fun SomeFunction() {
+                        val blockNew = PointerInputEventHandler {
+                            awaitPointerEventScope { }
+                            val something = "hello"
+                        }
+                }
+            """
+        )
+    }
+
+    // Current way to create a handler for the pointer input type with variables above
+    // awaitPointerEventScope.
+    @Test
+    fun awaitPointerEventScope_assignedFromContainingPointerInputEventHandlerVars_shouldNotWarn() {
+        expectClean(
+            """
+                package test
+                import androidx.compose.runtime.Composable
+                import androidx.compose.ui.input.pointer.PointerInputEventHandler
+
+                @Composable
+                fun SomeFunction() {
+                        val blockNew = PointerInputEventHandler {
+                            var variable1 = 0
+                            var variable2 = "hello"
+                            var variable3 = 0.0
+                            var variable4 = "hello2"
+                            awaitPointerEventScope { }
+                        }
+                }
+            """
+        )
+    }
+
+    @Test
+    fun awaitPointerEventScope_assignedFromContainingLambdaMethod_shouldNotWarn() {
+        expectClean(
+            """
+                package test
+                import androidx.compose.runtime.Composable
+                import androidx.compose.ui.input.pointer.PointerInputScope
+
+                @Composable
+                fun SomeFunction() {
+                        val block: suspend PointerInputScope.() -> Unit = {
+                            awaitPointerEventScope { }
+                        }
+                }
+            """
+        )
+    }
+
+    @Test
+    fun awaitPointerEventScope_inCoroutineScopeStandaloneExtensionFunction_shouldNotWarn() {
+        expectClean(
+            """
+                package test
+                import androidx.compose.ui.input.pointer.PointerInputScope
+                import kotlinx.coroutines.coroutineScope
+
+                suspend fun PointerInputScope.detectMoves() = coroutineScope {
+                    awaitPointerEventScope { }
+                }
+            """
+        )
+    }
+
+    // Pointer input handler implicitly using PointerInputEventHandler for pointer input handler.
+    @Test
+    fun awaitPointerEventScope_standaloneExtensionFunction_shouldNotWarn() {
+        expectClean(
+            """
+                package test
+                import android.view.MotionEvent
+                import androidx.compose.ui.Modifier
+                import androidx.compose.ui.input.pointer.pointerInput
+
+                fun Modifier.motionEventSpy(watcher: (motionEvent: MotionEvent) -> Unit): Modifier =
+                    this.pointerInput(watcher) {
+                        interceptOutOfBoundsChildEvents = true
+                        awaitPointerEventScope {
+                            while (true) {
+                                val event = awaitPointerEvent(PointerEventPass.Initial)
+                                event.motionEvent?.let(watcher)
+                            }
+                        }
+                    }
+            """
+        )
+    }
+
     @Test
     fun awaitPointerEventScope_insideForEach_shouldNotWarn() {
         expectClean(
diff --git a/compose/ui/ui-lint/src/test/java/androidx/compose/ui/lint/UiStubs.kt b/compose/ui/ui-lint/src/test/java/androidx/compose/ui/lint/UiStubs.kt
index a3043ec..38e9d10 100644
--- a/compose/ui/ui-lint/src/test/java/androidx/compose/ui/lint/UiStubs.kt
+++ b/compose/ui/ui-lint/src/test/java/androidx/compose/ui/lint/UiStubs.kt
@@ -117,11 +117,12 @@
         """
         )
 
+    // Functional Interface for pointer input event handling
     val PointerInputScope: TestFile =
         bytecodeStub(
             filename = "SuspendingPointerInputFilter.kt",
             filepath = "androidx/compose/ui/input/pointer",
-            checksum = 0xa05e1a0a,
+            checksum = 0x9c1bd41d,
             """
             package androidx.compose.ui.input.pointer
             import androidx.compose.ui.unit.Density
@@ -133,58 +134,75 @@
                 ): R
             }
 
+            fun interface PointerInputEventHandler {
+                    suspend operator fun PointerInputScope.invoke()
+            }
+
             fun Modifier.pointerInput(
                 key1: Any?,
-                block: suspend PointerInputScope.() -> Unit
+                block: PointerInputEventHandler
             ): Modifier = Modifier
-        """,
-            """
-        META-INF/main.kotlin_module:
-        H4sIAAAAAAAA/2VMQQoCMRAbUQR7EOkDBMWThzl7F1dkL4J+oGzr7oDOlHYK
-        Pt/KejOQEBISAJgCwKRyAT+Yg9k59knIv7GTV5Qc8CGFvVMSxj5kLSlku2ok
-        nVw3nMegVXM0m79lISSORTEKsYZk17eSY2BP3F/H6PLtG3pWW0+WZqb10c7v
-        VVvdwh4+IfeLY6cAAAA=
-        """,
-            """
-        androidx/compose/ui/input/pointer/PointerInputScope.class:
-        H4sIAAAAAAAA/51Ty24TMRS9nsljklKYDlDSFtqSlpdQmRBg04SKClo1VYAq
-        idh05UzcyOnEjsae0O7yLSz4CBYo6pIf4S8Qd/JQSxsRxML28fXx9T328Y9f
-        374DwEt4SOAFFY1A8saJ68l2RyrmhtzlohNqtyO50CxwD4ZjKQpWPdlhSSAE
-        7BbtUtenoul+rLeYp5NgElidlC4UXLvvmFBcnyYhTmCefqZcj/LudJkY5iVQ
-        e1w+ltrnwm112+5RKDzNpVDu7gjlC+N1TwYy1Fww5b6VAkFII0LhSflyXQUC
-        P4uVzavxrWmHFTfK029ne6KUwsaUQosbtUphq/B0QlnTNI62TlS6XpZB020x
-        XQ8oRy1UCKnpUNeH0Pdp3WdIW/sbTeqIiay5cSHvmaYNqinGjHbXRO+QqEtF
-        HRAgxxg/4dEsh6jxnIDq97JpI2MMm2We46jZ/d4A9HvWUabfyxs5sv/aNhaN
-        PTMbs/o928w/smOLaxZxYo6RSzhpx4rQnplLOgknliE5Kxc/+5IwrNTe2dc3
-        EbLT0dF5Aq/+4dGuWBqVZSfuu+hdJJEKgXjdlx5KdsbXc+5OApv/bxn8PdPc
-        TaLrXh6zdk50VJgU4wJqp4M0K9VQdZhocNG8KHSX+wifHWsCqSpvCqrDAP/c
-        UiXEE9qsJLpccfTH9rkZ0FCXVw9oQNsME/1BS1dlGHgMj8CMC6M9n67kS+Ab
-        QQw1JCLjxAgkwQIT7uPMgBRkcUzgahrHNWyzBk5mBh6bGVDWB/0qPMCxjNFr
-        EIfZQzBLcL0EN0pgwxxCcEpwE24dAlFwG+YPYUbBHQUZBUkFCwoWFSwpuKvg
-        noJlBSsKrN90t5jzEwUAAA==
-        """,
-            """
-        androidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt.class:
-        H4sIAAAAAAAA/61VW28bRRT+Zu34VkPcDSmJE9KUmObSpusYym2jiBJRycIN
-        BZe85Gm8nroTr2esnd0ofetv4RcgnhAPKOKR38JvQJzZOKnTBAehPuyZc/nm
-        3OYc+8+/f/sdwCfYZviKq26kZffYC/RgqI3wEulJNUxib6ilikXktRMzFKor
-        Ve/pqaZpzY9lSOy3cR6MoXLIj7gXctXzvuscioC0GYbycAzPMFxrXRXsie7K
-        51JEfutNJ36rr+NQKu/waOA9T1QQS62M93jENfz1yQ4Z/nrbIbc3r3R4sWHj
-        bWoHeij8zTO3gY50EksljLerFTEJt363zwE/Khn7O/69y5ntXF/uSktHPe9Q
-        xJ2IS0qbK6VjflrCno73kjAkVG0SiiC8EwqC5bbjF9LsFFBiWBrrSlqb4qHX
-        VHFE92Vg8igzzAYvRNAfhXnKIz4QBGRYXbuiy681beuk56/vl/Eupkt4BxWG
-        qU6og34BLsPipJrzeI+huEsGrih/hsnvXTtH+mXcwvtFzGKOwa3ZSmsXp3Xp
-        umZn++LlFl2+XB3D8nWTy3DzDPJExLzLY046Z3CUocVklhQtAQPrW8Yh47G0
-        XJ24LsU1J69qpZNXJWfOSY8KkZF4/lWckbn6NZmrTp1t0NcoVJxqdo7VM43V
-        Sra6UmBu1nXqObfkFlKuUM+7OTdF1Kf++CnnFIqWVko2dIPZrNyz7MdLevi/
-        dmOsW/+yHb59jRHkm+NY0MxpdRb42cvUx93/9u5527/bk37RHvTp8bO7uisY
-        pluUy14y6Ijomd0KW7cOeLjPI2nlkbLYlj3F4yQifuGHhBIfiKY6kkaS+dHr
-        7aLVe9N6vicXYOWmUiLaDbkxgsRSWydRICg/CjA/crF/yT224CCL07GZxxRy
-        JH1M0vekt6Mzs+He+BU377szRH/B/Almf7azRf8EIDDFxTQeEr98CkcVC6m7
-        GSziA7JbzsUS3fg0vZfHZ6ObBTo/t/bMSKCupNTyGXxBtETSFi3cLcrty/R6
-        Az6dLdLfpmyXD5Bp4k4THzaxgloTH+FuE6tYOwAzWMfGAW4YTBksGCwa3DNw
-        De4bbBo8SEXPIPcPJkHsLNsGAAA=
         """
+                .trimIndent(),
+            """
+                META-INF/main.kotlin_module:
+                H4sIAAAAAAAA/2VMQQoCMRAbUQR7EOkDBMWThzl7F1dkL4J+oGzr7oDOlHYK
+                Pt/KejOQEBISAJgCwKRyAT+Yg9k59knIv7GTV5Qc8CGFvVMSxj5kLSlku2ok
+                nVw3nMegVXM0m79lISSORTEKsYZk17eSY2BP3F/H6PLtG3pWW0+WZqb10c7v
+                VVvdwh4+IfeLY6cAAAA=
+                """,
+            """
+                androidx/compose/ui/input/pointer/PointerInputEventHandler.class:
+                H4sIAAAAAAAA/7VSTW8TMRB9dpJNs1DYlgJpy8cBDoAEDhVcSIsECNRFAapG
+                cMnJSazIycaO1t6o3PJbOPRHcEBRuPGjELMLFaUgpCIh2fPlN/PsGX/5+vET
+                gAe4xvBImn5qdf9A9Ox4Yp0SmRbaTDIvJlYbr1Kx913HefD5VBm/SzmJSqtg
+                DNFQTqVIpBmIN92h6vkqSgyBNlM7Ugz6Vut0BO2enahma2R9og2lpDbz2ign
+                nllDRia9tqZ5u3WStsnw/r9wbd89Arw12jcf/5n7ZsumAzFUvptKbZyQxlhf
+                5DvxOksS2U0UwW78DWZ9jiTUyhHjK+VlX3pJMT6elmhmLBe1XICBjSh+oHOv
+                QVb/PsPOfLYW8joPeTSfhbR4xAt/Plv6fLiYsfp8tsUb7OVqxDd4o3SHN8q7
+                i8Oniw8Bjyp5kS2G7VP28finoKvSzR7+0yQYrrczN1Gmr83g+PELnZB5b+QZ
+                am09MNJnKX2uzf2M5jRWsZlqp6nDT362k0Zy8nRPpnKsqNAvsLBts7SniIIq
+                rv/IefdbvYB6gzKKxpcZKghQwjp5HFVskA7o2UukN2kvc3JqxYxqBeRKIeu4
+                SnqHoiEVONNBKcbZGMsxzuE8mYhirGC1A+ZwAWsdBA4XHS45VAp52SH4BreP
+                UBy8AwAA
+                """,
+            """
+                androidx/compose/ui/input/pointer/PointerInputScope.class:
+                H4sIAAAAAAAA/51Ty24TMRS9nsljklKYDlDSFtqSlpdQmRBg04SKClo1VYAq
+                idh05UzcyOnEjsae0O7yLSz4CBYo6pIf4S8Qd/JQSxsRxML28fXx9T328Y9f
+                374DwEt4SOAFFY1A8saJ68l2RyrmhtzlohNqtyO50CxwD4ZjKQpWPdlhSSAE
+                7BbtUtenoul+rLeYp5NgElidlC4UXLvvmFBcnyYhTmCefqZcj/LudJkY5iVQ
+                e1w+ltrnwm112+5RKDzNpVDu7gjlC+N1TwYy1Fww5b6VAkFII0LhSflyXQUC
+                P4uVzavxrWmHFTfK029ne6KUwsaUQosbtUphq/B0QlnTNI62TlS6XpZB020x
+                XQ8oRy1UCKnpUNeH0Pdp3WdIW/sbTeqIiay5cSHvmaYNqinGjHbXRO+QqEtF
+                HRAgxxg/4dEsh6jxnIDq97JpI2MMm2We46jZ/d4A9HvWUabfyxs5sv/aNhaN
+                PTMbs/o928w/smOLaxZxYo6RSzhpx4rQnplLOgknliE5Kxc/+5IwrNTe2dc3
+                EbLT0dF5Aq/+4dGuWBqVZSfuu+hdJJEKgXjdlx5KdsbXc+5OApv/bxn8PdPc
+                TaLrXh6zdk50VJgU4wJqp4M0K9VQdZhocNG8KHSX+wifHWsCqSpvCqrDAP/c
+                UiXEE9qsJLpccfTH9rkZ0FCXVw9oQNsME/1BS1dlGHgMj8CMC6M9n67kS+Ab
+                QQw1JCLjxAgkwQIT7uPMgBRkcUzgahrHNWyzBk5mBh6bGVDWB/0qPMCxjNFr
+                EIfZQzBLcL0EN0pgwxxCcEpwE24dAlFwG+YPYUbBHQUZBUkFCwoWFSwpuKvg
+                noJlBSsKrN90t5jzEwUAAA==
+                """,
+            """
+                androidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt.class:
+                H4sIAAAAAAAA/6VTW08TQRT+pi29WaUtoFCuSuUmsqWiMSkaDdG4sSCK4YWn
+                6XYs025nm51tg2/8AH+M8cn4YHj2RxnPtA33VBMf9sw53/nOZc6c/fX7x08A
+                G3jC8IKrqu/J6pHleM2Wp4XVlpZUrXZgtTypAuFbe23dEqoqVW23h9jG/Vq6
+                pL4NYmAM6TrvcMvlqma9q9SFQ2iYIdU6x2f4slS+rti2V5WfpPBL5ctJStfy
+                LzZ3vqVXHaGCNxTjUrblwcUY5sueX7PqIqj4XCptcaW8gAfSI33HC3barkus
+                /CAWUXjFFUSLbgaHUj+PI8Ew0/ACVyqr3mla3eYUdy1bBT7FS0fHcINhzDkU
+                TqNfZpf7vCmIyLC4dM0UzpA9k6RWWt5P4SZuJZHCMMNQxfWcRhwZhqlBd45h
+                hCGxRQ6uqH+Gwe+RP2WWUhjD7QRGcYchmzc3zV982pm/DTvSEJ/XKfjq7Rg2
+                /+eZGTLl/ry3RcCrPOCEhZqdMG04MyJhBBhYwyghch5JoxVIq1JPT0+Os8mT
+                42RoPNQ90iR6Zm6K9FyowFboK8bToVxknBXCxWg6QuiQiS8yk3rh3+YYwwOG
+                2UG/01qDhhnZ8qqCYbgsldhpNyvC/2i2zEzPc7i7z31p7D44+aGtAtkUtupI
+                LQl6ebahtL6Xvae7doGWspUS/pbLtRZkJve8tu8I6okKTPRT7F9Jj3WEEEFv
+                vBMYQhRhrJH1nnAz4pGVbPI70qvZLMlvGD/B6FfzBrBIRikohSwKpM/16JQk
+                1003gklMkd9oGUxTxHo/IkZn0eDhvsEQ70qjh/GIZJKsVVrWMUq30S33EI/p
+                fEb4DHU5e4CwjTkbd23cw7yNPO7bWMDiAZjGEpYPENUY0shpTGqsaGQ0pv8A
+                cjqS8TUFAAA=
+                """
         )
 
     val Alignment: TestFile =
diff --git a/compose/ui/ui-test-junit4/build.gradle b/compose/ui/ui-test-junit4/build.gradle
index cc0e595..863c99c 100644
--- a/compose/ui/ui-test-junit4/build.gradle
+++ b/compose/ui/ui-test-junit4/build.gradle
@@ -85,14 +85,8 @@
             }
         }
 
-        jvmTest {
-            dependsOn(commonTest)
-            dependencies {
-            }
-        }
-
         androidInstrumentedTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(project(":compose:animation:animation"))
                 implementation(project(":compose:test-utils"))
@@ -108,7 +102,7 @@
         }
 
         androidUnitTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(project(":compose:animation:animation-core"))
                 implementation(project(":compose:material:material"))
@@ -117,18 +111,6 @@
                 implementation(libs.robolectric)
             }
         }
-
-        desktopTest {
-            dependsOn(jvmTest)
-            dependencies {
-                implementation(libs.truth)
-                implementation(libs.junit)
-                implementation(libs.kotlinTest)
-                implementation(libs.skikoCurrentOs)
-                implementation(project(":compose:foundation:foundation"))
-                implementation(project(":compose:ui:ui-test-junit4"))
-            }
-        }
     }
 }
 
diff --git a/compose/ui/ui-test-junit4/src/desktopTest/kotlin/androidx/compose/ui/test/junit4/CustomEffectContextRuleTest.kt b/compose/ui/ui-test-junit4/src/desktopTest/kotlin/androidx/compose/ui/test/junit4/CustomEffectContextRuleTest.kt
deleted file mode 100644
index 735f031..0000000
--- a/compose/ui/ui-test-junit4/src/desktopTest/kotlin/androidx/compose/ui/test/junit4/CustomEffectContextRuleTest.kt
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.test.junit4
-
-import androidx.compose.runtime.rememberCoroutineScope
-import androidx.compose.ui.test.ExperimentalTestApi
-import androidx.compose.ui.test.runComposeUiTest
-import com.google.common.truth.Truth.assertThat
-import kotlin.coroutines.CoroutineContext
-import kotlinx.coroutines.CoroutineScope
-import org.junit.Rule
-import org.junit.Test
-import org.junit.rules.TestWatcher
-import org.junit.runner.Description
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-import org.junit.runners.model.Statement
-
-/**
- * Tests for passing a custom CoroutineContext to one of [ComposeTestRule]s. Similar tests are
- * available for [runComposeUiTest] in compose:ui:ui-test
- */
-@RunWith(JUnit4::class)
-@OptIn(ExperimentalTestApi::class)
-class CustomEffectContextRuleTest {
-
-    private lateinit var testDescription: Description
-
-    /**
-     * Records the current [testDescription] so it can be used when manually applying the
-     * [ComposeTestRule].
-     */
-    @get:Rule
-    val testWatcher =
-        object : TestWatcher() {
-            override fun starting(description: Description) {
-                testDescription = description
-            }
-        }
-
-    @Test
-    fun effectContextPropagatedToComposition_createComposeRule() {
-        val testElement = TestCoroutineContextElement()
-        lateinit var compositionScope: CoroutineScope
-        val rule = createComposeRule(testElement)
-        val baseStatement =
-            object : Statement() {
-                override fun evaluate() {
-                    rule.setContent { compositionScope = rememberCoroutineScope() }
-                    rule.waitForIdle()
-                }
-            }
-        rule.apply(baseStatement, testDescription).evaluate()
-
-        val elementFromComposition = compositionScope.coroutineContext[TestCoroutineContextElement]
-        assertThat(elementFromComposition).isSameInstanceAs(testElement)
-    }
-
-    private class TestCoroutineContextElement : CoroutineContext.Element {
-        override val key: CoroutineContext.Key<*>
-            get() = Key
-
-        companion object Key : CoroutineContext.Key<TestCoroutineContextElement>
-    }
-}
diff --git a/compose/ui/ui-test/api/current.txt b/compose/ui/ui-test/api/current.txt
index 9999552..4ca2049 100644
--- a/compose/ui/ui-test/api/current.txt
+++ b/compose/ui/ui-test/api/current.txt
@@ -387,9 +387,9 @@
   }
 
   public final class MouseInjectionScopeKt {
-    method public static void animateAlong(androidx.compose.ui.test.MouseInjectionScope, kotlin.jvm.functions.Function1<? super java.lang.Long,androidx.compose.ui.geometry.Offset> curve, optional long durationMillis);
-    method public static void animateBy(androidx.compose.ui.test.MouseInjectionScope, long delta, optional long durationMillis);
-    method public static void animateTo(androidx.compose.ui.test.MouseInjectionScope, long position, optional long durationMillis);
+    method public static void animateMoveAlong(androidx.compose.ui.test.MouseInjectionScope, kotlin.jvm.functions.Function1<? super java.lang.Long,androidx.compose.ui.geometry.Offset> curve, optional long durationMillis);
+    method public static void animateMoveBy(androidx.compose.ui.test.MouseInjectionScope, long delta, optional long durationMillis);
+    method public static void animateMoveTo(androidx.compose.ui.test.MouseInjectionScope, long position, optional long durationMillis);
     method public static void click(androidx.compose.ui.test.MouseInjectionScope, optional long position, optional int button);
     method public static void doubleClick(androidx.compose.ui.test.MouseInjectionScope, optional long position, optional int button);
     method public static void dragAndDrop(androidx.compose.ui.test.MouseInjectionScope, long start, long end, optional int button, optional long durationMillis);
diff --git a/compose/ui/ui-test/api/restricted_current.txt b/compose/ui/ui-test/api/restricted_current.txt
index 40c0b2c..e0e9e2d 100644
--- a/compose/ui/ui-test/api/restricted_current.txt
+++ b/compose/ui/ui-test/api/restricted_current.txt
@@ -388,9 +388,9 @@
   }
 
   public final class MouseInjectionScopeKt {
-    method public static void animateAlong(androidx.compose.ui.test.MouseInjectionScope, kotlin.jvm.functions.Function1<? super java.lang.Long,androidx.compose.ui.geometry.Offset> curve, optional long durationMillis);
-    method public static void animateBy(androidx.compose.ui.test.MouseInjectionScope, long delta, optional long durationMillis);
-    method public static void animateTo(androidx.compose.ui.test.MouseInjectionScope, long position, optional long durationMillis);
+    method public static void animateMoveAlong(androidx.compose.ui.test.MouseInjectionScope, kotlin.jvm.functions.Function1<? super java.lang.Long,androidx.compose.ui.geometry.Offset> curve, optional long durationMillis);
+    method public static void animateMoveBy(androidx.compose.ui.test.MouseInjectionScope, long delta, optional long durationMillis);
+    method public static void animateMoveTo(androidx.compose.ui.test.MouseInjectionScope, long position, optional long durationMillis);
     method public static void click(androidx.compose.ui.test.MouseInjectionScope, optional long position, optional int button);
     method public static void doubleClick(androidx.compose.ui.test.MouseInjectionScope, optional long position, optional int button);
     method public static void dragAndDrop(androidx.compose.ui.test.MouseInjectionScope, long start, long end, optional int button, optional long durationMillis);
diff --git a/compose/ui/ui-test/build.gradle b/compose/ui/ui-test/build.gradle
index a98605f..90c717f 100644
--- a/compose/ui/ui-test/build.gradle
+++ b/compose/ui/ui-test/build.gradle
@@ -85,12 +85,6 @@
             }
         }
 
-        jvmTest {
-            dependsOn(commonTest)
-            dependencies {
-            }
-        }
-
         androidCommonTest {
             dependsOn(commonTest)
             dependencies {
@@ -100,7 +94,7 @@
         }
 
         androidInstrumentedTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependsOn(androidCommonTest)
             dependencies {
                 implementation(project(":compose:material:material"))
@@ -121,7 +115,7 @@
         }
 
         androidUnitTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependsOn(androidCommonTest)
             dependencies {
                 implementation(libs.truth)
@@ -135,18 +129,6 @@
                 implementation(project(":compose:test-utils"))
             }
         }
-
-        desktopTest {
-            dependsOn(jvmTest)
-            dependencies {
-                implementation(libs.truth)
-                implementation(libs.junit)
-                implementation(libs.kotlinTest)
-                implementation(libs.skikoCurrentOs)
-                implementation(project(":compose:foundation:foundation"))
-                implementation(project(":compose:ui:ui-test"))
-            }
-        }
     }
 }
 
diff --git a/compose/ui/ui-test/samples/src/main/java/androidx/compose/ui/test/samples/MouseInjectionScopeSamples.kt b/compose/ui/ui-test/samples/src/main/java/androidx/compose/ui/test/samples/MouseInjectionScopeSamples.kt
index 792ba856..a67ade9 100644
--- a/compose/ui/ui-test/samples/src/main/java/androidx/compose/ui/test/samples/MouseInjectionScopeSamples.kt
+++ b/compose/ui/ui-test/samples/src/main/java/androidx/compose/ui/test/samples/MouseInjectionScopeSamples.kt
@@ -19,8 +19,8 @@
 import androidx.annotation.Sampled
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.test.ScrollWheel
-import androidx.compose.ui.test.animateAlong
-import androidx.compose.ui.test.animateTo
+import androidx.compose.ui.test.animateMoveAlong
+import androidx.compose.ui.test.animateMoveTo
 import androidx.compose.ui.test.click
 import androidx.compose.ui.test.onNodeWithTag
 import androidx.compose.ui.test.performMouseInput
@@ -38,24 +38,24 @@
 }
 
 @Sampled
-fun mouseInputAnimateTo() {
+fun mouseInputAnimateMoveTo() {
     composeTestRule.onNodeWithTag("myComponent").performMouseInput {
         // Hover over the node, making an X shape
         moveTo(topLeft)
-        animateTo(bottomRight)
+        animateMoveTo(bottomRight)
         // Note that an actual user wouldn't be able to instantly
         // move from the bottom right to the top right
         moveTo(topRight)
-        animateTo(bottomLeft)
+        animateMoveTo(bottomLeft)
     }
 }
 
 @Sampled
-fun mouseInputAnimateAlong() {
+fun mouseInputAnimateMoveAlong() {
     composeTestRule.onNodeWithTag("myComponent").performMouseInput {
         // Hover over the node, making a full circle with a radius of 100px
         val r = 100f
-        animateAlong(
+        animateMoveAlong(
             curve = {
                 val angle = 2 * PI * it / 1000
                 center + Offset(r * cos(angle).toFloat(), r * sin(angle).toFloat())
diff --git a/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/actions/ScrollToNodeTest.kt b/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/actions/ScrollToNodeTest.kt
index 653217f..0f442e20 100644
--- a/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/actions/ScrollToNodeTest.kt
+++ b/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/actions/ScrollToNodeTest.kt
@@ -25,8 +25,12 @@
 import androidx.compose.testutils.expectError
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.composed
+import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.geometry.Rect
 import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
+import androidx.compose.ui.input.nestedscroll.NestedScrollSource
+import androidx.compose.ui.input.nestedscroll.nestedScroll
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.platform.LocalLayoutDirection
 import androidx.compose.ui.platform.testTag
@@ -62,7 +66,8 @@
         val orientation: Orientation,
         val reverseLayout: Boolean,
         val viewportSize: ViewportSize,
-        val targetPosition: StartPosition
+        val targetPosition: StartPosition,
+        val hasNestedScrollConsumer: Boolean
     ) {
         val viewportSizePx: Int
             get() = viewportSize.sizePx
@@ -112,8 +117,10 @@
                 "targetIs=" +
                 when (targetPosition) {
                     NotInList -> "$targetPosition"
-                    else -> "${targetPosition}Viewport"
-                }
+                    else -> "${targetPosition}Viewport "
+                } +
+                "nestedScrollConsumer=" +
+                hasNestedScrollConsumer
     }
 
     companion object {
@@ -132,13 +139,16 @@
                     for (reverseScrolling in listOf(false, true)) {
                         for (viewportSize in ViewportSize.values()) {
                             for (targetPosition in StartPosition.values()) {
-                                TestConfig(
-                                        orientation = orientation,
-                                        reverseLayout = reverseScrolling,
-                                        viewportSize = viewportSize,
-                                        targetPosition = targetPosition
-                                    )
-                                    .also { add(it) }
+                                for (nestedScrollConsumer in listOf(true, false)) {
+                                    TestConfig(
+                                            orientation = orientation,
+                                            reverseLayout = reverseScrolling,
+                                            viewportSize = viewportSize,
+                                            targetPosition = targetPosition,
+                                            hasNestedScrollConsumer = nestedScrollConsumer
+                                        )
+                                        .also { add(it) }
+                                }
                             }
                         }
                     }
@@ -257,6 +267,11 @@
         Modifier.composed {
             with(LocalDensity.current) {
                 Modifier.testTag(containerTag)
+                    .then(
+                        if (config.hasNestedScrollConsumer)
+                            Modifier.nestedScroll(horizontalNestedScrollConsumer)
+                        else Modifier
+                    )
                     .requiredSize(config.viewportSizePx.toDp(), itemSizePx.toDp())
             }
         }
@@ -265,6 +280,11 @@
         Modifier.composed {
             with(LocalDensity.current) {
                 Modifier.testTag(containerTag)
+                    .then(
+                        if (config.hasNestedScrollConsumer)
+                            Modifier.nestedScroll(verticalNestedScrollConsumer)
+                        else Modifier
+                    )
                     .requiredSize(itemSizePx.toDp(), config.viewportSizePx.toDp())
             }
         }
@@ -307,4 +327,18 @@
         FullyBefore(2 * itemsAround, 20, 2 * itemsAround - 1, 50),
         NotInList(0, 0, 0, 0)
     }
+
+    private val verticalNestedScrollConsumer =
+        object : NestedScrollConnection {
+            override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
+                return Offset(0f, available.y / 2f)
+            }
+        }
+
+    private val horizontalNestedScrollConsumer =
+        object : NestedScrollConnection {
+            override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
+                return Offset(available.x / 2f, 0f)
+            }
+        }
 }
diff --git a/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/gesturescope/SendSwipeVelocityTest.kt b/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/gesturescope/SendSwipeVelocityTest.kt
index 8d0d4e7..61ea04d 100644
--- a/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/gesturescope/SendSwipeVelocityTest.kt
+++ b/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/gesturescope/SendSwipeVelocityTest.kt
@@ -22,6 +22,7 @@
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.input.pointer.util.ExperimentalVelocityTrackerApi
 import androidx.compose.ui.input.pointer.util.VelocityTrackerStrategyUseImpulse
 import androidx.compose.ui.test.InputDispatcher.Companion.eventPeriodMillis
 import androidx.compose.ui.test.junit4.createComposeRule
@@ -45,6 +46,7 @@
 import org.junit.runners.Parameterized
 
 /** Tests if we can generate gestures that end with a specific velocity */
+@OptIn(ExperimentalVelocityTrackerApi::class)
 @MediumTest
 @RunWith(Parameterized::class)
 class SendSwipeVelocityTest(private val config: TestConfig) {
diff --git a/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/injectionscope/mouse/MoveTest.kt b/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/injectionscope/mouse/MoveTest.kt
index 5ad0300..6473c55 100644
--- a/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/injectionscope/mouse/MoveTest.kt
+++ b/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/injectionscope/mouse/MoveTest.kt
@@ -25,9 +25,9 @@
 import androidx.compose.ui.test.InputDispatcher
 import androidx.compose.ui.test.MouseButton
 import androidx.compose.ui.test.MouseInjectionScope
-import androidx.compose.ui.test.animateAlong
-import androidx.compose.ui.test.animateBy
-import androidx.compose.ui.test.animateTo
+import androidx.compose.ui.test.animateMoveAlong
+import androidx.compose.ui.test.animateMoveBy
+import androidx.compose.ui.test.animateMoveTo
 import androidx.compose.ui.test.injectionscope.mouse.Common.PrimaryButton
 import androidx.compose.ui.test.injectionscope.mouse.Common.runMouseInputInjectionTest
 import androidx.compose.ui.test.injectionscope.mouse.Common.verifyMouseEvent
@@ -199,7 +199,7 @@
     @Test
     fun animatePointerTo() =
         runMouseInputInjectionTest(
-            mouseInput = { animateTo(position1, durationMillis = steps * T) },
+            mouseInput = { animateMoveTo(position1, durationMillis = steps * T) },
             eventVerifiers =
                 arrayOf(
                     { verifyMouseEvent(1 * T, Enter, false, distancePerStep * 1f) },
@@ -214,7 +214,7 @@
         runMouseInputInjectionTest(
             mouseInput = {
                 moveTo(position2)
-                animateBy(distance, durationMillis = steps * T)
+                animateMoveBy(distance, durationMillis = steps * T)
             },
             eventVerifiers =
                 arrayOf(
@@ -229,7 +229,7 @@
     @Test
     fun animateAlong_fromCurrentPosition() =
         runMouseInputInjectionTest(
-            mouseInput = { animateAlong(curveFromHere, durationMillis = steps * T) },
+            mouseInput = { animateMoveAlong(curveFromHere, durationMillis = steps * T) },
             eventVerifiers =
                 arrayOf(
                     // The curve starts at the current position (0, 0) so we expect no initial
@@ -244,7 +244,7 @@
     @Test
     fun animateAlong_fromOtherPosition() =
         runMouseInputInjectionTest(
-            mouseInput = { animateAlong(curveFromElsewhere, durationMillis = steps * T) },
+            mouseInput = { animateMoveAlong(curveFromElsewhere, durationMillis = steps * T) },
             eventVerifiers =
                 arrayOf(
                     // The curve doesn't start at the current position (0, 0) so we expect an
diff --git a/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/injectionscope/touch/SwipeWithVelocityTest.kt b/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/injectionscope/touch/SwipeWithVelocityTest.kt
index 1b389c8..1108740 100644
--- a/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/injectionscope/touch/SwipeWithVelocityTest.kt
+++ b/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/injectionscope/touch/SwipeWithVelocityTest.kt
@@ -22,6 +22,7 @@
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.input.pointer.util.ExperimentalVelocityTrackerApi
 import androidx.compose.ui.input.pointer.util.VelocityTrackerStrategyUseImpulse
 import androidx.compose.ui.test.InputDispatcher.Companion.eventPeriodMillis
 import androidx.compose.ui.test.TouchInjectionScope
@@ -52,6 +53,7 @@
  * a specific velocity. Note that the "engine" is already extensively tested in
  * [VelocityPathFinderTest], so all we need to do here is verify a few swipes.
  */
+@OptIn(ExperimentalVelocityTrackerApi::class)
 @MediumTest
 @RunWith(Parameterized::class)
 class SwipeWithVelocityTest(private val config: TestConfig) {
diff --git a/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/injectionscope/touch/VelocityPathFinderCalculateDurationTest.kt b/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/injectionscope/touch/VelocityPathFinderCalculateDurationTest.kt
index 2928eab..907b2e6 100644
--- a/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/injectionscope/touch/VelocityPathFinderCalculateDurationTest.kt
+++ b/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/injectionscope/touch/VelocityPathFinderCalculateDurationTest.kt
@@ -14,10 +14,13 @@
  * limitations under the License.
  */
 
+@file:OptIn(ExperimentalVelocityTrackerApi::class)
+
 package androidx.compose.ui.test.injectionscope.touch
 
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.geometry.isFinite
+import androidx.compose.ui.input.pointer.util.ExperimentalVelocityTrackerApi
 import androidx.compose.ui.input.pointer.util.VelocityTracker
 import androidx.compose.ui.input.pointer.util.VelocityTrackerStrategyUseImpulse
 import androidx.compose.ui.test.InputDispatcher.Companion.eventPeriodMillis
diff --git a/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/injectionscope/touch/VelocityPathFinderTest.kt b/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/injectionscope/touch/VelocityPathFinderTest.kt
index dc19c3d..8152da6 100644
--- a/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/injectionscope/touch/VelocityPathFinderTest.kt
+++ b/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/injectionscope/touch/VelocityPathFinderTest.kt
@@ -18,6 +18,7 @@
 
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.geometry.isFinite
+import androidx.compose.ui.input.pointer.util.ExperimentalVelocityTrackerApi
 import androidx.compose.ui.input.pointer.util.VelocityTracker
 import androidx.compose.ui.input.pointer.util.VelocityTrackerStrategyUseImpulse
 import androidx.compose.ui.test.InputDispatcher.Companion.eventPeriodMillis
@@ -37,6 +38,7 @@
 import org.junit.runners.Parameterized
 
 /** Tests of [VelocityPathFinder] creates paths that will lead to the desired velocity. */
+@OptIn(ExperimentalVelocityTrackerApi::class)
 @RunWith(Parameterized::class)
 class VelocityPathFinderTest(private val config: TestConfig) {
     data class TestConfig(
diff --git a/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/junit4/SynchronizationMethodsTest.kt b/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/junit4/SynchronizationMethodsTest.kt
index b4080bd..e334a2e 100644
--- a/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/junit4/SynchronizationMethodsTest.kt
+++ b/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/junit4/SynchronizationMethodsTest.kt
@@ -25,9 +25,11 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
 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.rules.TestName
 import org.junit.rules.TestRule
 import org.junit.runner.RunWith
 import org.junit.runners.model.Statement
@@ -47,6 +49,8 @@
     private val composeRootRegistry = environment.composeRootRegistry
     private val test = environment.test
 
+    @get:Rule val testName = TestName()
+
     @get:Rule
     val registryRule: TestRule = TestRule { base, _ ->
         object : Statement() {
@@ -81,6 +85,30 @@
     }
 
     @Test
+    fun runOnUiThread_exception_rethrownWithCallersStackTrace() {
+        var errorThrown = false
+        val expectedError = CustomException("test")
+        try {
+            test.runOnUiThread<Unit> { throw expectedError }
+        } catch (t: Throwable) {
+            errorThrown = true
+            assertWithMessage("caught error should be the original error")
+                .that(t)
+                .isSameInstanceAs(expectedError)
+            assertWithMessage("test thread's stacktrace should be added as a suppressed exception")
+                .that(
+                    t.suppressedExceptions.first().stackTrace.any {
+                        testName.methodName in it.methodName
+                    }
+                )
+                .isTrue()
+        }
+        assertWithMessage("error on the UI thread was not propagated by runOnUiThread")
+            .that(errorThrown)
+            .isEqualTo(true)
+    }
+
+    @Test
     fun runOnIdle() {
         val result = test.runOnIdle { "Hello" }
         assertThat(result).isEqualTo("Hello")
@@ -124,3 +152,5 @@
         return composeRoot
     }
 }
+
+private class CustomException(message: String?) : Exception(message)
diff --git a/compose/ui/ui-test/src/androidMain/kotlin/androidx/compose/ui/test/AndroidSynchronization.android.kt b/compose/ui/ui-test/src/androidMain/kotlin/androidx/compose/ui/test/AndroidSynchronization.android.kt
index af204e4..7b02370 100644
--- a/compose/ui/ui-test/src/androidMain/kotlin/androidx/compose/ui/test/AndroidSynchronization.android.kt
+++ b/compose/ui/ui-test/src/androidMain/kotlin/androidx/compose/ui/test/AndroidSynchronization.android.kt
@@ -16,7 +16,6 @@
 
 package androidx.compose.ui.test
 
-import android.annotation.SuppressLint
 import android.os.Looper
 import androidx.test.platform.app.InstrumentationRegistry
 import java.util.concurrent.ExecutionException
@@ -26,8 +25,11 @@
  * Runs the given action on the UI thread.
  *
  * This method is blocking until the action is complete.
+ *
+ * @throws Throwable Any exception that is thrown on the UI thread during execution of [action]. The
+ *   thrown exception contains a suppressed [ExecutionException] that contains the stacktrace on the
+ *   calling side.
  */
-@SuppressLint("DocumentExceptions")
 internal fun <T> runOnUiThread(action: () -> T): T {
     if (isOnUiThread()) {
         return action()
@@ -38,8 +40,19 @@
     InstrumentationRegistry.getInstrumentation().runOnMainSync(task)
     try {
         return task.get()
-    } catch (e: ExecutionException) { // Expose the original exception
-        throw e.cause!!
+    } catch (e: ExecutionException) {
+        // Throw the original exception, but add a new ExecutionException as a suppressed error
+        // to expose the caller's thread's stacktrace. We have to create a new ExecutionException
+        // to be able to remove the cause, for otherwise we would create a circular reference
+        // (cause --suppresses--> e --causedBy--> cause --suppresses--> e --etc-->)
+        throw e.cause?.also {
+            it.addSuppressed(
+                ExecutionException(
+                    "An Exception occurred on the UI thread during runOnUiThread()",
+                    null
+                )
+            )
+        } ?: e
     }
 }
 
diff --git a/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/Actions.kt b/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/Actions.kt
index b669037..507c604 100644
--- a/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/Actions.kt
+++ b/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/Actions.kt
@@ -66,16 +66,26 @@
  *
  * @return The [SemanticsNodeInteraction] that is the receiver of this method
  */
+@OptIn(InternalTestApi::class)
 fun SemanticsNodeInteraction.performScrollTo(): SemanticsNodeInteraction {
     @OptIn(ExperimentalTestApi::class) invokeGlobalAssertions()
-    @OptIn(InternalTestApi::class)
-    fetchSemanticsNode("Action performScrollTo() failed.").scrollToNode(testContext.testOwner)
+    do {
+        val shouldContinueScroll =
+            fetchSemanticsNode("Action performScrollTo() failed.")
+                .scrollToNode(testContext.testOwner)
+    } while (shouldContinueScroll)
+
     return this
 }
 
-/** Implementation of [performScrollTo] */
+/**
+ * Implementation of [performScrollTo]
+ *
+ * @return True if we were able to scroll and a subsequent scroll might be needed and false if no
+ *   scroll was needed.
+ */
 @OptIn(InternalTestApi::class)
-private fun SemanticsNode.scrollToNode(testOwner: TestOwner) {
+private fun SemanticsNode.scrollToNode(testOwner: TestOwner): Boolean {
     val scrollableNode =
         findClosestParentNode { hasScrollAction().matches(it) }
             ?: throw AssertionError(
@@ -110,7 +120,17 @@
     // And adjust for reversing properties
     if (scrollableNode.isReversedVertically) dy = -dy
 
-    testOwner.runOnUiThread { scrollableNode.config[ScrollBy].action?.invoke(dx, dy) }
+    if (
+        dx != 0f && scrollableNode.horizontalScrollAxis != null ||
+            dy != 0f && scrollableNode.verticalScrollAxis != null
+    ) {
+        // we have something to scroll
+        testOwner.runOnUiThread { scrollableNode.config[ScrollBy].action?.invoke(dx, dy) }
+        return true
+    } else {
+        // we don't have anything to scroll
+        return false // no need to scroll again
+    }
 }
 
 /**
@@ -209,12 +229,7 @@
     matcher: SemanticsMatcher
 ): SemanticsNodeInteraction {
     @OptIn(ExperimentalTestApi::class) invokeGlobalAssertions()
-    var node = fetchSemanticsNode("Failed: performScrollToNode(${matcher.description})")
-    matcher.findMatchInDescendants(node)?.also {
-        @OptIn(InternalTestApi::class) it.scrollToNode(testContext.testOwner)
-        return this
-    }
-
+    val node = scrollToMatchingDescendantOrReturnScrollable(matcher) ?: return this
     // If this is NOT a lazy list, but we haven't found the node above ..
     if (!node.isLazyList) {
         // .. throw an error that the node doesn't exist
@@ -229,30 +244,47 @@
 
     while (true) {
         // Fetch the node again
-        node = fetchSemanticsNode("Failed: performScrollToNode(${matcher.description})")
-        matcher.findMatchInDescendants(node)?.also {
-            @OptIn(InternalTestApi::class) it.scrollToNode(testContext.testOwner)
-            return this
-        }
+        val newNode = scrollToMatchingDescendantOrReturnScrollable(matcher) ?: return this
 
         // Are we there yet? Are we there yet? Are we there yet?
-        if (node.horizontalScrollAxis.isAtEnd && node.verticalScrollAxis.isAtEnd) {
+        if (newNode.horizontalScrollAxis.isAtEnd && newNode.verticalScrollAxis.isAtEnd) {
             // If we're finished and we haven't found the node
             val msg = "No node found that matches ${matcher.description} in scrollable container"
-            throw AssertionError(buildGeneralErrorMessage(msg, selector, node))
+            throw AssertionError(buildGeneralErrorMessage(msg, selector, newNode))
         }
 
-        val viewPortSize = node.layoutInfo.coordinates.boundsInParent().size
-        val dx = node.horizontalScrollAxis?.let { viewPortSize.width } ?: 0f
-        val dy = node.verticalScrollAxis?.let { viewPortSize.height } ?: 0f
+        val viewPortSize = newNode.layoutInfo.coordinates.boundsInParent().size
+        val dx = newNode.horizontalScrollAxis?.let { viewPortSize.width } ?: 0f
+        val dy = newNode.verticalScrollAxis?.let { viewPortSize.height } ?: 0f
 
         // Scroll one screen
         @OptIn(InternalTestApi::class)
-        testContext.testOwner.runOnUiThread { node.config[ScrollBy].action?.invoke(dx, dy) }
+        testContext.testOwner.runOnUiThread { newNode.config[ScrollBy].action?.invoke(dx, dy) }
     }
 }
 
 /**
+ * Searches a descendant of the caller node that matches [matcher] and scroll to that node using
+ * [scrollToNode]. Once scroll finishes this will return null. If no descendant node matches this
+ * will return the caller node.
+ */
+private fun SemanticsNodeInteraction.scrollToMatchingDescendantOrReturnScrollable(
+    matcher: SemanticsMatcher
+): SemanticsNode? {
+    var node = fetchSemanticsNode("Failed: performScrollToNode(${matcher.description})")
+    var matchedNode = matcher.scrollToMatchingDescendantOrReturnScrollable(node)
+    @OptIn(InternalTestApi::class)
+    while (matchedNode != null) {
+        val shouldContinueScroll = matchedNode.scrollToNode(testContext.testOwner)
+        if (!shouldContinueScroll) return null
+        node = fetchSemanticsNode("Failed: performScrollToNode(${matcher.description})")
+        matchedNode = matcher.scrollToMatchingDescendantOrReturnScrollable(node)
+    }
+
+    return node
+}
+
+/**
  * Executes the (partial) gesture specified in the given [block]. The gesture doesn't need to be
  * complete and can be resumed in a later invocation of [performGesture]. The event time is
  * initialized to the current time of the [MainTestClock].
@@ -689,17 +721,19 @@
     if (missingProperties.isNotEmpty()) {
         val msg =
             "${errorMessage()}, the node is missing [${
-            missingProperties.joinToString { it.name }
-        }]"
+                missingProperties.joinToString { it.name }
+            }]"
         throw AssertionError(buildGeneralErrorMessage(msg, selector, node))
     }
 }
 
 @Suppress("NOTHING_TO_INLINE") // Avoids doubling the stack depth for recursive search
-private inline fun SemanticsMatcher.findMatchInDescendants(root: SemanticsNode): SemanticsNode? {
+private inline fun SemanticsMatcher.scrollToMatchingDescendantOrReturnScrollable(
+    root: SemanticsNode
+): SemanticsNode? {
     return root.children.firstOrNull { it.layoutInfo.isPlaced && findMatchInHierarchy(it) != null }
 }
 
 private fun SemanticsMatcher.findMatchInHierarchy(node: SemanticsNode): SemanticsNode? {
-    return if (matches(node)) node else findMatchInDescendants(node)
+    return if (matches(node)) node else scrollToMatchingDescendantOrReturnScrollable(node)
 }
diff --git a/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/MouseInjectionScope.kt b/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/MouseInjectionScope.kt
index cd0593d..0b8cbf4 100644
--- a/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/MouseInjectionScope.kt
+++ b/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/MouseInjectionScope.kt
@@ -30,7 +30,7 @@
  */
 private const val SingleClickDelayMillis = 60L
 
-/** The default duration of mouse gestures with configurable time (e.g. [animateTo]). */
+/** The default duration of mouse gestures with configurable time (e.g. [animateMoveTo]). */
 private const val DefaultMouseGestureDurationMillis: Long = 300L
 
 /**
@@ -40,8 +40,8 @@
  * individual mouse events. The individual mouse events are: [press], [moveTo] and friends,
  * [release], [cancel], [scroll] and [advanceEventTime]. Full gestures are all the other functions,
  * like [MouseInjectionScope.click], [MouseInjectionScope.doubleClick],
- * [MouseInjectionScope.animateTo], etc. These are built on top of the individual events and serve
- * as a good example on how you can build your own full gesture functions.
+ * [MouseInjectionScope.animateMoveTo], etc. These are built on top of the individual events and
+ * serve as a good example on how you can build your own full gesture functions.
  *
  * A mouse move event can be sent with [moveTo] and [moveBy]. The mouse position can be updated with
  * [updatePointerTo] and [updatePointerBy], which will not send an event and only update the
@@ -405,17 +405,17 @@
  *
  * Example of moving the mouse along a line:
  *
- * @sample androidx.compose.ui.test.samples.mouseInputAnimateTo
+ * @sample androidx.compose.ui.test.samples.mouseInputAnimateMoveTo
  * @param position The position where to move the mouse to, in the node's local coordinate system
  * @param durationMillis The duration of the gesture. By default 300 milliseconds.
  */
-fun MouseInjectionScope.animateTo(
+fun MouseInjectionScope.animateMoveTo(
     position: Offset,
     durationMillis: Long = DefaultMouseGestureDurationMillis
 ) {
     val durationFloat = durationMillis.toFloat()
     val start = currentPosition
-    animateAlong(
+    animateMoveAlong(
         curve = { lerp(start, position, it / durationFloat) },
         durationMillis = durationMillis
     )
@@ -431,11 +431,11 @@
  *   right and 100 pixels upwards.
  * @param durationMillis The duration of the gesture. By default 300 milliseconds.
  */
-fun MouseInjectionScope.animateBy(
+fun MouseInjectionScope.animateMoveBy(
     delta: Offset,
     durationMillis: Long = DefaultMouseGestureDurationMillis
 ) {
-    animateTo(currentPosition + delta, durationMillis)
+    animateMoveTo(currentPosition + delta, durationMillis)
 }
 
 /**
@@ -446,13 +446,15 @@
  *
  * Example of moving the mouse along a curve:
  *
- * @sample androidx.compose.ui.test.samples.mouseInputAnimateAlong
+ * @sample androidx.compose.ui.test.samples.mouseInputAnimateMoveAlong
  * @param curve The function that defines the position of the mouse over time for this gesture, in
- *   the node's local coordinate system.
+ *   the node's local coordinate system. The argument passed to the function is the time in
+ *   milliseconds since the start of the animated move, and the return value is the location of the
+ *   mouse at that point in time
  * @param durationMillis The duration of the gesture. By default 300 milliseconds.
  */
-fun MouseInjectionScope.animateAlong(
-    curve: (Long) -> Offset,
+fun MouseInjectionScope.animateMoveAlong(
+    curve: (timeMillis: Long) -> Offset,
     durationMillis: Long = DefaultMouseGestureDurationMillis
 ) {
     require(durationMillis > 0) { "Duration is 0" }
@@ -497,7 +499,7 @@
 ) {
     updatePointerTo(start)
     press(button)
-    animateTo(end, durationMillis)
+    animateMoveTo(end, durationMillis)
     release(button)
 }
 
diff --git a/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/TouchInjectionScope.kt b/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/TouchInjectionScope.kt
index 28b4a04..44f8345 100644
--- a/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/TouchInjectionScope.kt
+++ b/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/TouchInjectionScope.kt
@@ -456,13 +456,15 @@
  * coordinates are in the node's local coordinate system, where (0, 0) is the top left corner of the
  * node. The default duration is 200 milliseconds.
  *
- * @param curve The function that defines the position of the gesture over time
+ * @param curve The function that describes the gesture. The argument passed to the function is the
+ *   time in milliseconds since the start of the swipe, and the return value is the location of the
+ *   pointer at that point in time.
  * @param durationMillis The duration of the gesture
  * @param keyTimes An optional list of timestamps in milliseconds at which a move event must be
  *   sampled
  */
 fun TouchInjectionScope.swipe(
-    curve: (Long) -> Offset,
+    curve: (timeMillis: Long) -> Offset,
     durationMillis: Long = 200,
     keyTimes: List<Long> = emptyList()
 ) {
@@ -478,13 +480,16 @@
  * coordinates are in the node's local coordinate system, where (0, 0) is the top left corner of the
  * node. The default duration is 200 milliseconds.
  *
- * @param curves The functions that define the position of the gesture over time
+ * @param curves The functions that describe the gesture. Function _i_ defines the position over
+ *   time for pointer id _i_. The argument passed to each function is the time in milliseconds since
+ *   the start of the swipe, and the return value is the location of that pointer at that point in
+ *   time.
  * @param durationMillis The duration of the gesture
  * @param keyTimes An optional list of timestamps in milliseconds at which a move event must be
  *   sampled
  */
 fun TouchInjectionScope.multiTouchSwipe(
-    curves: List<(Long) -> Offset>,
+    curves: List<(timeMillis: Long) -> Offset>,
     durationMillis: Long = 200,
     keyTimes: List<Long> = emptyList()
 ) {
diff --git a/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/VelocityPathFinder.kt b/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/VelocityPathFinder.kt
index d70c919..c52defa 100644
--- a/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/VelocityPathFinder.kt
+++ b/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/VelocityPathFinder.kt
@@ -17,6 +17,7 @@
 package androidx.compose.ui.test
 
 import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.input.pointer.util.ExperimentalVelocityTrackerApi
 import androidx.compose.ui.input.pointer.util.VelocityTracker
 import androidx.compose.ui.input.pointer.util.VelocityTrackerStrategyUseImpulse
 import androidx.compose.ui.test.InputDispatcher.Companion.eventPeriodMillis
@@ -88,6 +89,7 @@
     }
 }
 
+@OptIn(ExperimentalVelocityTrackerApi::class)
 internal fun VelocityPathFinder(
     startPosition: Offset,
     endPosition: Offset,
diff --git a/compose/ui/ui-test/src/desktopTest/kotlin/androidx/compose/ui/test/CustomEffectContextTest.kt b/compose/ui/ui-test/src/desktopTest/kotlin/androidx/compose/ui/test/CustomEffectContextTest.kt
deleted file mode 100644
index 29d942c..0000000
--- a/compose/ui/ui-test/src/desktopTest/kotlin/androidx/compose/ui/test/CustomEffectContextTest.kt
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.test
-
-import androidx.compose.runtime.rememberCoroutineScope
-import androidx.compose.ui.MotionDurationScale
-import com.google.common.truth.Truth.assertThat
-import kotlin.coroutines.CoroutineContext
-import kotlinx.coroutines.CoroutineScope
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-/**
- * Tests for passing a custom CoroutineContext when [running a ComposeUiTest][runComposeUiTest].
- * Similar tests are available for ComposeTestRule in compose:ui:ui-test-junit4
- */
-@RunWith(JUnit4::class)
-@OptIn(ExperimentalTestApi::class)
-class CustomEffectContextTest {
-
-    @Test
-    fun effectContextPropagatedToComposition_runComposeUiTest() {
-        val testElement = TestCoroutineContextElement()
-        runComposeUiTest(effectContext = testElement) {
-            lateinit var compositionScope: CoroutineScope
-            setContent { compositionScope = rememberCoroutineScope() }
-
-            runOnIdle {
-                val elementFromComposition =
-                    compositionScope.coroutineContext[TestCoroutineContextElement]
-                assertThat(elementFromComposition).isSameInstanceAs(testElement)
-            }
-        }
-    }
-
-    @Test
-    fun motionDurationScale_defaultValue() = runComposeUiTest {
-        var lastRecordedMotionDurationScale: Float? = null
-        setContent {
-            val context = rememberCoroutineScope().coroutineContext
-            lastRecordedMotionDurationScale = context[MotionDurationScale]?.scaleFactor
-        }
-
-        runOnIdle { assertThat(lastRecordedMotionDurationScale).isNull() }
-    }
-
-    @Test
-    fun motionDurationScale_propagatedToCoroutines() {
-        val motionDurationScale =
-            object : MotionDurationScale {
-                override val scaleFactor: Float
-                    get() = 0f
-            }
-        runComposeUiTest(effectContext = motionDurationScale) {
-            var lastRecordedMotionDurationScale: Float? = null
-            setContent {
-                val context = rememberCoroutineScope().coroutineContext
-                lastRecordedMotionDurationScale = context[MotionDurationScale]?.scaleFactor
-            }
-
-            runOnIdle { assertThat(lastRecordedMotionDurationScale).isEqualTo(0f) }
-        }
-    }
-
-    private class TestCoroutineContextElement : CoroutineContext.Element {
-        override val key: CoroutineContext.Key<*>
-            get() = Key
-
-        companion object Key : CoroutineContext.Key<TestCoroutineContextElement>
-    }
-}
diff --git a/compose/ui/ui-text/api/current.txt b/compose/ui/ui-text/api/current.txt
index 58f340d..f93f646 100644
--- a/compose/ui/ui-text/api/current.txt
+++ b/compose/ui/ui-text/api/current.txt
@@ -7,7 +7,9 @@
   }
 
   @androidx.compose.runtime.Immutable public final class AnnotatedString implements java.lang.CharSequence {
+    ctor public AnnotatedString(String text, optional java.util.List<? extends androidx.compose.ui.text.AnnotatedString.Range<? extends androidx.compose.ui.text.AnnotatedString.Annotation>> annotations);
     ctor public AnnotatedString(String text, optional java.util.List<androidx.compose.ui.text.AnnotatedString.Range<androidx.compose.ui.text.SpanStyle>> spanStyles, optional java.util.List<androidx.compose.ui.text.AnnotatedString.Range<androidx.compose.ui.text.ParagraphStyle>> paragraphStyles);
+    method public androidx.compose.ui.text.AnnotatedString flatMapAnnotations(kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.AnnotatedString.Range<? extends androidx.compose.ui.text.AnnotatedString.Annotation>,? extends java.util.List<? extends androidx.compose.ui.text.AnnotatedString.Range<? extends androidx.compose.ui.text.AnnotatedString.Annotation>>> transform);
     method public operator char get(int index);
     method public int getLength();
     method public java.util.List<androidx.compose.ui.text.AnnotatedString.Range<androidx.compose.ui.text.LinkAnnotation>> getLinkAnnotations(int start, int end);
@@ -21,6 +23,7 @@
     method public boolean hasEqualAnnotations(androidx.compose.ui.text.AnnotatedString other);
     method public boolean hasLinkAnnotations(int start, int end);
     method public boolean hasStringAnnotations(String tag, int start, int end);
+    method public androidx.compose.ui.text.AnnotatedString mapAnnotations(kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.AnnotatedString.Range<? extends androidx.compose.ui.text.AnnotatedString.Annotation>,? extends androidx.compose.ui.text.AnnotatedString.Range<? extends androidx.compose.ui.text.AnnotatedString.Annotation>> transform);
     method @androidx.compose.runtime.Stable public operator androidx.compose.ui.text.AnnotatedString plus(androidx.compose.ui.text.AnnotatedString other);
     method public androidx.compose.ui.text.AnnotatedString subSequence(int startIndex, int endIndex);
     method public androidx.compose.ui.text.AnnotatedString subSequence(long range);
@@ -31,6 +34,9 @@
     field public static final androidx.compose.ui.text.AnnotatedString.Companion Companion;
   }
 
+  public static sealed interface AnnotatedString.Annotation {
+  }
+
   public static final class AnnotatedString.Builder implements java.lang.Appendable {
     ctor public AnnotatedString.Builder(androidx.compose.ui.text.AnnotatedString text);
     ctor public AnnotatedString.Builder(optional int capacity);
@@ -124,7 +130,7 @@
   @SuppressCompatibility @kotlin.RequiresOptIn(level=kotlin.RequiresOptIn.Level.ERROR, message="This is internal API that may change frequently and without warning.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.CLASS, kotlin.annotation.AnnotationTarget.FUNCTION, kotlin.annotation.AnnotationTarget.PROPERTY}) public @interface InternalTextApi {
   }
 
-  public abstract class LinkAnnotation {
+  public abstract class LinkAnnotation implements androidx.compose.ui.text.AnnotatedString.Annotation {
     method public abstract androidx.compose.ui.text.LinkInteractionListener? getLinkInteractionListener();
     method public abstract androidx.compose.ui.text.TextLinkStyles? getStyles();
     property public abstract androidx.compose.ui.text.LinkInteractionListener? linkInteractionListener;
@@ -133,6 +139,7 @@
 
   public static final class LinkAnnotation.Clickable extends androidx.compose.ui.text.LinkAnnotation {
     ctor public LinkAnnotation.Clickable(String tag, optional androidx.compose.ui.text.TextLinkStyles? styles, androidx.compose.ui.text.LinkInteractionListener? linkInteractionListener);
+    method public androidx.compose.ui.text.LinkAnnotation.Clickable copy(optional String tag, optional androidx.compose.ui.text.TextLinkStyles? styles, optional androidx.compose.ui.text.LinkInteractionListener? linkInteractionListener);
     method public androidx.compose.ui.text.LinkInteractionListener? getLinkInteractionListener();
     method public androidx.compose.ui.text.TextLinkStyles? getStyles();
     method public String getTag();
@@ -143,6 +150,7 @@
 
   public static final class LinkAnnotation.Url extends androidx.compose.ui.text.LinkAnnotation {
     ctor public LinkAnnotation.Url(String url, optional androidx.compose.ui.text.TextLinkStyles? styles, optional androidx.compose.ui.text.LinkInteractionListener? linkInteractionListener);
+    method public androidx.compose.ui.text.LinkAnnotation.Url copy(optional String url, optional androidx.compose.ui.text.TextLinkStyles? styles, optional androidx.compose.ui.text.LinkInteractionListener? linkInteractionListener);
     method public androidx.compose.ui.text.LinkInteractionListener? getLinkInteractionListener();
     method public androidx.compose.ui.text.TextLinkStyles? getStyles();
     method public String getUrl();
@@ -292,7 +300,7 @@
     method public static androidx.compose.ui.text.Paragraph Paragraph(String text, androidx.compose.ui.text.TextStyle style, long constraints, androidx.compose.ui.unit.Density density, androidx.compose.ui.text.font.FontFamily.Resolver fontFamilyResolver, optional java.util.List<androidx.compose.ui.text.AnnotatedString.Range<androidx.compose.ui.text.SpanStyle>> spanStyles, optional java.util.List<androidx.compose.ui.text.AnnotatedString.Range<androidx.compose.ui.text.Placeholder>> placeholders, optional int maxLines, optional boolean ellipsis);
   }
 
-  @androidx.compose.runtime.Immutable public final class ParagraphStyle {
+  @androidx.compose.runtime.Immutable public final class ParagraphStyle implements androidx.compose.ui.text.AnnotatedString.Annotation {
     ctor @Deprecated public ParagraphStyle(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent);
     ctor @Deprecated public ParagraphStyle(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle);
     ctor @Deprecated public ParagraphStyle(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens);
@@ -407,7 +415,7 @@
     property public final androidx.compose.ui.text.PlatformSpanStyle? spanStyle;
   }
 
-  @androidx.compose.runtime.Immutable public final class SpanStyle {
+  @androidx.compose.runtime.Immutable public final class SpanStyle implements androidx.compose.ui.text.AnnotatedString.Annotation {
     ctor public SpanStyle(androidx.compose.ui.graphics.Brush? brush, optional float alpha, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle);
     ctor @Deprecated public SpanStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow);
     ctor @Deprecated public SpanStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle);
@@ -460,6 +468,12 @@
     method public static androidx.compose.ui.text.SpanStyle lerp(androidx.compose.ui.text.SpanStyle start, androidx.compose.ui.text.SpanStyle stop, float fraction);
   }
 
+  @kotlin.jvm.JvmInline public final value class StringAnnotation implements androidx.compose.ui.text.AnnotatedString.Annotation {
+    ctor public StringAnnotation(String value);
+    method public String getValue();
+    property public final String value;
+  }
+
   public final class StringKt {
     method public static String capitalize(String, androidx.compose.ui.text.intl.Locale locale);
     method public static String capitalize(String, androidx.compose.ui.text.intl.LocaleList localeList);
@@ -730,10 +744,10 @@
     method public static androidx.compose.ui.text.TextStyle resolveDefaults(androidx.compose.ui.text.TextStyle style, androidx.compose.ui.unit.LayoutDirection direction);
   }
 
-  public abstract sealed class TtsAnnotation {
+  public abstract sealed class TtsAnnotation implements androidx.compose.ui.text.AnnotatedString.Annotation {
   }
 
-  @Deprecated @SuppressCompatibility @androidx.compose.ui.text.ExperimentalTextApi public final class UrlAnnotation {
+  @Deprecated @SuppressCompatibility @androidx.compose.ui.text.ExperimentalTextApi public final class UrlAnnotation implements androidx.compose.ui.text.AnnotatedString.Annotation {
     ctor @Deprecated public UrlAnnotation(String url);
     method @Deprecated public String getUrl();
     property @Deprecated public final String url;
@@ -1494,9 +1508,13 @@
 
   public final class LineHeightStyle {
     ctor public LineHeightStyle(float alignment, int trim);
+    ctor public LineHeightStyle(float alignment, int trim, int mode);
+    method public androidx.compose.ui.text.style.LineHeightStyle copy(optional float alignment, optional int trim, optional int mode);
     method public float getAlignment();
+    method public int getMode();
     method public int getTrim();
     property public final float alignment;
+    property public final int mode;
     property public final int trim;
     field public static final androidx.compose.ui.text.style.LineHeightStyle.Companion Companion;
   }
@@ -1522,6 +1540,17 @@
     property public final androidx.compose.ui.text.style.LineHeightStyle Default;
   }
 
+  @kotlin.jvm.JvmInline public static final value class LineHeightStyle.Mode {
+    field public static final androidx.compose.ui.text.style.LineHeightStyle.Mode.Companion Companion;
+  }
+
+  public static final class LineHeightStyle.Mode.Companion {
+    method public int getFixed();
+    method public int getMinimum();
+    property public final int Fixed;
+    property public final int Minimum;
+  }
+
   @kotlin.jvm.JvmInline public static final value class LineHeightStyle.Trim {
     field public static final androidx.compose.ui.text.style.LineHeightStyle.Trim.Companion Companion;
   }
diff --git a/compose/ui/ui-text/api/restricted_current.txt b/compose/ui/ui-text/api/restricted_current.txt
index 081cd6f..1375e6c 100644
--- a/compose/ui/ui-text/api/restricted_current.txt
+++ b/compose/ui/ui-text/api/restricted_current.txt
@@ -7,7 +7,9 @@
   }
 
   @androidx.compose.runtime.Immutable public final class AnnotatedString implements java.lang.CharSequence {
+    ctor public AnnotatedString(String text, optional java.util.List<? extends androidx.compose.ui.text.AnnotatedString.Range<? extends androidx.compose.ui.text.AnnotatedString.Annotation>> annotations);
     ctor public AnnotatedString(String text, optional java.util.List<androidx.compose.ui.text.AnnotatedString.Range<androidx.compose.ui.text.SpanStyle>> spanStyles, optional java.util.List<androidx.compose.ui.text.AnnotatedString.Range<androidx.compose.ui.text.ParagraphStyle>> paragraphStyles);
+    method public androidx.compose.ui.text.AnnotatedString flatMapAnnotations(kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.AnnotatedString.Range<? extends androidx.compose.ui.text.AnnotatedString.Annotation>,? extends java.util.List<? extends androidx.compose.ui.text.AnnotatedString.Range<? extends androidx.compose.ui.text.AnnotatedString.Annotation>>> transform);
     method public operator char get(int index);
     method public int getLength();
     method public java.util.List<androidx.compose.ui.text.AnnotatedString.Range<androidx.compose.ui.text.LinkAnnotation>> getLinkAnnotations(int start, int end);
@@ -21,6 +23,7 @@
     method public boolean hasEqualAnnotations(androidx.compose.ui.text.AnnotatedString other);
     method public boolean hasLinkAnnotations(int start, int end);
     method public boolean hasStringAnnotations(String tag, int start, int end);
+    method public androidx.compose.ui.text.AnnotatedString mapAnnotations(kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.AnnotatedString.Range<? extends androidx.compose.ui.text.AnnotatedString.Annotation>,? extends androidx.compose.ui.text.AnnotatedString.Range<? extends androidx.compose.ui.text.AnnotatedString.Annotation>> transform);
     method @androidx.compose.runtime.Stable public operator androidx.compose.ui.text.AnnotatedString plus(androidx.compose.ui.text.AnnotatedString other);
     method public androidx.compose.ui.text.AnnotatedString subSequence(int startIndex, int endIndex);
     method public androidx.compose.ui.text.AnnotatedString subSequence(long range);
@@ -31,6 +34,9 @@
     field public static final androidx.compose.ui.text.AnnotatedString.Companion Companion;
   }
 
+  public static sealed interface AnnotatedString.Annotation {
+  }
+
   public static final class AnnotatedString.Builder implements java.lang.Appendable {
     ctor public AnnotatedString.Builder(androidx.compose.ui.text.AnnotatedString text);
     ctor public AnnotatedString.Builder(optional int capacity);
@@ -124,7 +130,7 @@
   @SuppressCompatibility @kotlin.RequiresOptIn(level=kotlin.RequiresOptIn.Level.ERROR, message="This is internal API that may change frequently and without warning.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.CLASS, kotlin.annotation.AnnotationTarget.FUNCTION, kotlin.annotation.AnnotationTarget.PROPERTY}) public @interface InternalTextApi {
   }
 
-  public abstract class LinkAnnotation {
+  public abstract class LinkAnnotation implements androidx.compose.ui.text.AnnotatedString.Annotation {
     method public abstract androidx.compose.ui.text.LinkInteractionListener? getLinkInteractionListener();
     method public abstract androidx.compose.ui.text.TextLinkStyles? getStyles();
     property public abstract androidx.compose.ui.text.LinkInteractionListener? linkInteractionListener;
@@ -133,6 +139,7 @@
 
   public static final class LinkAnnotation.Clickable extends androidx.compose.ui.text.LinkAnnotation {
     ctor public LinkAnnotation.Clickable(String tag, optional androidx.compose.ui.text.TextLinkStyles? styles, androidx.compose.ui.text.LinkInteractionListener? linkInteractionListener);
+    method public androidx.compose.ui.text.LinkAnnotation.Clickable copy(optional String tag, optional androidx.compose.ui.text.TextLinkStyles? styles, optional androidx.compose.ui.text.LinkInteractionListener? linkInteractionListener);
     method public androidx.compose.ui.text.LinkInteractionListener? getLinkInteractionListener();
     method public androidx.compose.ui.text.TextLinkStyles? getStyles();
     method public String getTag();
@@ -143,6 +150,7 @@
 
   public static final class LinkAnnotation.Url extends androidx.compose.ui.text.LinkAnnotation {
     ctor public LinkAnnotation.Url(String url, optional androidx.compose.ui.text.TextLinkStyles? styles, optional androidx.compose.ui.text.LinkInteractionListener? linkInteractionListener);
+    method public androidx.compose.ui.text.LinkAnnotation.Url copy(optional String url, optional androidx.compose.ui.text.TextLinkStyles? styles, optional androidx.compose.ui.text.LinkInteractionListener? linkInteractionListener);
     method public androidx.compose.ui.text.LinkInteractionListener? getLinkInteractionListener();
     method public androidx.compose.ui.text.TextLinkStyles? getStyles();
     method public String getUrl();
@@ -292,7 +300,7 @@
     method public static androidx.compose.ui.text.Paragraph Paragraph(String text, androidx.compose.ui.text.TextStyle style, long constraints, androidx.compose.ui.unit.Density density, androidx.compose.ui.text.font.FontFamily.Resolver fontFamilyResolver, optional java.util.List<androidx.compose.ui.text.AnnotatedString.Range<androidx.compose.ui.text.SpanStyle>> spanStyles, optional java.util.List<androidx.compose.ui.text.AnnotatedString.Range<androidx.compose.ui.text.Placeholder>> placeholders, optional int maxLines, optional boolean ellipsis);
   }
 
-  @androidx.compose.runtime.Immutable public final class ParagraphStyle {
+  @androidx.compose.runtime.Immutable public final class ParagraphStyle implements androidx.compose.ui.text.AnnotatedString.Annotation {
     ctor @Deprecated public ParagraphStyle(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent);
     ctor @Deprecated public ParagraphStyle(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle);
     ctor @Deprecated public ParagraphStyle(optional androidx.compose.ui.text.style.TextAlign? textAlign, optional androidx.compose.ui.text.style.TextDirection? textDirection, optional long lineHeight, optional androidx.compose.ui.text.style.TextIndent? textIndent, optional androidx.compose.ui.text.PlatformParagraphStyle? platformStyle, optional androidx.compose.ui.text.style.LineHeightStyle? lineHeightStyle, optional androidx.compose.ui.text.style.LineBreak? lineBreak, optional androidx.compose.ui.text.style.Hyphens? hyphens);
@@ -407,7 +415,7 @@
     property public final androidx.compose.ui.text.PlatformSpanStyle? spanStyle;
   }
 
-  @androidx.compose.runtime.Immutable public final class SpanStyle {
+  @androidx.compose.runtime.Immutable public final class SpanStyle implements androidx.compose.ui.text.AnnotatedString.Annotation {
     ctor public SpanStyle(androidx.compose.ui.graphics.Brush? brush, optional float alpha, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle, optional androidx.compose.ui.graphics.drawscope.DrawStyle? drawStyle);
     ctor @Deprecated public SpanStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow);
     ctor @Deprecated public SpanStyle(optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional String? fontFeatureSettings, optional long letterSpacing, optional androidx.compose.ui.text.style.BaselineShift? baselineShift, optional androidx.compose.ui.text.style.TextGeometricTransform? textGeometricTransform, optional androidx.compose.ui.text.intl.LocaleList? localeList, optional long background, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.graphics.Shadow? shadow, optional androidx.compose.ui.text.PlatformSpanStyle? platformStyle);
@@ -460,6 +468,12 @@
     method public static androidx.compose.ui.text.SpanStyle lerp(androidx.compose.ui.text.SpanStyle start, androidx.compose.ui.text.SpanStyle stop, float fraction);
   }
 
+  @kotlin.jvm.JvmInline public final value class StringAnnotation implements androidx.compose.ui.text.AnnotatedString.Annotation {
+    ctor public StringAnnotation(String value);
+    method public String getValue();
+    property public final String value;
+  }
+
   public final class StringKt {
     method public static String capitalize(String, androidx.compose.ui.text.intl.Locale locale);
     method public static String capitalize(String, androidx.compose.ui.text.intl.LocaleList localeList);
@@ -730,10 +744,10 @@
     method public static androidx.compose.ui.text.TextStyle resolveDefaults(androidx.compose.ui.text.TextStyle style, androidx.compose.ui.unit.LayoutDirection direction);
   }
 
-  public abstract sealed class TtsAnnotation {
+  public abstract sealed class TtsAnnotation implements androidx.compose.ui.text.AnnotatedString.Annotation {
   }
 
-  @Deprecated @SuppressCompatibility @androidx.compose.ui.text.ExperimentalTextApi public final class UrlAnnotation {
+  @Deprecated @SuppressCompatibility @androidx.compose.ui.text.ExperimentalTextApi public final class UrlAnnotation implements androidx.compose.ui.text.AnnotatedString.Annotation {
     ctor @Deprecated public UrlAnnotation(String url);
     method @Deprecated public String getUrl();
     property @Deprecated public final String url;
@@ -1505,9 +1519,13 @@
 
   public final class LineHeightStyle {
     ctor public LineHeightStyle(float alignment, int trim);
+    ctor public LineHeightStyle(float alignment, int trim, int mode);
+    method public androidx.compose.ui.text.style.LineHeightStyle copy(optional float alignment, optional int trim, optional int mode);
     method public float getAlignment();
+    method public int getMode();
     method public int getTrim();
     property public final float alignment;
+    property public final int mode;
     property public final int trim;
     field public static final androidx.compose.ui.text.style.LineHeightStyle.Companion Companion;
   }
@@ -1533,6 +1551,17 @@
     property public final androidx.compose.ui.text.style.LineHeightStyle Default;
   }
 
+  @kotlin.jvm.JvmInline public static final value class LineHeightStyle.Mode {
+    field public static final androidx.compose.ui.text.style.LineHeightStyle.Mode.Companion Companion;
+  }
+
+  public static final class LineHeightStyle.Mode.Companion {
+    method public int getFixed();
+    method public int getMinimum();
+    property public final int Fixed;
+    property public final int Minimum;
+  }
+
   @kotlin.jvm.JvmInline public static final value class LineHeightStyle.Trim {
     field public static final androidx.compose.ui.text.style.LineHeightStyle.Trim.Companion Companion;
   }
diff --git a/compose/ui/ui-text/build.gradle b/compose/ui/ui-text/build.gradle
index 0ce873d..89ce61f 100644
--- a/compose/ui/ui-text/build.gradle
+++ b/compose/ui/ui-text/build.gradle
@@ -56,6 +56,8 @@
 
         commonTest {
             dependencies {
+                implementation(libs.junit)
+                implementation(libs.truth)
             }
         }
 
@@ -90,14 +92,8 @@
             dependsOn(jvmMain)
         }
 
-        jvmTest {
-            dependsOn(commonTest)
-            dependencies {
-            }
-        }
-
         androidInstrumentedTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(project(":compose:ui:ui-test-junit4"))
                 implementation(project(":internal-testutils-fonts"))
@@ -115,7 +111,7 @@
         }
 
         androidUnitTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(project(":internal-testutils-fonts"))
                 implementation(libs.testRules)
@@ -129,20 +125,6 @@
                 implementation(libs.byteBuddy)
             }
         }
-
-        desktopTest {
-            dependsOn(jvmTest)
-            dependencies {
-                implementation(libs.truth)
-                implementation(libs.junit)
-                implementation(libs.kotlinTest)
-                implementation(libs.skikoCurrentOs)
-                implementation(project(":compose:foundation:foundation"))
-                implementation(project(":compose:ui:ui-test-junit4"))
-                implementation(project(":internal-testutils-fonts"))
-            }
-        }
-
         androidMain.kotlin.srcDirs("${supportRootFolder}/text/text/src/main/java")
     }
 }
diff --git a/compose/ui/ui-text/samples/src/main/java/androidx/compose/ui/text/samples/AnnotatedStringBuilderSamples.kt b/compose/ui/ui-text/samples/src/main/java/androidx/compose/ui/text/samples/AnnotatedStringBuilderSamples.kt
index 08354d2..d804ae8 100644
--- a/compose/ui/ui-text/samples/src/main/java/androidx/compose/ui/text/samples/AnnotatedStringBuilderSamples.kt
+++ b/compose/ui/ui-text/samples/src/main/java/androidx/compose/ui/text/samples/AnnotatedStringBuilderSamples.kt
@@ -22,6 +22,7 @@
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.platform.LocalUriHandler
 import androidx.compose.ui.text.AnnotatedString
+import androidx.compose.ui.text.AnnotatedString.Range
 import androidx.compose.ui.text.LinkAnnotation
 import androidx.compose.ui.text.ParagraphStyle
 import androidx.compose.ui.text.SpanStyle
@@ -51,6 +52,24 @@
 }
 
 @Sampled
+fun AnnotatedStringMainConstructorSample() {
+    AnnotatedString(
+        text = "Jetpack Compose",
+        // mark all text as a link, separate it into two paragraphs and make "Compose" italic
+        annotations =
+            listOf(
+                AnnotatedString.Range(
+                    LinkAnnotation.Url("https://developer.android.com/jetpack/compose"),
+                    0,
+                    15
+                ),
+                AnnotatedString.Range(ParagraphStyle(textAlign = TextAlign.Center), 0, 8),
+                AnnotatedString.Range(SpanStyle(fontStyle = FontStyle.Italic), 8, 15)
+            )
+    )
+}
+
+@Sampled
 fun AnnotatedStringBuilderSample() {
     buildAnnotatedString {
         append("Hello")
@@ -226,3 +245,23 @@
         }
     )
 }
+
+@Composable
+@Sampled
+@Suppress("UNCHECKED_CAST")
+fun AnnotatedStringMapAnnotationsSamples(text: AnnotatedString, linkColor: Color) {
+    // An example of applying color to the links in the given text where the `linkColor` would
+    // usually come from the theme in your app
+    val linkStyles = TextLinkStyles(style = SpanStyle(color = linkColor))
+    BasicText(
+        text.mapAnnotations {
+            when (it.item) {
+                is LinkAnnotation.Url ->
+                    (it as Range<LinkAnnotation.Url>).copy(it.item.copy(styles = linkStyles))
+                is LinkAnnotation.Clickable ->
+                    (it as Range<LinkAnnotation.Clickable>).copy(it.item.copy(styles = linkStyles))
+                else -> it
+            }
+        }
+    )
+}
diff --git a/compose/ui/ui-text/src/androidInstrumentedTest/kotlin/androidx/compose/ui/text/AnnotatedStringFromHtmlTest.kt b/compose/ui/ui-text/src/androidInstrumentedTest/kotlin/androidx/compose/ui/text/AnnotatedStringFromHtmlTest.kt
index 1722723..6e7661d 100644
--- a/compose/ui/ui-text/src/androidInstrumentedTest/kotlin/androidx/compose/ui/text/AnnotatedStringFromHtmlTest.kt
+++ b/compose/ui/ui-text/src/androidInstrumentedTest/kotlin/androidx/compose/ui/text/AnnotatedStringFromHtmlTest.kt
@@ -41,6 +41,7 @@
 import androidx.compose.ui.test.captureToImage
 import androidx.compose.ui.test.hasClickAction
 import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithText
 import androidx.compose.ui.text.font.FontFamily
 import androidx.compose.ui.text.font.FontStyle
 import androidx.compose.ui.text.font.FontWeight
@@ -376,8 +377,8 @@
 
     @Test
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
-    fun link_appliesColorFromMethod() {
-        val stringWithColoredLink = "<span style=\"color:blue\"><a href=\"url\">link</a></span>"
+    fun link_appliesColorFromHtmlTag_rightMostAlwaysWinsInNestedStyling() {
+        val stringWithColoredLink = "<span style=\"color:blue\">text<a href=\"url\">link</a></span>"
         val annotatedString =
             AnnotatedString.fromHtml(
                 stringWithColoredLink,
@@ -386,11 +387,30 @@
 
         rule.setContent { BasicText(text = annotatedString) }
 
+        // b/347661747 closing tags always win in fromHtml method therefore nested styling is not
+        // fully supported.
         rule
-            .onNode(hasClickAction(), useUnmergedTree = true)
+            .onNodeWithText("text", substring = true)
             .captureToImage()
-            .assertContainsColor(Color.Green)
-            .assertDoesNotContainColor(Color.Blue)
+            .assertContainsColor(Color.Blue)
+            .assertDoesNotContainColor(Color.Green)
+    }
+
+    @Test
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    fun link_appliesColorFromMethod_whenNoNestedStyling() {
+        val stringWithColoredLink = "<a href=\"url\">link</a>"
+        val annotatedString =
+            AnnotatedString.fromHtml(
+                stringWithColoredLink,
+                TextLinkStyles(SpanStyle(color = Color.Green))
+            )
+
+        rule.setContent { BasicText(text = annotatedString) }
+
+        // b/347661747 closing tags always win in fromHtml method therefore nested styling is not
+        // fully supported.
+        rule.onNodeWithText("link").captureToImage().assertContainsColor(Color.Green)
     }
 
     @Test
diff --git a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/Html.android.kt b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/Html.android.kt
index b46b704..3a81e24 100644
--- a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/Html.android.kt
+++ b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/Html.android.kt
@@ -50,10 +50,39 @@
 import org.xml.sax.ContentHandler
 import org.xml.sax.XMLReader
 
-actual fun AnnotatedString.Companion.fromHtml(
+/**
+ * Converts a string with HTML tags into [AnnotatedString].
+ *
+ * If you define your string in the resources, make sure to use HTML-escaped opening brackets "&lt;"
+ * instead of "<".
+ *
+ * For a list of supported tags go check
+ * [Styling with HTML markup](https://developer.android.com/guide/topics/resources/string-resource#StylingWithHTML)
+ * guide. Note that bullet lists are not **yet** available.
+ *
+ * @param htmlString HTML-tagged string to be parsed to construct AnnotatedString
+ * @param linkStyles style configuration to be applied to links present in the string in different
+ *   styles
+ * @param linkInteractionListener a listener that will be attached to links that are present in the
+ *   string and triggered when user clicks on those links. When set to null, which is a default, the
+ *   system will try to open the corresponding links with the
+ *   [androidx.compose.ui.platform.UriHandler] composition local
+ *
+ * Note that any link style passed directly to this method will be merged with the styles set
+ * directly on a HTML-tagged string. For example, if you set a color of the link via the span
+ * annotation to "red" but also pass a green color via the [linkStyles], the link will be displayed
+ * as green. If, however, you pass a green background via the [linkStyles] instead, the link will be
+ * displayed as red on a green background.
+ *
+ * Example of displaying styled string from resources
+ *
+ * @sample androidx.compose.ui.text.samples.AnnotatedStringFromHtml
+ * @see LinkAnnotation
+ */
+fun AnnotatedString.Companion.fromHtml(
     htmlString: String,
-    linkStyles: TextLinkStyles?,
-    linkInteractionListener: LinkInteractionListener?
+    linkStyles: TextLinkStyles? = null,
+    linkInteractionListener: LinkInteractionListener? = null
 ): AnnotatedString {
     // Check ContentHandlerReplacementTag kdoc for more details
     val stringToParse = "<$ContentHandlerReplacementTag />$htmlString"
diff --git a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/Savers.android.kt b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/Savers.android.kt
new file mode 100644
index 0000000..ed7f45a
--- /dev/null
+++ b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/Savers.android.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.ui.text
+
+import androidx.compose.runtime.saveable.Saver
+import androidx.compose.ui.text.style.LineBreak
+import androidx.compose.ui.text.style.TextMotion
+
+internal actual val PlatformParagraphStyle.Companion.Saver: Saver<PlatformParagraphStyle, Any>
+    get() = PlatformParagraphStyleSaver
+
+private val PlatformParagraphStyleSaver =
+    Saver<PlatformParagraphStyle, Any>(
+        save = { arrayListOf(save(it.includeFontPadding), save(it.emojiSupportMatch)) },
+        restore = {
+            @Suppress("UNCHECKED_CAST") val list = it as List<Any>
+            PlatformParagraphStyle(
+                includeFontPadding = restore(list[0])!!,
+                emojiSupportMatch = restore(list[1])!!
+            )
+        }
+    )
+
+internal actual val LineBreak.Companion.Saver: Saver<LineBreak, Any>
+    get() = LineBreakSaver
+
+private val LineBreakSaver =
+    Saver<LineBreak, Any>(save = { it.mask }, restore = { LineBreak(it as Int) })
+
+internal actual val TextMotion.Companion.Saver: Saver<TextMotion, Any>
+    get() = TextMotionSaver
+
+private val TextMotionSaver =
+    Saver<TextMotion, Any>(
+        save = { arrayListOf(save(it.linearity), save(it.subpixelTextPositioning)) },
+        restore = {
+            @Suppress("UNCHECKED_CAST") val list = it as List<Any>
+            TextMotion(linearity = restore(list[0])!!, subpixelTextPositioning = restore(list[1])!!)
+        }
+    )
diff --git a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/extensions/SpannableExtensions.android.kt b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/extensions/SpannableExtensions.android.kt
index eaa7c1c..b73a903 100644
--- a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/extensions/SpannableExtensions.android.kt
+++ b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/extensions/SpannableExtensions.android.kt
@@ -132,7 +132,8 @@
                     endIndex = endIndex,
                     trimFirstLineTop = lineHeightStyle.trim.isTrimFirstLineTop(),
                     trimLastLineBottom = lineHeightStyle.trim.isTrimLastLineBottom(),
-                    topRatio = lineHeightStyle.alignment.topRatio
+                    topRatio = lineHeightStyle.alignment.topRatio,
+                    preserveMinimumHeight = lineHeightStyle.mode == LineHeightStyle.Mode.Minimum,
                 ),
             start = 0,
             end = length
diff --git a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/style/LineBreak.android.kt b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/style/LineBreak.android.kt
index 89911a1..a2c92ba 100644
--- a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/style/LineBreak.android.kt
+++ b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/style/LineBreak.android.kt
@@ -40,7 +40,7 @@
  */
 @Immutable
 @JvmInline
-actual value class LineBreak private constructor(internal val mask: Int) {
+actual value class LineBreak internal constructor(internal val mask: Int) {
 
     /**
      * This represents a configuration for line breaking on Android, describing [Strategy],
diff --git a/compose/ui/ui-text/src/androidUnitTest/kotlin/androidx/compose/ui/text/AndroidSaversTest.kt b/compose/ui/ui-text/src/androidUnitTest/kotlin/androidx/compose/ui/text/AndroidSaversTest.kt
new file mode 100644
index 0000000..b05d927
--- /dev/null
+++ b/compose/ui/ui-text/src/androidUnitTest/kotlin/androidx/compose/ui/text/AndroidSaversTest.kt
@@ -0,0 +1,490 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.ui.text
+
+import androidx.compose.runtime.saveable.SaverScope
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Shadow
+import androidx.compose.ui.text.font.FontStyle
+import androidx.compose.ui.text.font.FontSynthesis
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.intl.Locale
+import androidx.compose.ui.text.intl.LocaleList
+import androidx.compose.ui.text.style.BaselineShift
+import androidx.compose.ui.text.style.LineHeightStyle
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.text.style.TextDecoration
+import androidx.compose.ui.text.style.TextDirection
+import androidx.compose.ui.text.style.TextGeometricTransform
+import androidx.compose.ui.text.style.TextIndent
+import androidx.compose.ui.unit.TextUnit
+import androidx.compose.ui.unit.em
+import androidx.compose.ui.unit.sp
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+@Suppress("Deprecation")
+class AndroidSaversTest {
+    private val defaultSaverScope = SaverScope { true }
+
+    @Test
+    fun test_TextUnit() {
+        val original = 2.sp
+        val saved = save(original, TextUnit.Saver, defaultSaverScope)
+        val restored: TextUnit? = restore(saved, TextUnit.Saver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_TextUnit_unspecified() {
+        val original = TextUnit.Unspecified
+        val saved = save(original, TextUnit.Saver, defaultSaverScope)
+        val restored: TextUnit? = restore(saved, TextUnit.Saver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_Offset() {
+        val original = Offset(10f, 10f)
+        val saved = save(original, Offset.Saver, defaultSaverScope)
+        val restored: Offset? = restore(saved, Offset.Saver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_Offset_Unspecified() {
+        val original = Offset.Unspecified
+        val saved = save(original, Offset.Saver, defaultSaverScope)
+        val restored: Offset? = restore(saved, Offset.Saver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_Offset_Infinite() {
+        val original = Offset.Infinite
+        val saved = save(original, Offset.Saver, defaultSaverScope)
+        val restored: Offset? = restore(saved, Offset.Saver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_Color() {
+        val original = Color.Yellow
+        val saved = save(original, Color.Saver, defaultSaverScope)
+        val restored: Color? = restore(saved, Color.Saver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_Color_Unspecified() {
+        val original = Color.Unspecified
+        val saved = save(original, Color.Saver, defaultSaverScope)
+        val restored: Color? = restore(saved, Color.Saver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_Shadow() {
+        val original = Shadow(color = Color.Blue, offset = Offset(5f, 5f), blurRadius = 2f)
+        val saved = save(original, Shadow.Saver, defaultSaverScope)
+        val restored: Shadow? = restore(saved, Shadow.Saver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_Shadow_None() {
+        val original = Shadow.None
+        val saved = save(original, Shadow.Saver, defaultSaverScope)
+        val restored: Shadow? = restore(saved, Shadow.Saver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_ParagraphStyle() {
+        val original = ParagraphStyle()
+        val saved = save(original, ParagraphStyleSaver, defaultSaverScope)
+        val restored: ParagraphStyle? = restore(saved, ParagraphStyleSaver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_ParagraphStyle_with_a_nonnull_value() {
+        val original = ParagraphStyle(textDirection = TextDirection.Rtl)
+        val saved = save(original, ParagraphStyleSaver, defaultSaverScope)
+        val restored: ParagraphStyle? = restore(saved, ParagraphStyleSaver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_SpanStyle() {
+        val original = SpanStyle()
+        val saved = save(original, SpanStyleSaver, defaultSaverScope)
+        val restored: SpanStyle? = restore(saved, SpanStyleSaver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_SpanStyle_with_a_nonnull_value() {
+        val original = SpanStyle(baselineShift = BaselineShift.Subscript)
+        val saved = save(original, SpanStyleSaver, defaultSaverScope)
+        val restored: SpanStyle? = restore(saved, SpanStyleSaver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_SpanStyle_with_no_null_value() {
+        val original =
+            SpanStyle(
+                color = Color.Red,
+                fontSize = 10.sp,
+                fontWeight = FontWeight.Bold,
+                fontStyle = FontStyle.Italic,
+                fontSynthesis = FontSynthesis.All,
+                // fontFamily =
+                fontFeatureSettings = "feature settings",
+                letterSpacing = 2.em,
+                baselineShift = BaselineShift.Superscript,
+                textGeometricTransform = TextGeometricTransform(2f, 3f),
+                localeList = LocaleList(Locale("sr-Latn-SR"), Locale("sr-Cyrl-SR"), Locale.current),
+                background = Color.Blue,
+                textDecoration = TextDecoration.LineThrough,
+                shadow = Shadow(color = Color.Red, offset = Offset(2f, 2f), blurRadius = 4f)
+            )
+        val saved = save(original, SpanStyleSaver, defaultSaverScope)
+        val restored: SpanStyle? = restore(saved, SpanStyleSaver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_TextLinkStyles() {
+        val original = TextLinkStyles(null)
+        val saved = save(original, TextLinkStylesSaver, defaultSaverScope)
+        val restored: TextLinkStyles? = restore(saved, TextLinkStylesSaver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_TextLinkStyles_withNonNullValues() {
+        val original =
+            TextLinkStyles(
+                SpanStyle(color = Color.Red),
+                SpanStyle(color = Color.Green),
+                SpanStyle(color = Color.Blue),
+                SpanStyle(color = Color.Gray)
+            )
+        val saved = save(original, TextLinkStylesSaver, defaultSaverScope)
+        val restored: TextLinkStyles? = restore(saved, TextLinkStylesSaver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_FontWeight() {
+        val original = FontWeight(123)
+        val saved = save(original, FontWeight.Saver, defaultSaverScope)
+        val restored: FontWeight? = restore(saved, FontWeight.Saver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_FontWeight_w100() {
+        val original = FontWeight.W100
+        val saved = save(original, FontWeight.Saver, defaultSaverScope)
+        val restored: FontWeight? = restore(saved, FontWeight.Saver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_BaselineShift() {
+        val original = BaselineShift(2f)
+        val saved = save(original, BaselineShift.Saver, defaultSaverScope)
+        val restored: BaselineShift? = restore(saved, BaselineShift.Saver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_BaselineShift_None() {
+        val original = BaselineShift.None
+        val saved = save(original, BaselineShift.Saver, defaultSaverScope)
+        val restored: BaselineShift? = restore(saved, BaselineShift.Saver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_TextDecoration() {
+        val original =
+            TextDecoration.combine(listOf(TextDecoration.LineThrough, TextDecoration.Underline))
+        val saved = save(original, TextDecoration.Saver, defaultSaverScope)
+        val restored: TextDecoration? = restore(saved, TextDecoration.Saver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_TextDecoration_None() {
+        val original = TextDecoration.None
+        val saved = save(original, TextDecoration.Saver, defaultSaverScope)
+        val restored: TextDecoration? = restore(saved, TextDecoration.Saver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun testSaveRestore_lineThrough() {
+        val original = TextDecoration.LineThrough
+        val saved = save(original, TextDecoration.Saver, defaultSaverScope)
+        val restored: TextDecoration? = restore(saved, TextDecoration.Saver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun testSaveRestore_underline() {
+        val original = TextDecoration.Underline
+        val saved = save(original, TextDecoration.Saver, defaultSaverScope)
+        val restored: TextDecoration? = restore(saved, TextDecoration.Saver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_TextGeometricTransform() {
+        val original = TextGeometricTransform(1f, 2f)
+        val saved = save(original, TextGeometricTransform.Saver, defaultSaverScope)
+        val restored: TextGeometricTransform? = restore(saved, TextGeometricTransform.Saver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_TextGeometricTransform_None() {
+        val original = TextGeometricTransform.None
+        val saved = save(original, TextGeometricTransform.Saver, defaultSaverScope)
+        val restored: TextGeometricTransform? = restore(saved, TextGeometricTransform.Saver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_TextIndent() {
+        val original = TextIndent(1.sp, 2.sp)
+        val saved = save(original, TextIndent.Saver, defaultSaverScope)
+        val restored: TextIndent? = restore(saved, TextIndent.Saver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_TextIndent_None() {
+        val original = TextIndent.None
+        val saved = save(original, TextIndent.Saver, defaultSaverScope)
+        val restored: TextIndent? = restore(saved, TextIndent.Saver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_AnnotatedString() {
+        val original = AnnotatedString("abc")
+        val saved = with(AnnotatedStringSaver) { defaultSaverScope.save(original) }
+
+        assertThat(AnnotatedStringSaver.restore(saved!!)).isEqualTo(original)
+    }
+
+    @Test
+    fun test_AnnotatedString_withSpanStyles() {
+        val original = buildAnnotatedString {
+            withStyle(SpanStyle(color = Color.Red)) { append("1") }
+            withStyle(SpanStyle(fontStyle = FontStyle.Italic)) { append("2") }
+        }
+
+        val saved = with(AnnotatedStringSaver) { defaultSaverScope.save(original) }
+
+        val restored: AnnotatedString = AnnotatedStringSaver.restore(saved!!)!!
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_AnnotatedString_withParagraphStyles() {
+        val original = buildAnnotatedString {
+            withStyle(ParagraphStyle(textAlign = TextAlign.Justify)) { append("1") }
+            withStyle(ParagraphStyle(textDirection = TextDirection.Rtl)) { append("2") }
+        }
+
+        val saved = with(AnnotatedStringSaver) { defaultSaverScope.save(original) }
+
+        val restored: AnnotatedString = AnnotatedStringSaver.restore(saved!!)!!
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @OptIn(ExperimentalTextApi::class)
+    @Test
+    fun test_AnnotatedString_withAnnotations() {
+        val original = buildAnnotatedString {
+            withAnnotation(tag = "Tag1", annotation = "Annotation1") { append("1") }
+            withAnnotation(VerbatimTtsAnnotation("verbatim1")) { append("2") }
+            withAnnotation(tag = "Tag2", annotation = "Annotation2") { append("3") }
+            withAnnotation(VerbatimTtsAnnotation("verbatim2")) { append("4") }
+            withAnnotation(UrlAnnotation("url1")) { append("5") }
+            withAnnotation(UrlAnnotation("url2")) { append("6") }
+            withLink(
+                LinkAnnotation.Url(
+                    "url3",
+                    TextLinkStyles(
+                        SpanStyle(color = Color.Red),
+                        SpanStyle(color = Color.Green),
+                        SpanStyle(color = Color.Blue),
+                        SpanStyle(color = Color.White)
+                    )
+                )
+            ) {
+                append("7")
+            }
+            withLink(
+                LinkAnnotation.Clickable(
+                    "tag3",
+                    TextLinkStyles(
+                        SpanStyle(color = Color.Red),
+                        SpanStyle(color = Color.Green),
+                        SpanStyle(color = Color.Blue),
+                        SpanStyle(background = Color.Gray)
+                    ),
+                    null
+                )
+            ) {
+                append("8")
+            }
+        }
+
+        val saved = with(AnnotatedStringSaver) { defaultSaverScope.save(original) }
+
+        val restored: AnnotatedString = AnnotatedStringSaver.restore(saved!!)!!
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @OptIn(ExperimentalTextApi::class)
+    @Test
+    fun test_AnnotatedString_withSpanAndParagraphStylesAndAnnotations() {
+        val original = buildAnnotatedString {
+            withStyle(ParagraphStyle(textAlign = TextAlign.Justify)) { append("1") }
+            withStyle(ParagraphStyle(textDirection = TextDirection.Rtl)) { append("2") }
+            withStyle(SpanStyle(color = Color.Red)) { append("3") }
+            withStyle(SpanStyle(fontStyle = FontStyle.Italic)) { append("4") }
+            withAnnotation(tag = "Tag1", annotation = "Annotation1") { append("5") }
+            withAnnotation(VerbatimTtsAnnotation("verbatim1")) { append("6") }
+            withAnnotation(tag = "Tag2", annotation = "Annotation2") { append("7") }
+            withAnnotation(VerbatimTtsAnnotation("verbatim2")) { append("8") }
+            withAnnotation(UrlAnnotation("url1")) { append("9") }
+            withAnnotation(UrlAnnotation("url2")) { append("10") }
+            withLink(
+                LinkAnnotation.Url(
+                    "url3",
+                    TextLinkStyles(
+                        SpanStyle(color = Color.Red),
+                        SpanStyle(color = Color.Green),
+                        SpanStyle(color = Color.Blue),
+                        SpanStyle(color = Color.Yellow)
+                    )
+                )
+            ) {
+                append("11")
+            }
+            withLink(
+                LinkAnnotation.Clickable(
+                    "tag3",
+                    TextLinkStyles(
+                        SpanStyle(color = Color.Red),
+                        SpanStyle(color = Color.Green),
+                        SpanStyle(color = Color.Blue),
+                        SpanStyle(color = Color.Gray)
+                    ),
+                    null
+                )
+            ) {
+                append("12")
+            }
+        }
+
+        val saved = with(AnnotatedStringSaver) { defaultSaverScope.save(original) }
+
+        val restored: AnnotatedString = AnnotatedStringSaver.restore(saved!!)!!
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_Locale() {
+        val original = Locale("sr-Latn-SR")
+        val saved = with(Locale.Saver) { defaultSaverScope.save(original) }
+
+        assertThat(Locale.Saver.restore(saved!!)).isEqualTo(original)
+    }
+
+    @Test
+    fun test_LocaleList() {
+        val original = LocaleList(Locale("sr-Latn-SR"), Locale("sr-Cyrl-SR"), Locale.current)
+        val saved = with(LocaleList.Saver) { defaultSaverScope.save(original) }
+
+        assertThat(LocaleList.Saver.restore(saved!!)).isEqualTo(original)
+    }
+
+    @Test
+    fun test_LineHeightStyle() {
+        val original =
+            LineHeightStyle(
+                LineHeightStyle.Alignment.Proportional,
+                LineHeightStyle.Trim.Both,
+                LineHeightStyle.Mode.Minimum
+            )
+        val saved = save(original, LineHeightStyle.Saver, defaultSaverScope)
+        val restored: LineHeightStyle? = restore(saved, LineHeightStyle.Saver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_PlatformParagraphStyle_with_no_null_args() {
+        val original = PlatformParagraphStyle(EmojiSupportMatch.All, true)
+        val saved = save(original, PlatformParagraphStyle.Saver, defaultSaverScope)
+        val restored: PlatformParagraphStyle? = restore(saved, PlatformParagraphStyle.Saver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+}
diff --git a/compose/ui/ui-text/src/androidUnitTest/kotlin/androidx/compose/ui/text/AnnotatedStringBuilderTest.kt b/compose/ui/ui-text/src/androidUnitTest/kotlin/androidx/compose/ui/text/AnnotatedStringBuilderTest.kt
index 96220ed..222cadd 100644
--- a/compose/ui/ui-text/src/androidUnitTest/kotlin/androidx/compose/ui/text/AnnotatedStringBuilderTest.kt
+++ b/compose/ui/ui-text/src/androidUnitTest/kotlin/androidx/compose/ui/text/AnnotatedStringBuilderTest.kt
@@ -178,14 +178,17 @@
         val annotatedString =
             AnnotatedString(
                 text = text,
-                spanStylesOrNull =
-                    listOf(text.inclusiveRangeOf('a', 'a', item = SpanStyle(color = Color.Red))),
-                paragraphStylesOrNull =
-                    listOf(
-                        text.inclusiveRangeOf('a', 'a', item = ParagraphStyle(lineHeight = 20.sp))
-                    ),
                 annotations =
-                    listOf(text.inclusiveRangeOf('a', 'a', item = "prefix", tag = "prefixTag"))
+                    listOf(
+                        text.inclusiveRangeOf('a', 'a', item = SpanStyle(color = Color.Red)),
+                        text.inclusiveRangeOf('a', 'a', item = ParagraphStyle(lineHeight = 20.sp)),
+                        text.inclusiveRangeOf(
+                            'a',
+                            'a',
+                            item = StringAnnotation("prefix"),
+                            tag = "prefixTag"
+                        ),
+                    ),
             )
 
         // We want to test the cross product of the following cases:
@@ -211,17 +214,15 @@
             )
         val appendedAnnotations =
             listOf(
-                appendedText.inclusiveRangeOf('b', 'f', item = 1, tag = "tag1"),
-                appendedText.inclusiveRangeOf('c', 'f', item = 2, tag = "tag2"),
-                appendedText.inclusiveRangeOf('b', 'e', item = 3, tag = "tag3"),
-                appendedText.inclusiveRangeOf('c', 'e', item = 4, tag = "tag4"),
+                appendedText.inclusiveRangeOf('b', 'f', item = 1.toAnnotation(), tag = "tag1"),
+                appendedText.inclusiveRangeOf('c', 'f', item = 2.toAnnotation(), tag = "tag2"),
+                appendedText.inclusiveRangeOf('b', 'e', item = 3.toAnnotation(), tag = "tag3"),
+                appendedText.inclusiveRangeOf('c', 'e', item = 4.toAnnotation(), tag = "tag4"),
             )
         val appendedAnnotatedString =
             AnnotatedString(
                 text = appendedText,
-                spanStylesOrNull = appendedSpanStyles,
-                paragraphStylesOrNull = appendedParagraphStyles,
-                annotations = appendedAnnotations
+                annotations = appendedSpanStyles + appendedParagraphStyles + appendedAnnotations,
             )
 
         val buildResult =
@@ -267,19 +268,29 @@
                     item = ParagraphStyle(lineHeight = 60.sp)
                 ),
             )
-        val expectedAnnotations =
+        val expectedStringAnnotations =
             listOf(
-                expectedString.inclusiveRangeOf('a', 'a', item = "prefix", tag = "prefixTag"),
-                expectedString.inclusiveRangeOf('c', 'e', item = 1, tag = "tag1"),
-                expectedString.inclusiveRangeOf('c', 'e', item = 2, tag = "tag2"),
-                expectedString.inclusiveRangeOf('c', 'e', item = 3, tag = "tag3"),
-                expectedString.inclusiveRangeOf('c', 'e', item = 4, tag = "tag4"),
+                expectedString.inclusiveRangeOf(
+                    'a',
+                    'a',
+                    item = "prefix".toAnnotation(),
+                    tag = "prefixTag"
+                ),
+                expectedString.inclusiveRangeOf('c', 'e', item = 1.toAnnotation(), tag = "tag1"),
+                expectedString.inclusiveRangeOf('c', 'e', item = 2.toAnnotation(), tag = "tag2"),
+                expectedString.inclusiveRangeOf('c', 'e', item = 3.toAnnotation(), tag = "tag3"),
+                expectedString.inclusiveRangeOf('c', 'e', item = 4.toAnnotation(), tag = "tag4"),
             )
 
         assertThat(buildResult.text).isEqualTo(expectedString)
         assertThat(buildResult.spanStyles).isEqualTo(expectedSpanStyles)
         assertThat(buildResult.paragraphStyles).isEqualTo(expectedParagraphStyles)
-        assertThat(buildResult.annotations).isEqualTo(expectedAnnotations)
+        assertThat(
+                buildResult.annotations?.filter {
+                    it.item !is SpanStyle && it.item !is ParagraphStyle
+                }
+            )
+            .isEqualTo(expectedStringAnnotations)
     }
 
     @Test
@@ -415,11 +426,23 @@
                 )
             )
 
-        val expectedAnnotations =
+        val expectedAllAnnotations =
             listOf(
+                Range(item = SpanStyle(color), start = 0, end = text.length),
+                Range(item = ParagraphStyle(lineHeight = lineHeight), start = 0, end = text.length),
+                Range(
+                    item = SpanStyle(appendedColor),
+                    start = text.length,
+                    end = expectedString.length
+                ),
+                Range(
+                    item = ParagraphStyle(lineHeight = appendedLineHeight),
+                    start = text.length,
+                    end = expectedString.length
+                ),
                 Range(
                     tag = appendedAnnotationTag,
-                    item = appendedAnnotation,
+                    item = appendedAnnotation.toAnnotation(),
                     start = expectedString.indexOf('d'),
                     end = expectedString.indexOf('e') + 1
                 )
@@ -428,7 +451,7 @@
         assertThat(buildResult.text).isEqualTo(expectedString)
         assertThat(buildResult.spanStyles).isEqualTo(expectedSpanStyles)
         assertThat(buildResult.paragraphStyles).isEqualTo(expectedParagraphStyles)
-        assertThat(buildResult.annotations).isEqualTo(expectedAnnotations)
+        assertThat(buildResult.annotations).isEqualTo(expectedAllAnnotations)
     }
 
     @Test
@@ -1206,6 +1229,14 @@
     }
 
     /** Returns a [Range] from the index of [start] to the index of [end], both inclusive. */
-    private fun <T> String.inclusiveRangeOf(start: Char, end: Char, item: T, tag: String = "") =
-        Range(tag = tag, item = item, start = indexOf(start), end = indexOf(end) + 1)
+    private fun <T : AnnotatedString.Annotation> String.inclusiveRangeOf(
+        start: Char,
+        end: Char,
+        item: T,
+        tag: String = ""
+    ) = Range(tag = tag, item = item, start = indexOf(start), end = indexOf(end) + 1)
+
+    private fun Int.toAnnotation() = StringAnnotation(this.toString())
+
+    private fun String.toAnnotation() = StringAnnotation(this)
 }
diff --git a/compose/ui/ui-text/src/androidUnitTest/kotlin/androidx/compose/ui/text/AnnotatedStringTest.kt b/compose/ui/ui-text/src/androidUnitTest/kotlin/androidx/compose/ui/text/AnnotatedStringTest.kt
index 055d204b..c356b99 100644
--- a/compose/ui/ui-text/src/androidUnitTest/kotlin/androidx/compose/ui/text/AnnotatedStringTest.kt
+++ b/compose/ui/ui-text/src/androidUnitTest/kotlin/androidx/compose/ui/text/AnnotatedStringTest.kt
@@ -100,25 +100,16 @@
     @Test
     fun plus_operator_creates_a_new_annotated_string() {
         val text1 = "Hello"
-        val spanStyles1 =
+        val annotations1 =
             listOf(
                 Range(SpanStyle(color = Color.Red), 0, 3),
-                Range(SpanStyle(color = Color.Blue), 2, 4)
-            )
-        val paragraphStyles1 =
-            listOf(
+                Range(SpanStyle(color = Color.Blue), 2, 4),
                 Range(ParagraphStyle(lineHeight = 20.sp), 0, 1),
-                Range(ParagraphStyle(lineHeight = 30.sp), 1, 5)
+                Range(ParagraphStyle(lineHeight = 30.sp), 1, 5),
+                Range(StringAnnotation("annotation1"), 0, 2, "scope1"),
+                Range(StringAnnotation("annotation1"), 3, 5, "scope1")
             )
-        val annotations1 =
-            listOf(Range("annotation1", 0, 2, "scope1"), Range("annotation1", 3, 5, "scope1"))
-        val annotatedString1 =
-            AnnotatedString(
-                text = text1,
-                spanStylesOrNull = spanStyles1,
-                paragraphStylesOrNull = paragraphStyles1,
-                annotations = annotations1
-            )
+        val annotatedString1 = AnnotatedString(text = text1, annotations = annotations1)
 
         val text2 = "World"
         val spanStyle = SpanStyle(color = Color.Cyan)
@@ -126,23 +117,24 @@
         val annotatedString2 =
             AnnotatedString(
                 text = text2,
-                spanStylesOrNull = listOf(Range(spanStyle, 0, text2.length)),
-                paragraphStylesOrNull = listOf(Range(paragraphStyle, 0, text2.length)),
-                annotations = listOf(Range("annotation2", 0, text2.length, "scope2"))
+                annotations =
+                    listOf(
+                        Range(spanStyle, 0, text2.length),
+                        Range(paragraphStyle, 0, text2.length),
+                        Range(StringAnnotation("annotation2"), 0, text2.length, "scope2")
+                    ),
             )
 
         assertThat(annotatedString1 + annotatedString2)
             .isEqualTo(
                 AnnotatedString(
                     "$text1$text2",
-                    spanStyles1 +
-                        listOf(Range(spanStyle, text1.length, text1.length + text2.length)),
-                    paragraphStyles1 +
-                        listOf(Range(paragraphStyle, text1.length, text1.length + text2.length)),
                     annotations1 +
                         listOf(
+                            Range(spanStyle, text1.length, text1.length + text2.length),
+                            Range(paragraphStyle, text1.length, text1.length + text2.length),
                             Range(
-                                "annotation2",
+                                StringAnnotation("annotation2"),
                                 text1.length,
                                 text1.length + text2.length,
                                 "scope2"
@@ -150,6 +142,23 @@
                         )
                 )
             )
+
+        assertThat((annotatedString1 + annotatedString2).spanStyles)
+            .isEqualTo(
+                listOf(
+                    Range(SpanStyle(color = Color.Red), 0, 3),
+                    Range(SpanStyle(color = Color.Blue), 2, 4),
+                    Range(spanStyle, text1.length, text1.length + text2.length),
+                )
+            )
+        assertThat((annotatedString1 + annotatedString2).paragraphStyles)
+            .isEqualTo(
+                listOf(
+                    Range(ParagraphStyle(lineHeight = 20.sp), 0, 1),
+                    Range(ParagraphStyle(lineHeight = 30.sp), 1, 5),
+                    Range(paragraphStyle, text1.length, text1.length + text2.length),
+                )
+            )
     }
 
     @Test
@@ -326,13 +335,19 @@
         // Collapsed range equals to start, has annotation
         assertThat(annotatedString.subSequence(2, 2))
             .isEqualTo(
-                AnnotatedString("", annotations = listOf(Range("annotation1", 0, 0, "scope1")))
+                AnnotatedString(
+                    "",
+                    annotations = listOf(Range(StringAnnotation("annotation1"), 0, 0, "scope1"))
+                )
             )
 
         // Collapsed range covered by annotation, has annotation
         assertThat(annotatedString.subSequence(3, 3))
             .isEqualTo(
-                AnnotatedString("", annotations = listOf(Range("annotation1", 0, 0, "scope1")))
+                AnnotatedString(
+                    "",
+                    annotations = listOf(Range(StringAnnotation("annotation1"), 0, 0, "scope1"))
+                )
             )
     }
 
@@ -348,13 +363,19 @@
         // Overlapping range, has annotation
         assertThat(annotatedString.subSequence(0, 3))
             .isEqualTo(
-                AnnotatedString("abc", annotations = listOf(Range("annotation1", 2, 3, "scope1")))
+                AnnotatedString(
+                    "abc",
+                    annotations = listOf(Range(StringAnnotation("annotation1"), 2, 3, "scope1"))
+                )
             )
 
         // Overlapping, has annotation
         assertThat(annotatedString.subSequence(3, 5))
             .isEqualTo(
-                AnnotatedString("de", annotations = listOf(Range("annotation1", 0, 1, "scope1")))
+                AnnotatedString(
+                    "de",
+                    annotations = listOf(Range(StringAnnotation("annotation1"), 0, 1, "scope1"))
+                )
             )
     }
 
@@ -371,13 +392,19 @@
         // Contains range, has annotation
         assertThat(annotatedString.subSequence(0, 5))
             .isEqualTo(
-                AnnotatedString("abcde", annotations = listOf(Range("annotation1", 2, 4, "scope1")))
+                AnnotatedString(
+                    "abcde",
+                    annotations = listOf(Range(StringAnnotation("annotation1"), 2, 4, "scope1"))
+                )
             )
 
         // Full range, has annotation
         assertThat(annotatedString.subSequence(2, 4))
             .isEqualTo(
-                AnnotatedString("cd", annotations = listOf(Range("annotation1", 0, 2, "scope1")))
+                AnnotatedString(
+                    "cd",
+                    annotations = listOf(Range(StringAnnotation("annotation1"), 0, 2, "scope1"))
+                )
             )
     }
 
diff --git a/compose/ui/ui-text/src/androidUnitTest/kotlin/androidx/compose/ui/text/LinkAnnotationTest.kt b/compose/ui/ui-text/src/androidUnitTest/kotlin/androidx/compose/ui/text/LinkAnnotationTest.kt
new file mode 100644
index 0000000..1eefca8
--- /dev/null
+++ b/compose/ui/ui-text/src/androidUnitTest/kotlin/androidx/compose/ui/text/LinkAnnotationTest.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.ui.text
+
+import androidx.compose.ui.graphics.Color
+import com.google.common.truth.Truth.assertThat
+import kotlin.test.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class LinkAnnotationTest {
+    @Test
+    fun copy_keepAll_linkAnnotation_url() {
+        val original = LinkAnnotation.Url("url1", TextLinkStyles(), null)
+        val actual = original.copy()
+
+        assertThat(actual).isEqualTo(original)
+    }
+
+    @Test
+    fun copy_changeAll_linkAnnotation_url() {
+        val original = LinkAnnotation.Url("url1", TextLinkStyles(), null)
+        val actual = original.copy(url = "url2", TextLinkStyles(SpanStyle(Color.Green))) {}
+
+        assertThat(actual.url).isEqualTo("url2")
+        assertThat(actual.styles).isEqualTo(TextLinkStyles(SpanStyle(Color.Green)))
+        assertThat(actual.linkInteractionListener).isNotNull()
+    }
+
+    @Test
+    fun copy_keepAll_linkAnnotation_clickable() {
+        val original = LinkAnnotation.Clickable("tag", TextLinkStyles()) {}
+        val actual = original.copy()
+
+        assertThat(actual).isEqualTo(original)
+    }
+
+    @Test
+    fun copy_changeAll_linkAnnotation_clickable() {
+        val original = LinkAnnotation.Clickable("tag", TextLinkStyles()) {}
+        val actual = original.copy("tag1", TextLinkStyles(SpanStyle(Color.Green)), null)
+
+        assertThat(actual.tag).isEqualTo("tag1")
+        assertThat(actual.styles).isEqualTo(TextLinkStyles(SpanStyle(Color.Green)))
+        assertThat(actual.linkInteractionListener).isNull()
+    }
+}
diff --git a/compose/ui/ui-text/src/androidUnitTest/kotlin/androidx/compose/ui/text/SaversTest.kt b/compose/ui/ui-text/src/androidUnitTest/kotlin/androidx/compose/ui/text/SaversTest.kt
deleted file mode 100644
index 65599eb..0000000
--- a/compose/ui/ui-text/src/androidUnitTest/kotlin/androidx/compose/ui/text/SaversTest.kt
+++ /dev/null
@@ -1,481 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.text
-
-import androidx.compose.runtime.saveable.SaverScope
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.Shadow
-import androidx.compose.ui.text.font.FontStyle
-import androidx.compose.ui.text.font.FontSynthesis
-import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.text.intl.Locale
-import androidx.compose.ui.text.intl.LocaleList
-import androidx.compose.ui.text.style.BaselineShift
-import androidx.compose.ui.text.style.TextAlign
-import androidx.compose.ui.text.style.TextDecoration
-import androidx.compose.ui.text.style.TextDirection
-import androidx.compose.ui.text.style.TextGeometricTransform
-import androidx.compose.ui.text.style.TextIndent
-import androidx.compose.ui.unit.TextUnit
-import androidx.compose.ui.unit.em
-import androidx.compose.ui.unit.sp
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-@Suppress("Deprecation")
-class SaversTest {
-    private val defaultSaverScope = SaverScope { true }
-
-    @Test
-    fun test_TextUnit() {
-        val original = 2.sp
-        val saved = save(original, TextUnit.Saver, defaultSaverScope)
-        val restored: TextUnit? = restore(saved, TextUnit.Saver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_TextUnit_unspecified() {
-        val original = TextUnit.Unspecified
-        val saved = save(original, TextUnit.Saver, defaultSaverScope)
-        val restored: TextUnit? = restore(saved, TextUnit.Saver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_Offset() {
-        val original = Offset(10f, 10f)
-        val saved = save(original, Offset.Saver, defaultSaverScope)
-        val restored: Offset? = restore(saved, Offset.Saver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_Offset_Unspecified() {
-        val original = Offset.Unspecified
-        val saved = save(original, Offset.Saver, defaultSaverScope)
-        val restored: Offset? = restore(saved, Offset.Saver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_Offset_Infinite() {
-        val original = Offset.Infinite
-        val saved = save(original, Offset.Saver, defaultSaverScope)
-        val restored: Offset? = restore(saved, Offset.Saver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_Color() {
-        val original = Color.Yellow
-        val saved = save(original, Color.Saver, defaultSaverScope)
-        val restored: Color? = restore(saved, Color.Saver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_Color_Unspecified() {
-        val original = Color.Unspecified
-        val saved = save(original, Color.Saver, defaultSaverScope)
-        val restored: Color? = restore(saved, Color.Saver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_Shadow() {
-        val original = Shadow(color = Color.Blue, offset = Offset(5f, 5f), blurRadius = 2f)
-        val saved = save(original, Shadow.Saver, defaultSaverScope)
-        val restored: Shadow? = restore(saved, Shadow.Saver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_Shadow_None() {
-        val original = Shadow.None
-        val saved = save(original, Shadow.Saver, defaultSaverScope)
-        val restored: Shadow? = restore(saved, Shadow.Saver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_ParagraphStyle() {
-        val original = ParagraphStyle()
-        val saved = save(original, ParagraphStyleSaver, defaultSaverScope)
-        val restored: ParagraphStyle? = restore(saved, ParagraphStyleSaver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_ParagraphStyle_with_a_nonnull_value() {
-        val original = ParagraphStyle(textDirection = TextDirection.Rtl)
-        val saved = save(original, ParagraphStyleSaver, defaultSaverScope)
-        val restored: ParagraphStyle? = restore(saved, ParagraphStyleSaver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_ParagraphStyle_with_no_null_value() {
-        val original =
-            ParagraphStyle(
-                textAlign = TextAlign.Justify,
-                textDirection = TextDirection.Rtl,
-                lineHeight = 10.sp,
-                textIndent = TextIndent(firstLine = 2.sp, restLine = 3.sp)
-            )
-        val saved = save(original, ParagraphStyleSaver, defaultSaverScope)
-        val restored: ParagraphStyle? = restore(saved, ParagraphStyleSaver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_SpanStyle() {
-        val original = SpanStyle()
-        val saved = save(original, SpanStyleSaver, defaultSaverScope)
-        val restored: SpanStyle? = restore(saved, SpanStyleSaver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_SpanStyle_with_a_nonnull_value() {
-        val original = SpanStyle(baselineShift = BaselineShift.Subscript)
-        val saved = save(original, SpanStyleSaver, defaultSaverScope)
-        val restored: SpanStyle? = restore(saved, SpanStyleSaver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_SpanStyle_with_no_null_value() {
-        val original =
-            SpanStyle(
-                color = Color.Red,
-                fontSize = 10.sp,
-                fontWeight = FontWeight.Bold,
-                fontStyle = FontStyle.Italic,
-                fontSynthesis = FontSynthesis.All,
-                // fontFamily =
-                fontFeatureSettings = "feature settings",
-                letterSpacing = 2.em,
-                baselineShift = BaselineShift.Superscript,
-                textGeometricTransform = TextGeometricTransform(2f, 3f),
-                localeList = LocaleList(Locale("sr-Latn-SR"), Locale("sr-Cyrl-SR"), Locale.current),
-                background = Color.Blue,
-                textDecoration = TextDecoration.LineThrough,
-                shadow = Shadow(color = Color.Red, offset = Offset(2f, 2f), blurRadius = 4f)
-            )
-        val saved = save(original, SpanStyleSaver, defaultSaverScope)
-        val restored: SpanStyle? = restore(saved, SpanStyleSaver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_TextLinkStyles() {
-        val original = TextLinkStyles(null)
-        val saved = save(original, TextLinkStylesSaver, defaultSaverScope)
-        val restored: TextLinkStyles? = restore(saved, TextLinkStylesSaver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_TextLinkStyles_withNonNullValues() {
-        val original =
-            TextLinkStyles(
-                SpanStyle(color = Color.Red),
-                SpanStyle(color = Color.Green),
-                SpanStyle(color = Color.Blue),
-                SpanStyle(color = Color.Gray)
-            )
-        val saved = save(original, TextLinkStylesSaver, defaultSaverScope)
-        val restored: TextLinkStyles? = restore(saved, TextLinkStylesSaver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_FontWeight() {
-        val original = FontWeight(123)
-        val saved = save(original, FontWeight.Saver, defaultSaverScope)
-        val restored: FontWeight? = restore(saved, FontWeight.Saver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_FontWeight_w100() {
-        val original = FontWeight.W100
-        val saved = save(original, FontWeight.Saver, defaultSaverScope)
-        val restored: FontWeight? = restore(saved, FontWeight.Saver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_BaselineShift() {
-        val original = BaselineShift(2f)
-        val saved = save(original, BaselineShift.Saver, defaultSaverScope)
-        val restored: BaselineShift? = restore(saved, BaselineShift.Saver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_BaselineShift_None() {
-        val original = BaselineShift.None
-        val saved = save(original, BaselineShift.Saver, defaultSaverScope)
-        val restored: BaselineShift? = restore(saved, BaselineShift.Saver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_TextDecoration() {
-        val original =
-            TextDecoration.combine(listOf(TextDecoration.LineThrough, TextDecoration.Underline))
-        val saved = save(original, TextDecoration.Saver, defaultSaverScope)
-        val restored: TextDecoration? = restore(saved, TextDecoration.Saver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_TextDecoration_None() {
-        val original = TextDecoration.None
-        val saved = save(original, TextDecoration.Saver, defaultSaverScope)
-        val restored: TextDecoration? = restore(saved, TextDecoration.Saver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun testSaveRestore_lineThrough() {
-        val original = TextDecoration.LineThrough
-        val saved = save(original, TextDecoration.Saver, defaultSaverScope)
-        val restored: TextDecoration? = restore(saved, TextDecoration.Saver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun testSaveRestore_underline() {
-        val original = TextDecoration.Underline
-        val saved = save(original, TextDecoration.Saver, defaultSaverScope)
-        val restored: TextDecoration? = restore(saved, TextDecoration.Saver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_TextGeometricTransform() {
-        val original = TextGeometricTransform(1f, 2f)
-        val saved = save(original, TextGeometricTransform.Saver, defaultSaverScope)
-        val restored: TextGeometricTransform? = restore(saved, TextGeometricTransform.Saver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_TextGeometricTransform_None() {
-        val original = TextGeometricTransform.None
-        val saved = save(original, TextGeometricTransform.Saver, defaultSaverScope)
-        val restored: TextGeometricTransform? = restore(saved, TextGeometricTransform.Saver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_TextIndent() {
-        val original = TextIndent(1.sp, 2.sp)
-        val saved = save(original, TextIndent.Saver, defaultSaverScope)
-        val restored: TextIndent? = restore(saved, TextIndent.Saver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_TextIndent_None() {
-        val original = TextIndent.None
-        val saved = save(original, TextIndent.Saver, defaultSaverScope)
-        val restored: TextIndent? = restore(saved, TextIndent.Saver)
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_AnnotatedString() {
-        val original = AnnotatedString("abc")
-        val saved = with(AnnotatedStringSaver) { defaultSaverScope.save(original) }
-
-        assertThat(AnnotatedStringSaver.restore(saved!!)).isEqualTo(original)
-    }
-
-    @Test
-    fun test_AnnotatedString_withSpanStyles() {
-        val original = buildAnnotatedString {
-            withStyle(SpanStyle(color = Color.Red)) { append("1") }
-            withStyle(SpanStyle(fontStyle = FontStyle.Italic)) { append("2") }
-        }
-
-        val saved = with(AnnotatedStringSaver) { defaultSaverScope.save(original) }
-
-        val restored: AnnotatedString = AnnotatedStringSaver.restore(saved!!)!!
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_AnnotatedString_withParagraphStyles() {
-        val original = buildAnnotatedString {
-            withStyle(ParagraphStyle(textAlign = TextAlign.Justify)) { append("1") }
-            withStyle(ParagraphStyle(textDirection = TextDirection.Rtl)) { append("2") }
-        }
-
-        val saved = with(AnnotatedStringSaver) { defaultSaverScope.save(original) }
-
-        val restored: AnnotatedString = AnnotatedStringSaver.restore(saved!!)!!
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @OptIn(ExperimentalTextApi::class)
-    @Test
-    fun test_AnnotatedString_withAnnotations() {
-        val original = buildAnnotatedString {
-            withAnnotation(tag = "Tag1", annotation = "Annotation1") { append("1") }
-            withAnnotation(VerbatimTtsAnnotation("verbatim1")) { append("2") }
-            withAnnotation(tag = "Tag2", annotation = "Annotation2") { append("3") }
-            withAnnotation(VerbatimTtsAnnotation("verbatim2")) { append("4") }
-            withAnnotation(UrlAnnotation("url1")) { append("5") }
-            withAnnotation(UrlAnnotation("url2")) { append("6") }
-            withLink(
-                LinkAnnotation.Url(
-                    "url3",
-                    TextLinkStyles(
-                        SpanStyle(color = Color.Red),
-                        SpanStyle(color = Color.Green),
-                        SpanStyle(color = Color.Blue),
-                        SpanStyle(color = Color.White)
-                    )
-                )
-            ) {
-                append("7")
-            }
-            withLink(
-                LinkAnnotation.Clickable(
-                    "tag3",
-                    TextLinkStyles(
-                        SpanStyle(color = Color.Red),
-                        SpanStyle(color = Color.Green),
-                        SpanStyle(color = Color.Blue),
-                        SpanStyle(background = Color.Gray)
-                    ),
-                    null
-                )
-            ) {
-                append("8")
-            }
-        }
-
-        val saved = with(AnnotatedStringSaver) { defaultSaverScope.save(original) }
-
-        val restored: AnnotatedString = AnnotatedStringSaver.restore(saved!!)!!
-
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @OptIn(ExperimentalTextApi::class)
-    @Test
-    fun test_AnnotatedString_withSpanAndParagraphStylesAndAnnotations() {
-        val original = buildAnnotatedString {
-            withStyle(ParagraphStyle(textAlign = TextAlign.Justify)) { append("1") }
-            withStyle(ParagraphStyle(textDirection = TextDirection.Rtl)) { append("2") }
-            withStyle(SpanStyle(color = Color.Red)) { append("3") }
-            withStyle(SpanStyle(fontStyle = FontStyle.Italic)) { append("4") }
-            withAnnotation(tag = "Tag1", annotation = "Annotation1") { append("5") }
-            withAnnotation(VerbatimTtsAnnotation("verbatim1")) { append("6") }
-            withAnnotation(tag = "Tag2", annotation = "Annotation2") { append("7") }
-            withAnnotation(VerbatimTtsAnnotation("verbatim2")) { append("8") }
-            withAnnotation(UrlAnnotation("url1")) { append("9") }
-            withAnnotation(UrlAnnotation("url2")) { append("10") }
-            withLink(
-                LinkAnnotation.Url(
-                    "url3",
-                    TextLinkStyles(
-                        SpanStyle(color = Color.Red),
-                        SpanStyle(color = Color.Green),
-                        SpanStyle(color = Color.Blue),
-                        SpanStyle(color = Color.Yellow)
-                    )
-                )
-            ) {
-                append("11")
-            }
-            withLink(
-                LinkAnnotation.Clickable(
-                    "tag3",
-                    TextLinkStyles(
-                        SpanStyle(color = Color.Red),
-                        SpanStyle(color = Color.Green),
-                        SpanStyle(color = Color.Blue),
-                        SpanStyle(color = Color.Gray)
-                    ),
-                    null
-                )
-            ) {
-                append("12")
-            }
-        }
-
-        val saved = with(AnnotatedStringSaver) { defaultSaverScope.save(original) }
-
-        val restored: AnnotatedString = AnnotatedStringSaver.restore(saved!!)!!
-        assertThat(restored).isEqualTo(original)
-    }
-
-    @Test
-    fun test_Locale() {
-        val original = Locale("sr-Latn-SR")
-        val saved = with(Locale.Saver) { defaultSaverScope.save(original) }
-
-        assertThat(Locale.Saver.restore(saved!!)).isEqualTo(original)
-    }
-
-    @Test
-    fun test_LocaleList() {
-        val original = LocaleList(Locale("sr-Latn-SR"), Locale("sr-Cyrl-SR"), Locale.current)
-        val saved = with(LocaleList.Saver) { defaultSaverScope.save(original) }
-
-        assertThat(LocaleList.Saver.restore(saved!!)).isEqualTo(original)
-    }
-}
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/AnnotatedString.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/AnnotatedString.kt
index e66c58e..66e075a 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/AnnotatedString.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/AnnotatedString.kt
@@ -19,13 +19,17 @@
 import androidx.compose.runtime.Immutable
 import androidx.compose.runtime.Stable
 import androidx.compose.runtime.saveable.Saver
+import androidx.compose.ui.text.AnnotatedString.Annotation
 import androidx.compose.ui.text.AnnotatedString.Builder
 import androidx.compose.ui.text.AnnotatedString.Range
 import androidx.compose.ui.text.intl.LocaleList
 import androidx.compose.ui.util.fastAny
 import androidx.compose.ui.util.fastFilter
+import androidx.compose.ui.util.fastFlatMap
 import androidx.compose.ui.util.fastForEach
 import androidx.compose.ui.util.fastMap
+import kotlin.contracts.ExperimentalContracts
+import kotlin.contracts.contract
 
 /**
  * The basic data structure of text with multiple styles. To construct an [AnnotatedString] you can
@@ -33,16 +37,15 @@
  */
 @Immutable
 class AnnotatedString
-internal constructor(
-    val text: String,
-    internal val spanStylesOrNull: List<Range<SpanStyle>>? = null,
-    internal val paragraphStylesOrNull: List<Range<ParagraphStyle>>? = null,
-    internal val annotations: List<Range<out Any>>? = null
-) : CharSequence {
+internal constructor(internal val annotations: List<Range<out Annotation>>?, val text: String) :
+    CharSequence {
+
+    internal val spanStylesOrNull: List<Range<SpanStyle>>?
     /** All [SpanStyle] that have been applied to a range of this String */
     val spanStyles: List<Range<SpanStyle>>
         get() = spanStylesOrNull ?: emptyList()
 
+    internal val paragraphStylesOrNull: List<Range<ParagraphStyle>>?
     /** All [ParagraphStyle] that have been applied to a range of this String */
     val paragraphStyles: List<Range<ParagraphStyle>>
         get() = paragraphStylesOrNull ?: emptyList()
@@ -51,11 +54,13 @@
      * The basic data structure of text with multiple styles. To construct an [AnnotatedString] you
      * can use [Builder].
      *
+     * If you need to provide other types of [Annotation]s, use an alternative constructor.
+     *
      * @param text the text to be displayed.
      * @param spanStyles a list of [Range]s that specifies [SpanStyle]s on certain portion of the
      *   text. These styles will be applied in the order of the list. And the [SpanStyle]s applied
      *   later can override the former styles. Notice that [SpanStyle] attributes which are null or
-     *   [androidx.compose.ui.unit.TextUnit.Unspecified] won't change the current ones.
+     *   [Unspecified] won't change the current ones.
      * @param paragraphStyles a list of [Range]s that specifies [ParagraphStyle]s on certain portion
      *   of the text. Each [ParagraphStyle] with a [Range] defines a paragraph of text. It's
      *   required that [Range]s of paragraphs don't overlap with each other. If there are gaps
@@ -69,9 +74,53 @@
         text: String,
         spanStyles: List<Range<SpanStyle>> = listOf(),
         paragraphStyles: List<Range<ParagraphStyle>> = listOf()
-    ) : this(text, spanStyles.ifEmpty { null }, paragraphStyles.ifEmpty { null }, null)
+    ) : this(constructAnnotationsFromSpansAndParagraphs(spanStyles, paragraphStyles), text)
+
+    /**
+     * The basic data structure of text with multiple styles and other annotations. To construct an
+     * [AnnotatedString] you may use a [Builder].
+     *
+     * @param text the text to be displayed.
+     * @param annotations a list of [Range]s that specifies [Annotation]s on certain portion of the
+     *   text. These annotations will be applied in the order of the list. There're a few properties
+     *   that these annotations have:
+     * - [Annotation]s applied later can override the former annotations. For example, the
+     *   attributes of the last applied [SpanStyle] will override similar attributes of the
+     *   previously applied [SpanStyle]s.
+     * - [SpanStyle] attributes which are null or Unspecified won't change the styling.
+     * - It's required that [Range]s of [ParagraphStyle]s don't overlap with each other. If there
+     *   are gaps between specified paragraph [Range]s, a default paragraph will be created in
+     *   between.
+     *
+     * @throws IllegalArgumentException if [ParagraphStyle]s contains any two overlapping [Range]s.
+     * @sample androidx.compose.ui.text.samples.AnnotatedStringMainConstructorSample
+     * @see Annotation
+     */
+    constructor(
+        text: String,
+        annotations: List<Range<out Annotation>> = emptyList()
+    ) : this(annotations.ifEmpty { null }, text)
 
     init {
+        var spanStyles: MutableList<Range<SpanStyle>>? = null
+        var paragraphStyles: MutableList<Range<ParagraphStyle>>? = null
+        @Suppress("UNCHECKED_CAST")
+        annotations?.fastForEach { annotation ->
+            if (annotation.item is SpanStyle) {
+                if (spanStyles == null) {
+                    spanStyles = mutableListOf()
+                }
+                spanStyles!!.add(annotation as Range<SpanStyle>)
+            } else if (annotation.item is ParagraphStyle) {
+                if (paragraphStyles == null) {
+                    paragraphStyles = mutableListOf()
+                }
+                paragraphStyles!!.add(annotation as Range<ParagraphStyle>)
+            }
+        }
+        spanStylesOrNull = spanStyles
+        paragraphStylesOrNull = paragraphStyles
+
         var lastStyleEnd = -1
         @Suppress("ListIterator")
         paragraphStylesOrNull
@@ -108,8 +157,6 @@
         val text = text.substring(startIndex, endIndex)
         return AnnotatedString(
             text = text,
-            spanStylesOrNull = filterRanges(spanStylesOrNull, startIndex, endIndex),
-            paragraphStylesOrNull = filterRanges(paragraphStylesOrNull, startIndex, endIndex),
             annotations = filterRanges(annotations, startIndex, endIndex)
         )
     }
@@ -147,17 +194,18 @@
      */
     @Suppress("UNCHECKED_CAST")
     fun getStringAnnotations(tag: String, start: Int, end: Int): List<Range<String>> =
-        (annotations?.fastFilter {
-            it.item is String && tag == it.tag && intersect(start, end, it.start, it.end)
+        (annotations?.fastFilterMap({
+            it.item is StringAnnotation && tag == it.tag && intersect(start, end, it.start, it.end)
+        }) {
+            it.unbox()
         } ?: emptyList())
-            as List<Range<String>>
 
     /**
      * Returns true if [getStringAnnotations] with the same parameters would return a non-empty list
      */
     fun hasStringAnnotations(tag: String, start: Int, end: Int): Boolean =
         annotations?.fastAny {
-            it.item is String && tag == it.tag && intersect(start, end, it.start, it.end)
+            it.item is StringAnnotation && tag == it.tag && intersect(start, end, it.start, it.end)
         } ?: false
 
     /**
@@ -171,9 +219,11 @@
      */
     @Suppress("UNCHECKED_CAST")
     fun getStringAnnotations(start: Int, end: Int): List<Range<String>> =
-        (annotations?.fastFilter { it.item is String && intersect(start, end, it.start, it.end) }
-            ?: emptyList())
-            as List<Range<String>>
+        annotations?.fastFilterMap({
+            it.item is StringAnnotation && intersect(start, end, it.start, it.end)
+        }) {
+            it.unbox()
+        } ?: emptyList()
 
     /**
      * Query all of the [TtsAnnotation]s attached on this [AnnotatedString].
@@ -237,16 +287,12 @@
         if (this === other) return true
         if (other !is AnnotatedString) return false
         if (text != other.text) return false
-        if (spanStylesOrNull != other.spanStylesOrNull) return false
-        if (paragraphStylesOrNull != other.paragraphStylesOrNull) return false
         if (annotations != other.annotations) return false
         return true
     }
 
     override fun hashCode(): Int {
         var result = text.hashCode()
-        result = 31 * result + (spanStylesOrNull?.hashCode() ?: 0)
-        result = 31 * result + (paragraphStylesOrNull?.hashCode() ?: 0)
         result = 31 * result + (annotations?.hashCode() ?: 0)
         return result
     }
@@ -262,8 +308,8 @@
      *
      * This may be used for fast partial equality checks.
      *
-     * Note that this only checks annotations, and [equals] still may be false if any of
-     * [spanStyles], [paragraphStyles], or [text] are different.
+     * Note that this checks all annotations including [spanStyles] and [paragraphStyles], but
+     * [equals] still may be false if [text] is different.
      *
      * @param other to compare annotations with
      * @return true if and only if this compares equal on annotations with other
@@ -271,6 +317,34 @@
     fun hasEqualAnnotations(other: AnnotatedString): Boolean = this.annotations == other.annotations
 
     /**
+     * Returns a new [AnnotatedString] where a list of annotations contains the results of applying
+     * the given [transform] function to each element in the original annotations list.
+     *
+     * @sample androidx.compose.ui.text.samples.AnnotatedStringMapAnnotationsSamples
+     */
+    fun mapAnnotations(
+        transform: (Range<out Annotation>) -> Range<out Annotation>
+    ): AnnotatedString {
+        val builder = Builder(this)
+        builder.mapAnnotations(transform)
+        return builder.toAnnotatedString()
+    }
+
+    /**
+     * Returns a new [AnnotatedString] where a list of annotations contains all elementes yielded
+     * from results [transform] function being invoked on each element of original annotations list.
+     *
+     * @see mapAnnotations
+     */
+    fun flatMapAnnotations(
+        transform: (Range<out Annotation>) -> List<Range<out Annotation>>
+    ): AnnotatedString {
+        val builder = Builder(this)
+        builder.flatMapAnnotations(transform)
+        return builder.toAnnotatedString()
+    }
+
+    /**
      * The information attached on the text such as a [SpanStyle].
      *
      * @param item The object attached to [AnnotatedString]s.
@@ -319,13 +393,31 @@
                 check(end != Int.MIN_VALUE) { "Item.end should be set first" }
                 return Range(item = item, start = start, end = end, tag = tag)
             }
+
+            /**
+             * Create an immutable [Range] object.
+             *
+             * @param defaultEnd if the end is not set yet, it will be set to this value.
+             */
+            fun <R> toRange(transform: (T) -> R, defaultEnd: Int = Int.MIN_VALUE): Range<R> {
+                val end = if (end == Int.MIN_VALUE) defaultEnd else end
+                check(end != Int.MIN_VALUE) { "Item.end should be set first" }
+                return Range(item = transform(item), start = start, end = end, tag = tag)
+            }
+
+            companion object {
+                fun <T> fromRange(range: AnnotatedString.Range<T>) =
+                    MutableRange(range.item, range.start, range.end, range.tag)
+            }
         }
 
         private val text: StringBuilder = StringBuilder(capacity)
-        private val spanStyles: MutableList<MutableRange<SpanStyle>> = mutableListOf()
-        private val paragraphStyles: MutableList<MutableRange<ParagraphStyle>> = mutableListOf()
-        private val annotations: MutableList<MutableRange<out Any>> = mutableListOf()
         private val styleStack: MutableList<MutableRange<out Any>> = mutableListOf()
+        /**
+         * Holds all objects of type [AnnotatedString.Annotation] including [SpanStyle]s and
+         * [ParagraphStyle]s in order.
+         */
+        private val annotations = mutableListOf<MutableRange<out Annotation>>()
 
         /** Create an [Builder] instance using the given [String]. */
         constructor(text: String) : this() {
@@ -419,14 +511,7 @@
         fun append(text: AnnotatedString) {
             val start = this.text.length
             this.text.append(text.text)
-            // offset every style with start and add to the builder
-            text.spanStylesOrNull?.fastForEach {
-                addStyle(it.item, start + it.start, start + it.end)
-            }
-            text.paragraphStylesOrNull?.fastForEach {
-                addStyle(it.item, start + it.start, start + it.end)
-            }
-
+            // offset every annotation with start and add to the builder
             text.annotations?.fastForEach {
                 annotations.add(MutableRange(it.item, start + it.start, start + it.end, it.tag))
             }
@@ -444,14 +529,7 @@
         fun append(text: AnnotatedString, start: Int, end: Int) {
             val insertionStart = this.text.length
             this.text.append(text.text, start, end)
-            // offset every style with insertionStart and add to the builder
-            text.getLocalSpanStyles(start, end)?.fastForEach {
-                addStyle(it.item, insertionStart + it.start, insertionStart + it.end)
-            }
-            text.getLocalParagraphStyles(start, end)?.fastForEach {
-                addStyle(it.item, insertionStart + it.start, insertionStart + it.end)
-            }
-
+            // offset every annotation with insertionStart and add to the builder
             text.getLocalAnnotations(start, end)?.fastForEach {
                 annotations.add(
                     MutableRange(
@@ -472,7 +550,7 @@
          * @param end the exclusive end offset of the range
          */
         fun addStyle(style: SpanStyle, start: Int, end: Int) {
-            spanStyles.add(MutableRange(item = style, start = start, end = end))
+            annotations.add(MutableRange(item = style, start = start, end = end))
         }
 
         /**
@@ -484,7 +562,7 @@
          * @param end the exclusive end offset of the range
          */
         fun addStyle(style: ParagraphStyle, start: Int, end: Int) {
-            paragraphStyles.add(MutableRange(item = style, start = start, end = end))
+            annotations.add(MutableRange(item = style, start = start, end = end))
         }
 
         /**
@@ -498,7 +576,14 @@
          * @see getStringAnnotations
          */
         fun addStringAnnotation(tag: String, annotation: String, start: Int, end: Int) {
-            annotations.add(MutableRange(annotation, start, end, tag))
+            annotations.add(
+                MutableRange(
+                    item = StringAnnotation(annotation),
+                    start = start,
+                    end = end,
+                    tag = tag
+                )
+            )
         }
 
         /**
@@ -585,7 +670,7 @@
         fun pushStyle(style: SpanStyle): Int {
             MutableRange(item = style, start = text.length).also {
                 styleStack.add(it)
-                spanStyles.add(it)
+                annotations.add(it)
             }
             return styleStack.size - 1
         }
@@ -600,7 +685,7 @@
         fun pushStyle(style: ParagraphStyle): Int {
             MutableRange(item = style, start = text.length).also {
                 styleStack.add(it)
-                paragraphStyles.add(it)
+                annotations.add(it)
             }
             return styleStack.size - 1
         }
@@ -615,7 +700,7 @@
          * @see Range
          */
         fun pushStringAnnotation(tag: String, annotation: String): Int {
-            MutableRange(item = annotation, start = text.length, tag = tag).also {
+            MutableRange(item = StringAnnotation(annotation), start = text.length, tag = tag).also {
                 styleStack.add(it)
                 annotations.add(it)
             }
@@ -715,14 +800,48 @@
         fun toAnnotatedString(): AnnotatedString {
             return AnnotatedString(
                 text = text.toString(),
-                spanStylesOrNull = spanStyles.fastMap { it.toRange(text.length) }.ifEmpty { null },
-                paragraphStylesOrNull =
-                    paragraphStyles.fastMap { it.toRange(text.length) }.ifEmpty { null },
-                annotations = annotations.fastMap { it.toRange(text.length) }.ifEmpty { null }
+                annotations = annotations.fastMap { it.toRange(text.length) }
             )
         }
+
+        /** @see AnnotatedString.mapAnnotations */
+        internal fun mapAnnotations(transform: (Range<out Annotation>) -> Range<out Annotation>) {
+            for (i in annotations.indices) {
+                val newAnnotation = transform(annotations[i].toRange())
+                annotations[i] = MutableRange.fromRange(newAnnotation)
+            }
+        }
+
+        /** @see AnnotatedString.flatMapAnnotations */
+        internal fun flatMapAnnotations(
+            transform: (Range<out Annotation>) -> List<Range<out Annotation>>
+        ) {
+            val replacedAnnotations =
+                annotations.fastFlatMap {
+                    transform(it.toRange()).fastMap { MutableRange.fromRange(it) }
+                }
+            annotations.clear()
+            annotations.addAll(replacedAnnotations)
+        }
     }
 
+    /**
+     * Defines annotations that specify additional information to apply to ranges of text within the
+     * given AnnotatedString.
+     *
+     * The AnnotatedString supports annotations that provide different kind of information, such as
+     * * [SpanStyle] specifies character level styling such as color, font, letter spacing etc.
+     * * [ParagraphStyle] for configuring styling on a paragraph level such as line heights, text
+     *   aligning, text direction etc.
+     * * [LinkAnnotation] to mark links in the text.
+     * * [TtsAnnotation] provides information to assistive technologies such as screen readers.
+     * * Custom annotations using the [StringAnnotation].
+     */
+    sealed interface Annotation
+
+    // Unused private subclass of the marker interface to avoid exhaustive "when" statement
+    private class ExhaustiveAnnotation : Annotation
+
     companion object {
         /**
          * The default [Saver] implementation for [AnnotatedString].
@@ -735,6 +854,24 @@
     }
 }
 
+private fun constructAnnotationsFromSpansAndParagraphs(
+    spanStyles: List<Range<SpanStyle>>,
+    paragraphStyles: List<Range<ParagraphStyle>>
+): List<Range<out Annotation>>? {
+    return if (spanStyles.isEmpty() && paragraphStyles.isEmpty()) {
+        null
+    } else if (paragraphStyles.isEmpty()) {
+        spanStyles
+    } else if (spanStyles.isEmpty()) {
+        paragraphStyles
+    } else {
+        ArrayList<Range<out Annotation>>(spanStyles.size + paragraphStyles.size).also { array ->
+            spanStyles.fastForEach { array.add(it) }
+            paragraphStyles.fastForEach { array.add(it) }
+        }
+    }
+}
+
 /**
  * A helper function used to determine the paragraph boundaries in [MultiParagraph].
  *
@@ -789,15 +926,9 @@
     if (start == 0 && end >= this.text.length) {
         return spanStyles
     }
-    return spanStyles
-        .fastFilter { intersect(start, end, it.start, it.end) }
-        .fastMap {
-            Range(
-                it.item,
-                it.start.coerceIn(start, end) - start,
-                it.end.coerceIn(start, end) - start
-            )
-        }
+    return spanStyles.fastFilterMap({ intersect(start, end, it.start, it.end) }) {
+        Range(it.item, it.start.coerceIn(start, end) - start, it.end.coerceIn(start, end) - start)
+    }
 }
 
 /**
@@ -817,15 +948,9 @@
     if (start == 0 && end >= this.text.length) {
         return paragraphStyles
     }
-    return paragraphStyles
-        .fastFilter { intersect(start, end, it.start, it.end) }
-        .fastMap {
-            Range(
-                it.item,
-                it.start.coerceIn(start, end) - start,
-                it.end.coerceIn(start, end) - start
-            )
-        }
+    return paragraphStyles.fastFilterMap({ intersect(start, end, it.start, it.end) }) {
+        Range(it.item, it.start.coerceIn(start, end) - start, it.end.coerceIn(start, end) - start)
+    }
 }
 
 /**
@@ -835,23 +960,24 @@
  * @param start The start index of the range, inclusive
  * @param end The end index of the range, exclusive
  */
-private fun AnnotatedString.getLocalAnnotations(start: Int, end: Int): List<Range<out Any>>? {
+private fun AnnotatedString.getLocalAnnotations(
+    start: Int,
+    end: Int
+): List<Range<out AnnotatedString.Annotation>>? {
     if (start == end) return null
     val annotations = annotations ?: return null
-    // If the given range covers the whole AnnotatedString, return SpanStyles without conversion.
+    // If the given range covers the whole AnnotatedString, return it without conversion.
     if (start == 0 && end >= this.text.length) {
         return annotations
     }
-    return annotations
-        .fastFilter { intersect(start, end, it.start, it.end) }
-        .fastMap {
-            Range(
-                tag = it.tag,
-                item = it.item,
-                start = it.start.coerceIn(start, end) - start,
-                end = it.end.coerceIn(start, end) - start
-            )
-        }
+    return annotations.fastFilterMap({ intersect(start, end, it.start, it.end) }) {
+        Range(
+            tag = it.tag,
+            item = it.item,
+            start = it.start.coerceIn(start, end) - start,
+            end = it.end.coerceIn(start, end) - start
+        )
+    }
 }
 
 /**
@@ -866,7 +992,7 @@
 private fun AnnotatedString.substringWithoutParagraphStyles(start: Int, end: Int): AnnotatedString {
     return AnnotatedString(
         text = if (start != end) text.substring(start, end) else "",
-        spanStylesOrNull = getLocalSpanStyles(start, end)
+        annotations = getLocalSpanStyles(start, end) ?: emptyList()
     )
 }
 
@@ -1125,8 +1251,7 @@
     val nonNullRange = ranges ?: return null
 
     return nonNullRange
-        .fastFilter { intersect(start, end, it.start, it.end) }
-        .fastMap {
+        .fastFilterMap({ intersect(start, end, it.start, it.end) }) {
             Range(
                 item = it.item,
                 start = maxOf(start, it.start) - start,
@@ -1198,3 +1323,18 @@
 
 /** Returns an AnnotatedString with empty text and no annotations. */
 internal fun emptyAnnotatedString() = EmptyAnnotatedString
+
+@OptIn(ExperimentalContracts::class)
+@Suppress("BanInlineOptIn")
+private inline fun <T, R> List<T>.fastFilterMap(
+    predicate: (T) -> Boolean,
+    transform: (T) -> R
+): List<R> {
+    contract {
+        callsInPlace(predicate)
+        callsInPlace(transform)
+    }
+    val target = ArrayList<R>(size)
+    fastForEach { if (predicate(it)) target += transform(it) }
+    return target
+}
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/Html.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/Html.kt
deleted file mode 100644
index 53ed97a4..0000000
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/Html.kt
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.text
-
-/**
- * Converts a string with HTML tags into [AnnotatedString].
- *
- * If you define your string in the resources, make sure to use HTML-escaped opening brackets "&lt;"
- * instead of "<".
- *
- * For a list of supported tags go check
- * [Styling with HTML markup](https://developer.android.com/guide/topics/resources/string-resource#StylingWithHTML)
- * guide. Note that bullet lists are not **yet** available.
- *
- * @param htmlString HTML-tagged string to be parsed to construct AnnotatedString
- * @param linkStyles style configuration to be applied to links present in the string in different
- *   styles
- * @param linkInteractionListener a listener that will be attached to links that are present in the
- *   string and triggered when user clicks on those links. When set to null, which is a default, the
- *   system will try to open the corresponding links with the
- *   [androidx.compose.ui.platform.UriHandler] composition local
- *
- * Note that any link style passed directly to this method will be merged with the styles set
- * directly on a HTML-tagged string. For example, if you set a color of the link via the span
- * annotation to "red" but also pass a green color via the [linkStyles], the link will be displayed
- * as green. If, however, you pass a green background via the [linkStyles] instead, the link will be
- * displayed as red on a green background.
- *
- * Example of displaying styled string from resources
- *
- * @sample androidx.compose.ui.text.samples.AnnotatedStringFromHtml
- * @see LinkAnnotation
- */
-expect fun AnnotatedString.Companion.fromHtml(
-    htmlString: String,
-    linkStyles: TextLinkStyles? = null,
-    linkInteractionListener: LinkInteractionListener? = null
-): AnnotatedString
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/LinkAnnotation.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/LinkAnnotation.kt
index 08af0c6..2c1908d 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/LinkAnnotation.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/LinkAnnotation.kt
@@ -16,11 +16,23 @@
 
 package androidx.compose.ui.text
 
-/** An annotation that represents a clickable part of the text. */
-abstract class LinkAnnotation private constructor() {
-    /** Interaction listener triggered when user interacts with this link. */
+/**
+ * An annotation that represents a clickable part of the text.
+ *
+ * @sample androidx.compose.ui.text.samples.AnnotatedStringWithLinkSample
+ */
+abstract class LinkAnnotation private constructor() : AnnotatedString.Annotation {
+    /**
+     * Interaction listener triggered when user interacts with this link.
+     *
+     * @sample androidx.compose.ui.text.samples.AnnotatedStringWithListenerSample
+     */
     abstract val linkInteractionListener: LinkInteractionListener?
-    /** Style configuration for this link in different states */
+    /**
+     * Style configuration for this link in different states.
+     *
+     * @sample androidx.compose.ui.text.samples.AnnotatedStringWithHoveredLinkStylingSample
+     */
     abstract val styles: TextLinkStyles?
 
     /**
@@ -30,12 +42,23 @@
      * its [LinkInteractionListener.onClick] method will be called instead and so you need to then
      * handle opening url manually (for example by calling
      * [androidx.compose.ui.platform.UriHandler]).
+     *
+     * @see LinkAnnotation
      */
     class Url(
         val url: String,
         override val styles: TextLinkStyles? = null,
         override val linkInteractionListener: LinkInteractionListener? = null
     ) : LinkAnnotation() {
+
+        /** Returns a copy of this [Url], optionally overriding some of the values. */
+        @Suppress("ExecutorRegistration")
+        fun copy(
+            url: String = this.url,
+            styles: TextLinkStyles? = this.styles,
+            linkInteractionListener: LinkInteractionListener? = this.linkInteractionListener
+        ) = Url(url, styles, linkInteractionListener)
+
         override fun equals(other: Any?): Boolean {
             if (this === other) return true
             if (other !is Url) return false
@@ -62,6 +85,8 @@
     /**
      * An annotation that contains a clickable marked with [tag]. When clicking on the text to which
      * this annotation is attached, the app will trigger a [linkInteractionListener] listener.
+     *
+     * @see LinkAnnotation
      */
     class Clickable(
         val tag: String,
@@ -69,6 +94,15 @@
         // nullable for the save/restore purposes
         override val linkInteractionListener: LinkInteractionListener?
     ) : LinkAnnotation() {
+
+        /** Returns a copy of this [Clickable], optionally overriding some of the values. */
+        @Suppress("ExecutorRegistration")
+        fun copy(
+            tag: String = this.tag,
+            styles: TextLinkStyles? = this.styles,
+            linkInteractionListener: LinkInteractionListener? = this.linkInteractionListener
+        ) = Clickable(tag, styles, linkInteractionListener)
+
         override fun equals(other: Any?): Boolean {
             if (this === other) return true
             if (other !is Clickable) return false
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/ParagraphStyle.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/ParagraphStyle.kt
index f727872..b8e0abc 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/ParagraphStyle.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/ParagraphStyle.kt
@@ -71,7 +71,7 @@
     val lineBreak: LineBreak = LineBreak.Unspecified,
     val hyphens: Hyphens = Hyphens.Unspecified,
     val textMotion: TextMotion? = null
-) {
+) : AnnotatedString.Annotation {
     @Deprecated("Kept for backwards compatibility.", level = DeprecationLevel.WARNING)
     @get:JvmName("getTextAlign-buA522U") // b/320819734
     @Suppress("unused", "RedundantNullableReturnType", "PropertyName")
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/Savers.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/Savers.kt
index fb83b6b..2224391 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/Savers.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/Savers.kt
@@ -29,9 +29,12 @@
 import androidx.compose.ui.text.intl.Locale
 import androidx.compose.ui.text.intl.LocaleList
 import androidx.compose.ui.text.style.BaselineShift
+import androidx.compose.ui.text.style.LineBreak
+import androidx.compose.ui.text.style.LineHeightStyle
 import androidx.compose.ui.text.style.TextDecoration
 import androidx.compose.ui.text.style.TextGeometricTransform
 import androidx.compose.ui.text.style.TextIndent
+import androidx.compose.ui.text.style.TextMotion
 import androidx.compose.ui.unit.TextUnit
 import androidx.compose.ui.util.fastMap
 
@@ -95,23 +98,17 @@
         save = {
             arrayListOf(
                 save(it.text),
-                save(it.spanStyles, AnnotationRangeListSaver, this),
-                save(it.paragraphStyles, AnnotationRangeListSaver, this),
                 save(it.annotations, AnnotationRangeListSaver, this),
             )
         },
         restore = {
             val list = it as List<Any?>
             // lift these to make types work
-            val spanStylesOrNull: List<AnnotatedString.Range<SpanStyle>>? =
+            val annotationsOrNull: List<AnnotatedString.Range<out AnnotatedString.Annotation>>? =
                 restore(list[1], AnnotationRangeListSaver)
-            val paragraphStylesOrNull: List<AnnotatedString.Range<ParagraphStyle>>? =
-                restore(list[2], AnnotationRangeListSaver)
             AnnotatedString(
                 text = restore(list[0])!!,
-                spanStylesOrNull = spanStylesOrNull?.ifEmpty { null },
-                paragraphStylesOrNull = paragraphStylesOrNull?.ifEmpty { null },
-                annotations = restore(list[3], AnnotationRangeListSaver),
+                annotations = annotationsOrNull,
             )
         }
     )
@@ -150,7 +147,8 @@
                     is UrlAnnotation -> AnnotationType.Url
                     is LinkAnnotation.Url -> AnnotationType.Link
                     is LinkAnnotation.Clickable -> AnnotationType.Clickable
-                    else -> AnnotationType.String
+                    is StringAnnotation -> AnnotationType.String
+                    else -> throw UnsupportedOperationException()
                 }
 
             val item =
@@ -164,7 +162,7 @@
                     AnnotationType.Link -> save(it.item as LinkAnnotation.Url, LinkSaver, this)
                     AnnotationType.Clickable ->
                         save(it.item as LinkAnnotation.Clickable, ClickableSaver, this)
-                    AnnotationType.String -> save(it.item)
+                    AnnotationType.String -> save((it.item as StringAnnotation).value)
                 }
 
             arrayListOf(save(marker), item, save(it.start), save(it.end), save(it.tag))
@@ -203,7 +201,12 @@
                 }
                 AnnotationType.String -> {
                     val item: String = restore(list[1])!!
-                    AnnotatedString.Range(item = item, start = start, end = end, tag = tag)
+                    AnnotatedString.Range(
+                        item = StringAnnotation(item),
+                        start = start,
+                        end = end,
+                        tag = tag
+                    )
                 }
             }
         }
@@ -264,7 +267,12 @@
                 save(it.textAlign),
                 save(it.textDirection),
                 save(it.lineHeight, TextUnit.Saver, this),
-                save(it.textIndent, TextIndent.Saver, this)
+                save(it.textIndent, TextIndent.Saver, this),
+                save(it.platformStyle, PlatformParagraphStyle.Saver, this),
+                save(it.lineHeightStyle, LineHeightStyle.Saver, this),
+                save(it.lineBreak, LineBreak.Saver, this),
+                save(it.hyphens),
+                save(it.textMotion, TextMotion.Saver, this)
             )
         },
         restore = {
@@ -273,7 +281,12 @@
                 textAlign = restore(list[0])!!,
                 textDirection = restore(list[1])!!,
                 lineHeight = restore(list[2], TextUnit.Saver)!!,
-                textIndent = restore(list[3], TextIndent.Saver)
+                textIndent = restore(list[3], TextIndent.Saver),
+                platformStyle = restore(list[4], PlatformParagraphStyle.Saver),
+                lineHeightStyle = restore(list[5], LineHeightStyle.Saver),
+                lineBreak = restore(list[6], LineBreak.Saver)!!,
+                hyphens = restore(list[7])!!,
+                textMotion = restore(list[8], TextMotion.Saver)
             )
         }
     )
@@ -508,3 +521,25 @@
         save = { it.toLanguageTag() },
         restore = { Locale(languageTag = it as String) }
     )
+
+internal val LineHeightStyle.Companion.Saver: Saver<LineHeightStyle, Any>
+    get() = LineHeightStyleSaver
+
+private val LineHeightStyleSaver =
+    Saver<LineHeightStyle, Any>(
+        save = { arrayListOf(save(it.alignment), save(it.trim), save(it.mode)) },
+        restore = {
+            @Suppress("UNCHECKED_CAST") val list = it as List<Any>
+            LineHeightStyle(
+                alignment = restore(list[0])!!,
+                trim = restore(list[1])!!,
+                mode = restore(list[2])!!
+            )
+        },
+    )
+
+internal expect val PlatformParagraphStyle.Companion.Saver: Saver<PlatformParagraphStyle, Any>
+
+internal expect val LineBreak.Companion.Saver: Saver<LineBreak, Any>
+
+internal expect val TextMotion.Companion.Saver: Saver<TextMotion, Any>
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/SpanStyle.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/SpanStyle.kt
index 387fec6..5b926d3 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/SpanStyle.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/SpanStyle.kt
@@ -103,7 +103,7 @@
     val shadow: Shadow? = null,
     val platformStyle: PlatformSpanStyle? = null,
     val drawStyle: DrawStyle? = null
-) {
+) : AnnotatedString.Annotation {
 
     /**
      * Styling configuration for a text span. This configuration only allows character level
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/StringAnnotation.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/StringAnnotation.kt
new file mode 100644
index 0000000..4c293b1
--- /dev/null
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/StringAnnotation.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.ui.text
+
+/**
+ * An [AnnotatedString.Annotation] class which holds a String [value].
+ *
+ * You can use it to provide a custom annotation to the [AnnotatedString].
+ *
+ * If you use the [AnnotatedString.Builder] methods like [withAnnotation] and provide a string
+ * annotation, it will be automatically wrapped into this holder class.
+ *
+ * @see withAnnotation
+ * @see getStringAnnotations
+ */
+@JvmInline value class StringAnnotation(val value: String) : AnnotatedString.Annotation
+
+internal fun AnnotatedString.Range<out AnnotatedString.Annotation>.unbox():
+    AnnotatedString.Range<String> =
+    AnnotatedString.Range((item as StringAnnotation).value, start, end, tag)
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/TtsAnnotation.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/TtsAnnotation.kt
index 24034be..e8424a7 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/TtsAnnotation.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/TtsAnnotation.kt
@@ -21,7 +21,7 @@
  * processed by a text-to-speech engine, the engine may use the data in this annotation in addition
  * to or instead of its associated text.
  */
-sealed class TtsAnnotation
+sealed class TtsAnnotation : AnnotatedString.Annotation
 
 /**
  * The text associated with this annotation is a series of characters that have to be read verbatim.
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/UrlAnnotation.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/UrlAnnotation.kt
index 3541715..b1446a7 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/UrlAnnotation.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/UrlAnnotation.kt
@@ -27,7 +27,7 @@
 @ExperimentalTextApi
 @Deprecated("Use LinkAnnotatation.Url(url) instead", ReplaceWith("LinkAnnotation.Url(url)"))
 @Suppress("Deprecation")
-class UrlAnnotation(val url: String) {
+class UrlAnnotation(val url: String) : AnnotatedString.Annotation {
     override fun equals(other: Any?): Boolean {
         if (this === other) return true
         if (other !is UrlAnnotation) return false
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/style/LineBreak.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/style/LineBreak.kt
index c319725..6bbc8bb 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/style/LineBreak.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/style/LineBreak.kt
@@ -41,7 +41,7 @@
  * @sample androidx.compose.ui.text.samples.AndroidLineBreakSample
  */
 @Immutable
-expect value class LineBreak private constructor(private val mask: Int) {
+expect value class LineBreak private constructor(internal val mask: Int) {
     companion object {
         /**
          * Basic, fast line breaking. Ideal for text input fields, as it will cause minimal text
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/style/LineHeightStyle.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/style/LineHeightStyle.kt
index bd55b0c..5ad11e9 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/style/LineHeightStyle.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/style/LineHeightStyle.kt
@@ -33,23 +33,40 @@
  * @param trim defines whether the space that would be added to the top of first line, and bottom of
  *   the last line should be trimmed or not. This feature is available only when
  *   [PlatformParagraphStyle.includeFontPadding] is false.
+ * @param mode defines the behavior when the specified line height is smaller than system preferred
+ *   line height. By specifying [Mode.Fixed], the line height is always set to the specified value.
+ *   This is the default value. By specifying [Mode.Minimum], the specified line height is smaller
+ *   than the system preferred value, the system preferred one is used instead.
  */
-class LineHeightStyle(val alignment: Alignment, val trim: Trim) {
+class LineHeightStyle(val alignment: Alignment, val trim: Trim, val mode: Mode) {
+
+    constructor(alignment: Alignment, trim: Trim) : this(alignment, trim, Mode.Fixed)
+
     companion object {
         /**
          * The default configuration for [LineHeightStyle]:
          * - alignment = [Alignment.Proportional]
          * - trim = [Trim.Both]
+         * - mode = [Mode.Fixed]
          */
-        val Default = LineHeightStyle(alignment = Alignment.Proportional, trim = Trim.Both)
+        val Default =
+            LineHeightStyle(alignment = Alignment.Proportional, trim = Trim.Both, mode = Mode.Fixed)
     }
 
+    /** Returns a copy of this [LineHeightStyle], optionally overriding some of the values. */
+    fun copy(
+        alignment: Alignment = this.alignment,
+        trim: Trim = this.trim,
+        mode: Mode = this.mode,
+    ) = LineHeightStyle(alignment, trim, mode)
+
     override fun equals(other: Any?): Boolean {
         if (this === other) return true
         if (other !is LineHeightStyle) return false
 
         if (alignment != other.alignment) return false
         if (trim != other.trim) return false
+        if (mode != other.mode) return false
 
         return true
     }
@@ -57,11 +74,12 @@
     override fun hashCode(): Int {
         var result = alignment.hashCode()
         result = 31 * result + trim.hashCode()
+        result = 31 * result + mode.hashCode()
         return result
     }
 
     override fun toString(): String {
-        return "LineHeightStyle(" + "alignment=$alignment, " + "trim=$trim" + ")"
+        return "LineHeightStyle(" + "alignment=$alignment, " + "trim=$trim," + "mode=$mode" + ")"
     }
 
     /**
@@ -279,4 +297,30 @@
             val Bottom = Alignment(topRatio = 1f)
         }
     }
+
+    /**
+     * Defines if the specified line height value should be enforced.
+     *
+     * The line height is determined by the font file used in the text. So, sometimes the specified
+     * text height can be too tight to show the given text. By using `Adjustment.Minimum` the line
+     * height can be adjusted to the system provided value if the specified line height is too
+     * tight. This is useful for supporting languages that use tall glyphs, e.g. Arabic, Myanmar,
+     * etc.
+     */
+    @JvmInline
+    value class Mode private constructor(private val value: Int) {
+        companion object {
+            /**
+             * Always use the specified line height. Even if the system preferred line height is
+             * larger than specified one, the specified line height is used.
+             */
+            val Fixed = Mode(0)
+
+            /**
+             * Use the specified line height if the system preferred line height is smaller than
+             * specified line height.
+             */
+            val Minimum = Mode(1)
+        }
+    }
 }
diff --git a/compose/ui/ui-text/src/commonTest/kotlin/androidx/compose/ui/text/SaversTest.kt b/compose/ui/ui-text/src/commonTest/kotlin/androidx/compose/ui/text/SaversTest.kt
new file mode 100644
index 0000000..c6db31c
--- /dev/null
+++ b/compose/ui/ui-text/src/commonTest/kotlin/androidx/compose/ui/text/SaversTest.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.ui.text
+
+import androidx.compose.runtime.saveable.SaverScope
+import androidx.compose.ui.text.style.Hyphens
+import androidx.compose.ui.text.style.LineBreak
+import androidx.compose.ui.text.style.LineHeightStyle
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.text.style.TextDirection
+import androidx.compose.ui.text.style.TextIndent
+import androidx.compose.ui.text.style.TextMotion
+import androidx.compose.ui.unit.sp
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class SaversTest {
+    private val defaultSaverScope = SaverScope { true }
+
+    @Test
+    fun test_ParagraphStyle_with_no_null_value() {
+        val original =
+            ParagraphStyle(
+                textAlign = TextAlign.Justify,
+                textDirection = TextDirection.Rtl,
+                lineHeight = 10.sp,
+                textIndent = TextIndent(firstLine = 2.sp, restLine = 3.sp),
+                platformStyle = PlatformParagraphStyle.Default,
+                lineHeightStyle = LineHeightStyle.Default,
+                lineBreak = LineBreak.Paragraph,
+                hyphens = Hyphens.Auto,
+                textMotion = TextMotion.Animated
+            )
+        val saved = save(original, ParagraphStyleSaver, defaultSaverScope)
+        val restored: ParagraphStyle? = restore(saved, ParagraphStyleSaver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_PlatformParagraphStyle() {
+        val original = PlatformParagraphStyle.Default
+        val saved = save(original, PlatformParagraphStyle.Saver, defaultSaverScope)
+        val restored: PlatformParagraphStyle? = restore(saved, PlatformParagraphStyle.Saver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_LineBreak() {
+        val original = LineBreak.Paragraph
+        val saved = save(original, LineBreak.Saver, defaultSaverScope)
+        val restored: LineBreak? = restore(saved, LineBreak.Saver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+
+    @Test
+    fun test_TextMotion() {
+        val original = TextMotion.Animated
+        val saved = save(original, TextMotion.Saver, defaultSaverScope)
+        val restored: TextMotion? = restore(saved, TextMotion.Saver)
+
+        assertThat(restored).isEqualTo(original)
+    }
+}
diff --git a/compose/ui/ui-text/src/desktopTest/kotlin/androidx/compose/ui/text/CacheTest.kt b/compose/ui/ui-text/src/desktopTest/kotlin/androidx/compose/ui/text/CacheTest.kt
deleted file mode 100644
index 131f5a8..0000000
--- a/compose/ui/ui-text/src/desktopTest/kotlin/androidx/compose/ui/text/CacheTest.kt
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.text
-
-import com.google.common.truth.Truth
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-private class MockedTimeProvider : ExpireAfterAccessCache.TimeProvider {
-    var currentTime: Long = 0
-
-    override fun getTime() = currentTime
-}
-
-private const val twoSecondsInNanos = 2_000_000_000
-private const val tenMillisInNanos = 10_000_000
-
-@RunWith(JUnit4::class)
-class CacheTest {
-    private val time = MockedTimeProvider()
-    private val cache =
-        ExpireAfterAccessCache<String, String>(
-            expireAfterNanos = 1_000_000_000L, // 1 second
-            timeProvider = time
-        )
-
-    @Test
-    fun single_key() {
-        cache.get("k1") { "v1" }
-        Truth.assertThat(cache.accessQueue.head!!.key).isEqualTo("k1")
-        Truth.assertThat(cache.accessQueue.tail!!.key).isEqualTo("k1")
-
-        var valueFromCache = cache.get("k1") { "v1_2" }
-        Truth.assertThat(valueFromCache).isEqualTo("v1")
-
-        time.currentTime += twoSecondsInNanos
-
-        valueFromCache = cache.get("k1") { "v1_3" }
-        Truth.assertThat(valueFromCache).isEqualTo("v1")
-
-        Truth.assertThat(cache.accessQueue.head!!.accessTime).isEqualTo(twoSecondsInNanos)
-    }
-
-    @Test
-    fun two_keys() {
-        cache.get("k1") { "v1" }
-
-        time.currentTime += tenMillisInNanos
-
-        cache.get("k2") { "v2" }
-
-        Truth.assertThat(cache.accessQueue.head!!.key).isEqualTo("k2")
-        Truth.assertThat(cache.accessQueue.tail!!.key).isEqualTo("k1")
-
-        time.currentTime += tenMillisInNanos
-
-        var valueFromCache = cache.get("k1") { "v1_2" }
-
-        Truth.assertThat(valueFromCache).isEqualTo("v1")
-
-        Truth.assertThat(cache.accessQueue.head!!.key).isEqualTo("k1")
-        Truth.assertThat(cache.accessQueue.tail!!.key).isEqualTo("k2")
-
-        // expiration
-        time.currentTime += twoSecondsInNanos
-        cache.get("k1") { "v1_3" }
-
-        Truth.assertThat(cache.accessQueue.head!!.key).isEqualTo("k1")
-        Truth.assertThat(cache.accessQueue.tail!!.key).isEqualTo("k1")
-
-        Truth.assertThat(cache.map.size).isEqualTo(1)
-    }
-
-    @Test
-    fun three_keys() {
-        cache.get("k1") { "v1" }
-        cache.get("k2") { "v2" }
-        cache.get("k3") { "v3" }
-
-        Truth.assertThat(cache.accessQueue.head!!.key).isEqualTo("k3")
-        Truth.assertThat(cache.accessQueue.tail!!.key).isEqualTo("k1")
-
-        cache.get("k2") { "v2_2" }
-
-        Truth.assertThat(cache.accessQueue.head!!.key).isEqualTo("k2")
-        Truth.assertThat(cache.accessQueue.tail!!.key).isEqualTo("k1")
-        Truth.assertThat(cache.accessQueue.tail!!.nextInAccess!!.key).isEqualTo("k3")
-
-        time.currentTime += twoSecondsInNanos
-        cache.get("k3") { "v3_3" }
-
-        Truth.assertThat(cache.accessQueue.head!!.key).isEqualTo("k3")
-        Truth.assertThat(cache.accessQueue.head!!).isEqualTo(cache.accessQueue.tail!!)
-        Truth.assertThat(cache.accessQueue.tail!!.prevInAccess).isNull()
-        Truth.assertThat(cache.accessQueue.tail!!.nextInAccess).isNull()
-
-        Truth.assertThat(cache.map.size).isEqualTo(1)
-    }
-}
diff --git a/compose/ui/ui-text/src/desktopTest/kotlin/androidx/compose/ui/text/DesktopFontTest.kt b/compose/ui/ui-text/src/desktopTest/kotlin/androidx/compose/ui/text/DesktopFontTest.kt
deleted file mode 100644
index 09b876e..0000000
--- a/compose/ui/ui-text/src/desktopTest/kotlin/androidx/compose/ui/text/DesktopFontTest.kt
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.text
-
-import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.compose.ui.text.font.FontFamily
-import androidx.compose.ui.text.font.FontStyle
-import androidx.compose.ui.text.font.SkiaFontLoader
-import androidx.compose.ui.text.platform.Font
-import androidx.compose.ui.text.platform.GenericFontFamiliesMapping
-import androidx.compose.ui.text.platform.Typeface
-import com.google.common.truth.Truth
-import org.jetbrains.skia.Data
-import org.jetbrains.skia.Typeface
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class DesktopFontTest {
-    @get:Rule val rule = createComposeRule()
-
-    private val fontLoader = SkiaFontLoader()
-
-    private val fontListFontFamily by lazy {
-        FontFamily(
-            Font("font/sample_font.ttf"),
-            Font("font/test_400_italic.ttf", style = FontStyle.Italic)
-        )
-    }
-
-    private val loadedTypeface by lazy {
-        val bytes =
-            Thread.currentThread()
-                .contextClassLoader
-                .getResourceAsStream("font/sample_font.ttf")!!
-                .readAllBytes()
-        Typeface.makeFromData(Data.makeFromBytes(bytes))
-    }
-
-    private val loadedFontFamily by lazy { FontFamily(Typeface(loadedTypeface)) }
-
-    @Test
-    fun ensureRegistered() {
-        Truth.assertThat(fontLoader.loadPlatformTypes(FontFamily.Cursive).aliases)
-            .isEqualTo(GenericFontFamiliesMapping[FontFamily.Cursive.name])
-
-        Truth.assertThat(fontLoader.loadPlatformTypes(FontFamily.Default).aliases)
-            .isEqualTo(GenericFontFamiliesMapping[FontFamily.SansSerif.name])
-
-        Truth.assertThat(fontLoader.loadPlatformTypes(loadedFontFamily).aliases)
-            .isEqualTo(listOf("Sample Font"))
-    }
-}
diff --git a/compose/ui/ui-text/src/desktopTest/kotlin/androidx/compose/ui/text/DesktopParagraphTest.kt b/compose/ui/ui-text/src/desktopTest/kotlin/androidx/compose/ui/text/DesktopParagraphTest.kt
deleted file mode 100644
index 6cf61a1..0000000
--- a/compose/ui/ui-text/src/desktopTest/kotlin/androidx/compose/ui/text/DesktopParagraphTest.kt
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.text
-
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.geometry.Rect
-import androidx.compose.ui.graphics.Canvas
-import androidx.compose.ui.graphics.ImageBitmap
-import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.compose.ui.text.font.FontFamily
-import androidx.compose.ui.text.font.FontStyle
-import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.text.font.createFontFamilyResolver
-import androidx.compose.ui.text.platform.Font
-import androidx.compose.ui.text.style.TextDirection
-import androidx.compose.ui.unit.Constraints
-import androidx.compose.ui.unit.Density
-import androidx.compose.ui.unit.sp
-import com.google.common.truth.Truth
-import org.junit.Assume.assumeTrue
-import org.junit.Ignore
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class DesktopParagraphTest {
-    @get:Rule val rule = createComposeRule()
-
-    private val fontFamilyResolver = createFontFamilyResolver()
-    private val defaultDensity = Density(density = 1f)
-    private val fontFamilyMeasureFont =
-        FontFamily(
-            Font("font/sample_font.ttf", weight = FontWeight.Normal, style = FontStyle.Normal)
-        )
-
-    @Test
-    @Ignore("b/271123970 Fails in AOSP. Will be fixed after upstreaming Compose for Desktop")
-    fun getBoundingBox_basic() {
-        with(defaultDensity) {
-            val text = "abc"
-            val fontSize = 50.sp
-            val fontSizeInPx = fontSize.toPx()
-            val paragraph = simpleParagraph(text = text, style = TextStyle(fontSize = fontSize))
-
-            for (i in 0..text.length - 1) {
-                val box = paragraph.getBoundingBox(i)
-                Truth.assertThat(box.left).isEqualTo(i * fontSizeInPx)
-                Truth.assertThat(box.right).isEqualTo((i + 1) * fontSizeInPx)
-                Truth.assertThat(box.top).isZero()
-                Truth.assertThat(box.bottom).isEqualTo(fontSizeInPx + 10)
-            }
-        }
-    }
-
-    @Test
-    @Ignore("b/271123970 Fails in AOSP. Will be fixed after upstreaming Compose for Desktop")
-    fun getBoundingBox_multicodepoints() {
-        assumeTrue(isLinux)
-        with(defaultDensity) {
-            val text = "h\uD83E\uDDD1\uD83C\uDFFF\u200D\uD83E\uDDB0"
-            val fontSize = 50.sp
-            val fontSizeInPx = fontSize.toPx()
-            val paragraph = simpleParagraph(text = text, style = TextStyle(fontSize = 50.sp))
-
-            Truth.assertThat(paragraph.getBoundingBox(0)).isEqualTo(Rect(0f, 0f, fontSizeInPx, 60f))
-
-            Truth.assertThat(paragraph.getBoundingBox(1))
-                .isEqualTo(Rect(fontSizeInPx, 0f, fontSizeInPx * 2.5f, 60f))
-
-            Truth.assertThat(paragraph.getBoundingBox(5))
-                .isEqualTo(Rect(fontSizeInPx, 0f, fontSizeInPx * 2.5f, 60f))
-        }
-    }
-
-    @Test
-    fun getLineForOffset() {
-        val text = "ab\na"
-        val paragraph = simpleParagraph(text = text, style = TextStyle(fontSize = 50.sp))
-
-        Truth.assertThat(paragraph.getLineForOffset(2)).isEqualTo(0)
-        Truth.assertThat(paragraph.getLineForOffset(3)).isEqualTo(1)
-    }
-
-    @Test
-    fun getLineEnd() {
-        with(defaultDensity) {
-            val text = ""
-            val paragraph = simpleParagraph(text = text, style = TextStyle(fontSize = 50.sp))
-
-            Truth.assertThat(paragraph.getLineEnd(0, true)).isEqualTo(0)
-        }
-        with(defaultDensity) {
-            val text = "ab\n\nc"
-            val paragraph = simpleParagraph(text = text, style = TextStyle(fontSize = 50.sp))
-
-            Truth.assertThat(paragraph.getLineEnd(0, true)).isEqualTo(2)
-            Truth.assertThat(paragraph.getLineEnd(1, true)).isEqualTo(3)
-            Truth.assertThat(paragraph.getLineEnd(2, true)).isEqualTo(5)
-        }
-        with(defaultDensity) {
-            val text = "ab\n"
-            val paragraph = simpleParagraph(text = text, style = TextStyle(fontSize = 50.sp))
-
-            Truth.assertThat(paragraph.getLineEnd(0, true)).isEqualTo(2)
-            Truth.assertThat(paragraph.getLineEnd(1, true)).isEqualTo(3)
-        }
-    }
-
-    @Test
-    fun getLineBaseline() {
-        val text = "abc\nabc\nabc"
-        val paragraph = simpleParagraph(text = text)
-
-        Truth.assertThat(paragraph.getLineBaseline(0)).isEqualTo(paragraph.firstBaseline)
-        Truth.assertThat(paragraph.getLineBaseline(2)).isEqualTo(paragraph.lastBaseline)
-    }
-
-    @Test
-    fun getHorizontalPositionForOffset_primary_Bidi_singleLine_textDirectionDefault() {
-        with(defaultDensity) {
-            val ltrText = "abc"
-            val rtlText = "\u05D0\u05D1\u05D2"
-            val text = ltrText + rtlText
-            val fontSize = 50.sp
-            val fontSizeInPx = fontSize.toPx()
-            val width = text.length * fontSizeInPx
-            val paragraph =
-                simpleParagraph(text = text, style = TextStyle(fontSize = fontSize), width = width)
-
-            for (i in 0..ltrText.length) {
-                Truth.assertThat(paragraph.getHorizontalPosition(i, true))
-                    .isEqualTo(fontSizeInPx * i)
-            }
-
-            for (i in 1 until rtlText.length) {
-                Truth.assertThat(paragraph.getHorizontalPosition(i + ltrText.length, true))
-                    .isEqualTo(width - fontSizeInPx * i)
-            }
-        }
-    }
-
-    @Test
-    fun getHorizontalPositionForOffset_notPrimary_Bidi_singleLine_textDirectionLtr() {
-        with(defaultDensity) {
-            val ltrText = "abc"
-            val rtlText = "\u05D0\u05D1\u05D2"
-            val text = ltrText + rtlText
-            val fontSize = 50.sp
-            val fontSizeInPx = fontSize.toPx()
-            val width = text.length * fontSizeInPx
-            val paragraph =
-                simpleParagraph(
-                    text = text,
-                    style = TextStyle(fontSize = fontSize, textDirection = TextDirection.Ltr),
-                    width = width
-                )
-
-            for (i in ltrText.indices) {
-                Truth.assertThat(paragraph.getHorizontalPosition(i, false))
-                    .isEqualTo(fontSizeInPx * i)
-            }
-
-            for (i in rtlText.indices) {
-                Truth.assertThat(paragraph.getHorizontalPosition(i + ltrText.length, false))
-                    .isEqualTo(width - fontSizeInPx * i)
-            }
-
-            Truth.assertThat(paragraph.getHorizontalPosition(text.length, false))
-                .isEqualTo(width - rtlText.length * fontSizeInPx)
-        }
-    }
-
-    @Test
-    fun getWordBoundary_spaces() {
-        val text = "ab cd  e"
-        val paragraph =
-            simpleParagraph(
-                text = text,
-                style = TextStyle(fontFamily = fontFamilyMeasureFont, fontSize = 20.sp)
-            )
-
-        val singleSpaceStartResult = paragraph.getWordBoundary(text.indexOf('b') + 1)
-        Truth.assertThat(singleSpaceStartResult.start).isEqualTo(text.indexOf('a'))
-        Truth.assertThat(singleSpaceStartResult.end).isEqualTo(text.indexOf('b') + 1)
-
-        val singleSpaceEndResult = paragraph.getWordBoundary(text.indexOf('c'))
-
-        Truth.assertThat(singleSpaceEndResult.start).isEqualTo(text.indexOf('c'))
-        Truth.assertThat(singleSpaceEndResult.end).isEqualTo(text.indexOf('d') + 1)
-
-        val doubleSpaceResult = paragraph.getWordBoundary(text.indexOf('d') + 2)
-        Truth.assertThat(doubleSpaceResult.start).isEqualTo(text.indexOf('d') + 2)
-        Truth.assertThat(doubleSpaceResult.end).isEqualTo(text.indexOf('d') + 2)
-    }
-
-    @Test
-    fun two_paragraphs_use_common_intrinsics() {
-        fun Paragraph.testOffset() = getOffsetForPosition(Offset(0f, 100000f))
-        fun Paragraph.paint() = paint(Canvas(ImageBitmap(100, 100)))
-
-        val intrinsics = simpleIntrinsics((1..1000).joinToString(" "))
-
-        val paragraph1 = simpleParagraph(intrinsics, width = 100f)
-        val offset1 = paragraph1.testOffset()
-
-        val paragraph2 = simpleParagraph(intrinsics, width = 100000f)
-        val offset2 = paragraph2.testOffset()
-
-        Truth.assertThat(paragraph1.testOffset()).isEqualTo(offset1)
-        Truth.assertThat(paragraph2.testOffset()).isEqualTo(offset2)
-
-        paragraph2.paint()
-        Truth.assertThat(paragraph1.testOffset()).isEqualTo(offset1)
-        Truth.assertThat(paragraph2.testOffset()).isEqualTo(offset2)
-
-        paragraph1.paint()
-        Truth.assertThat(paragraph1.testOffset()).isEqualTo(offset1)
-        Truth.assertThat(paragraph2.testOffset()).isEqualTo(offset2)
-
-        paragraph2.paint()
-        Truth.assertThat(paragraph1.testOffset()).isEqualTo(offset1)
-        Truth.assertThat(paragraph2.testOffset()).isEqualTo(offset2)
-    }
-
-    @Test
-    fun `line heights`() {
-        val paragraph =
-            simpleParagraph(
-                text = "aaa\n\naaa\n\n\naaa\n   \naaa",
-                style = TextStyle(fontSize = 50.sp)
-            )
-        val firstLineHeight = paragraph.getLineHeight(0)
-
-        for (i in 1 until paragraph.lineCount) {
-            Truth.assertThat(paragraph.getLineHeight(i)).isEqualTo(firstLineHeight)
-        }
-    }
-
-    private fun simpleParagraph(
-        text: String = "",
-        style: TextStyle? = null,
-        maxLines: Int = Int.MAX_VALUE,
-        ellipsis: Boolean = false,
-        spanStyles: List<AnnotatedString.Range<SpanStyle>> = listOf(),
-        density: Density? = null,
-        width: Float = 2000f
-    ): Paragraph {
-        return Paragraph(
-            text = text,
-            spanStyles = spanStyles,
-            style = TextStyle(fontFamily = fontFamilyMeasureFont).merge(style),
-            maxLines = maxLines,
-            ellipsis = ellipsis,
-            constraints = Constraints(maxWidth = width.ceilToInt()),
-            density = density ?: defaultDensity,
-            fontFamilyResolver = fontFamilyResolver
-        )
-    }
-
-    private fun simpleIntrinsics(
-        text: String = "",
-        style: TextStyle? = null,
-        spanStyles: List<AnnotatedString.Range<SpanStyle>> = listOf(),
-        density: Density? = null
-    ): ParagraphIntrinsics {
-        return ParagraphIntrinsics(
-            text = text,
-            spanStyles = spanStyles,
-            style = TextStyle(fontFamily = fontFamilyMeasureFont).merge(style),
-            density = density ?: defaultDensity,
-            fontFamilyResolver = fontFamilyResolver
-        )
-    }
-
-    private fun simpleParagraph(
-        intrinsics: ParagraphIntrinsics,
-        maxLines: Int = Int.MAX_VALUE,
-        ellipsis: Boolean = false,
-        width: Float = 2000f
-    ): Paragraph {
-        return Paragraph(
-            paragraphIntrinsics = intrinsics,
-            maxLines = maxLines,
-            ellipsis = ellipsis,
-            constraints = Constraints(maxWidth = width.ceilToInt()),
-        )
-    }
-}
diff --git a/compose/ui/ui-text/src/desktopTest/kotlin/androidx/compose/ui/text/TestUtils.kt b/compose/ui/ui-text/src/desktopTest/kotlin/androidx/compose/ui/text/TestUtils.kt
deleted file mode 100644
index 79eac26..0000000
--- a/compose/ui/ui-text/src/desktopTest/kotlin/androidx/compose/ui/text/TestUtils.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.text
-
-private val os = System.getProperty("os.name").lowercase()
-internal val isLinux = os.startsWith("linux")
-internal val isWindows = os.startsWith("win")
-internal val isMacOs = os.startsWith("mac")
diff --git a/compose/ui/ui-text/src/jvmMain/kotlin/androidx/compose/ui/text/JvmAnnotatedString.jvm.kt b/compose/ui/ui-text/src/jvmMain/kotlin/androidx/compose/ui/text/JvmAnnotatedString.jvm.kt
index 7a86459..fe3ebbe 100644
--- a/compose/ui/ui-text/src/jvmMain/kotlin/androidx/compose/ui/text/JvmAnnotatedString.jvm.kt
+++ b/compose/ui/ui-text/src/jvmMain/kotlin/androidx/compose/ui/text/JvmAnnotatedString.jvm.kt
@@ -31,8 +31,6 @@
     transform: (String, Int, Int) -> String
 ): AnnotatedString {
     val transitions = sortedSetOf(0, text.length)
-    collectRangeTransitions(spanStylesOrNull, transitions)
-    collectRangeTransitions(paragraphStylesOrNull, transitions)
     collectRangeTransitions(annotations, transitions)
 
     var resultStr = ""
@@ -41,25 +39,11 @@
         resultStr += transform(text, start, end)
         offsetMap.put(end, resultStr.length)
     }
-
-    val newSpanStyles =
-        spanStylesOrNull?.fastMap {
-            // The offset map must have mapping entry from all style start, end position.
-            Range(it.item, offsetMap[it.start]!!, offsetMap[it.end]!!)
-        }
-    val newParaStyles =
-        paragraphStylesOrNull?.fastMap {
-            Range(it.item, offsetMap[it.start]!!, offsetMap[it.end]!!)
-        }
+    // The offset map must have mapping entry from all style start, end position.
     val newAnnotations =
         annotations?.fastMap { Range(it.item, offsetMap[it.start]!!, offsetMap[it.end]!!) }
 
-    return AnnotatedString(
-        text = resultStr,
-        spanStylesOrNull = newSpanStyles,
-        paragraphStylesOrNull = newParaStyles,
-        annotations = newAnnotations
-    )
+    return AnnotatedString(text = resultStr, annotations = newAnnotations)
 }
 
 /**
diff --git a/compose/ui/ui-text/src/skikoMain/kotlin/androidx/compose/ui/text/Html.skiko.kt b/compose/ui/ui-text/src/skikoMain/kotlin/androidx/compose/ui/text/Html.skiko.kt
deleted file mode 100644
index 195fdbc..0000000
--- a/compose/ui/ui-text/src/skikoMain/kotlin/androidx/compose/ui/text/Html.skiko.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.text
-
-/**
- * TBD: not yet implemented.
- *
- * Converts a string with HTML tags into [AnnotatedString].
- */
-actual fun AnnotatedString.Companion.fromHtml(
-    htmlString: String,
-    linkStyles: TextLinkStyles?,
-    linkInteractionListener: LinkInteractionListener?
-): AnnotatedString = AnnotatedString(htmlString)
diff --git a/compose/ui/ui-text/src/skikoMain/kotlin/androidx/compose/ui/text/Savers.skiko.kt b/compose/ui/ui-text/src/skikoMain/kotlin/androidx/compose/ui/text/Savers.skiko.kt
new file mode 100644
index 0000000..edec094
--- /dev/null
+++ b/compose/ui/ui-text/src/skikoMain/kotlin/androidx/compose/ui/text/Savers.skiko.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.ui.text
+
+import androidx.compose.runtime.saveable.Saver
+import androidx.compose.ui.text.style.LineBreak
+import androidx.compose.ui.text.style.TextMotion
+
+internal actual val PlatformParagraphStyle.Companion.Saver: Saver<PlatformParagraphStyle, Any>
+    get() = PlatformParagraphStyleSaver
+
+private val PlatformParagraphStyleSaver =
+    Saver<PlatformParagraphStyle, Any>(save = {}, restore = { PlatformParagraphStyle() })
+
+internal actual val LineBreak.Companion.Saver: Saver<LineBreak, Any>
+    get() = LineBreakSaver
+
+private val LineBreakSaver =
+    Saver<LineBreak, Any>(
+        save = { it.mask },
+        restore = {
+            val mask = it as Int
+            when (mask) {
+                1 -> LineBreak.Simple
+                2 -> LineBreak.Heading
+                3 -> LineBreak.Paragraph
+                else -> {
+                    LineBreak.Unspecified
+                }
+            }
+        }
+    )
+
+internal actual val TextMotion.Companion.Saver: Saver<TextMotion, Any>
+    get() = TextMotionSaver
+
+private val TextMotionSaver =
+    Saver<TextMotion, Any>(
+        save = { if (it == TextMotion.Static) 0 else 1 },
+        restore = {
+            if (it == 0) {
+                TextMotion.Static
+            } else {
+                TextMotion.Animated
+            }
+        }
+    )
diff --git a/compose/ui/ui-tooling-data/build.gradle b/compose/ui/ui-tooling-data/build.gradle
index dffb37e..4d7de1f 100644
--- a/compose/ui/ui-tooling-data/build.gradle
+++ b/compose/ui/ui-tooling-data/build.gradle
@@ -81,14 +81,8 @@
             }
         }
 
-        jvmTest {
-            dependsOn(commonTest)
-            dependencies {
-            }
-        }
-
         androidInstrumentedTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(project(":compose:ui:ui-test-junit4"))
 
@@ -106,18 +100,11 @@
         }
 
         androidUnitTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(libs.truth)
             }
         }
-
-        desktopTest {
-            dependsOn(jvmTest)
-            dependencies {
-
-            }
-        }
     }
 }
 
diff --git a/compose/ui/ui-tooling-preview/build.gradle b/compose/ui/ui-tooling-preview/build.gradle
index 3922e69..cc56e07 100644
--- a/compose/ui/ui-tooling-preview/build.gradle
+++ b/compose/ui/ui-tooling-preview/build.gradle
@@ -75,31 +75,18 @@
             }
         }
 
-        jvmTest {
+        androidInstrumentedTest {
             dependsOn(commonTest)
             dependencies {
             }
         }
 
-        androidInstrumentedTest {
-            dependsOn(jvmTest)
-            dependencies {
-            }
-        }
-
         androidUnitTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(libs.junit)
             }
         }
-
-        desktopTest {
-            dependsOn(jvmTest)
-            dependencies {
-
-            }
-        }
     }
 }
 
diff --git a/compose/ui/ui-tooling/build.gradle b/compose/ui/ui-tooling/build.gradle
index 2307370..6e2eba5 100644
--- a/compose/ui/ui-tooling/build.gradle
+++ b/compose/ui/ui-tooling/build.gradle
@@ -91,14 +91,8 @@
             }
         }
 
-        jvmTest {
-            dependsOn(commonTest)
-            dependencies {
-            }
-        }
-
         androidInstrumentedTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(project(":compose:ui:ui-test-junit4"))
 
@@ -117,17 +111,10 @@
         }
 
         androidUnitTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
             }
         }
-
-        desktopTest {
-            dependsOn(jvmTest)
-            dependencies {
-
-            }
-        }
     }
 }
 
diff --git a/compose/ui/ui-unit/build.gradle b/compose/ui/ui-unit/build.gradle
index eb2f195..a495a5e 100644
--- a/compose/ui/ui-unit/build.gradle
+++ b/compose/ui/ui-unit/build.gradle
@@ -77,14 +77,8 @@
             }
         }
 
-        jvmTest {
-            dependsOn(commonTest)
-            dependencies {
-            }
-        }
-
         androidInstrumentedTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(libs.testRules)
                 implementation(libs.testRunner)
@@ -96,16 +90,12 @@
         }
 
         androidUnitTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(libs.truth)
                 implementation('androidx.collection:collection-ktx:1.2.0')
             }
         }
-
-        desktopTest {
-            dependsOn(jvmTest)
-        }
     }
 }
 
diff --git a/compose/ui/ui-util/build.gradle b/compose/ui/ui-util/build.gradle
index 4bd9f11..4236e4c 100644
--- a/compose/ui/ui-util/build.gradle
+++ b/compose/ui/ui-util/build.gradle
@@ -70,28 +70,18 @@
             dependsOn(jvmMain)
         }
 
-        jvmTest {
+        androidInstrumentedTest {
             dependsOn(commonTest)
             dependencies {
             }
         }
 
-        androidInstrumentedTest {
-            dependsOn(jvmTest)
-            dependencies {
-            }
-        }
-
         androidUnitTest {
-            dependsOn(jvmTest)
+            dependsOn(commonTest)
             dependencies {
                 implementation(libs.truth)
             }
         }
-
-        desktopTest {
-            dependsOn(jvmTest)
-        }
     }
 }
 
diff --git a/compose/ui/ui/api/current.txt b/compose/ui/ui/api/current.txt
index b5bcfc9..9284277 100644
--- a/compose/ui/ui/api/current.txt
+++ b/compose/ui/ui/api/current.txt
@@ -61,10 +61,12 @@
 
   @androidx.compose.runtime.Stable public static fun interface Alignment.Horizontal {
     method public int align(int size, int space, androidx.compose.ui.unit.LayoutDirection layoutDirection);
+    method public default operator androidx.compose.ui.Alignment plus(androidx.compose.ui.Alignment.Vertical other);
   }
 
   @androidx.compose.runtime.Stable public static fun interface Alignment.Vertical {
     method public int align(int size, int space);
+    method public default operator androidx.compose.ui.Alignment plus(androidx.compose.ui.Alignment.Horizontal other);
   }
 
   @androidx.compose.runtime.Immutable public final class BiasAbsoluteAlignment implements androidx.compose.ui.Alignment {
@@ -85,6 +87,7 @@
     method public float component1();
     method public androidx.compose.ui.BiasAbsoluteAlignment.Horizontal copy(float bias);
     method public float getBias();
+    method public androidx.compose.ui.Alignment plus(androidx.compose.ui.Alignment.Vertical other);
     property public final float bias;
   }
 
@@ -106,6 +109,7 @@
     method public float component1();
     method public androidx.compose.ui.BiasAlignment.Horizontal copy(float bias);
     method public float getBias();
+    method public androidx.compose.ui.Alignment plus(androidx.compose.ui.Alignment.Vertical other);
     property public final float bias;
   }
 
@@ -115,6 +119,7 @@
     method public float component1();
     method public androidx.compose.ui.BiasAlignment.Vertical copy(float bias);
     method public float getBias();
+    method public androidx.compose.ui.Alignment plus(androidx.compose.ui.Alignment.Horizontal other);
     property public final float bias;
   }
 
@@ -1927,6 +1932,10 @@
     property public final long uptimeMillis;
   }
 
+  public fun interface PointerInputEventHandler {
+    method public suspend operator Object? invoke(androidx.compose.ui.input.pointer.PointerInputScope, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+  }
+
   public abstract class PointerInputFilter {
     ctor public PointerInputFilter();
     method public boolean getInterceptOutOfBoundsChildEvents();
@@ -1989,24 +1998,34 @@
   }
 
   public final class SuspendingPointerInputFilterKt {
-    method public static androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNode SuspendingPointerInputModifierNode(kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> pointerInputHandler);
-    method public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, Object? key1, Object? key2, kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> block);
-    method public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, Object? key1, kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> block);
-    method public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, Object?[] keys, kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> block);
+    method public static androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNode SuspendingPointerInputModifierNode(androidx.compose.ui.input.pointer.PointerInputEventHandler pointerInputEventHandler);
+    method @Deprecated public static androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNode SuspendingPointerInputModifierNode(kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> pointerInputHandler);
+    method public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, Object? key1, androidx.compose.ui.input.pointer.PointerInputEventHandler block);
+    method public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, Object? key1, Object? key2, androidx.compose.ui.input.pointer.PointerInputEventHandler block);
+    method @Deprecated public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, Object? key1, Object? key2, kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> block);
+    method @Deprecated public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, Object? key1, kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> block);
+    method @Deprecated public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, java.lang.Object?... keys, kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> block);
+    method public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, Object?[] keys, androidx.compose.ui.input.pointer.PointerInputEventHandler block);
     method @Deprecated public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> block);
   }
 
   public sealed interface SuspendingPointerInputModifierNode extends androidx.compose.ui.node.PointerInputModifierNode {
-    method public kotlin.jvm.functions.Function2<androidx.compose.ui.input.pointer.PointerInputScope,kotlin.coroutines.Continuation<? super kotlin.Unit>,java.lang.Object?> getPointerInputHandler();
+    method public default androidx.compose.ui.input.pointer.PointerInputEventHandler getPointerInputEventHandler();
+    method @Deprecated public kotlin.jvm.functions.Function2<androidx.compose.ui.input.pointer.PointerInputScope,kotlin.coroutines.Continuation<? super kotlin.Unit>,java.lang.Object?> getPointerInputHandler();
     method public void resetPointerInputHandler();
-    method public void setPointerInputHandler(kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?>);
-    property public abstract kotlin.jvm.functions.Function2<androidx.compose.ui.input.pointer.PointerInputScope,kotlin.coroutines.Continuation<? super kotlin.Unit>,java.lang.Object?> pointerInputHandler;
+    method public default void setPointerInputEventHandler(androidx.compose.ui.input.pointer.PointerInputEventHandler);
+    method @Deprecated public void setPointerInputHandler(kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?>);
+    property public default androidx.compose.ui.input.pointer.PointerInputEventHandler pointerInputEventHandler;
+    property @Deprecated public abstract kotlin.jvm.functions.Function2<androidx.compose.ui.input.pointer.PointerInputScope,kotlin.coroutines.Continuation<? super kotlin.Unit>,java.lang.Object?> pointerInputHandler;
   }
 
 }
 
 package androidx.compose.ui.input.pointer.util {
 
+  @SuppressCompatibility @kotlin.RequiresOptIn(message="This an opt-in flag to test the Velocity Tracker strategy algorithm used " + "for calculating gesture velocities in Compose.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalVelocityTrackerApi {
+  }
+
   public final class VelocityTracker {
     ctor public VelocityTracker();
     method public void addPosition(long timeMillis, long position);
@@ -2027,9 +2046,9 @@
 
   public final class VelocityTrackerKt {
     method public static void addPointerInputChange(androidx.compose.ui.input.pointer.util.VelocityTracker, androidx.compose.ui.input.pointer.PointerInputChange event);
-    method public static boolean getVelocityTrackerStrategyUseImpulse();
-    method public static void setVelocityTrackerStrategyUseImpulse(boolean);
-    property public static final boolean VelocityTrackerStrategyUseImpulse;
+    method @SuppressCompatibility @androidx.compose.ui.input.pointer.util.ExperimentalVelocityTrackerApi public static boolean getVelocityTrackerStrategyUseImpulse();
+    method @SuppressCompatibility @androidx.compose.ui.input.pointer.util.ExperimentalVelocityTrackerApi public static void setVelocityTrackerStrategyUseImpulse(boolean);
+    property @SuppressCompatibility @androidx.compose.ui.input.pointer.util.ExperimentalVelocityTrackerApi public static final boolean VelocityTrackerStrategyUseImpulse;
   }
 
 }
@@ -3302,6 +3321,7 @@
     method public int getCheckbox();
     method public int getDropdownList();
     method public int getImage();
+    method public int getNumberPicker();
     method public int getRadioButton();
     method public int getSwitch();
     method public int getTab();
@@ -3309,6 +3329,7 @@
     property public final int Checkbox;
     property public final int DropdownList;
     property public final int Image;
+    property public final int NumberPicker;
     property public final int RadioButton;
     property public final int Switch;
     property public final int Tab;
diff --git a/compose/ui/ui/api/restricted_current.txt b/compose/ui/ui/api/restricted_current.txt
index 74b5fb5..56a0613 100644
--- a/compose/ui/ui/api/restricted_current.txt
+++ b/compose/ui/ui/api/restricted_current.txt
@@ -61,10 +61,12 @@
 
   @androidx.compose.runtime.Stable public static fun interface Alignment.Horizontal {
     method public int align(int size, int space, androidx.compose.ui.unit.LayoutDirection layoutDirection);
+    method public default operator androidx.compose.ui.Alignment plus(androidx.compose.ui.Alignment.Vertical other);
   }
 
   @androidx.compose.runtime.Stable public static fun interface Alignment.Vertical {
     method public int align(int size, int space);
+    method public default operator androidx.compose.ui.Alignment plus(androidx.compose.ui.Alignment.Horizontal other);
   }
 
   @androidx.compose.runtime.Immutable public final class BiasAbsoluteAlignment implements androidx.compose.ui.Alignment {
@@ -85,6 +87,7 @@
     method public float component1();
     method public androidx.compose.ui.BiasAbsoluteAlignment.Horizontal copy(float bias);
     method public float getBias();
+    method public androidx.compose.ui.Alignment plus(androidx.compose.ui.Alignment.Vertical other);
     property public final float bias;
   }
 
@@ -106,6 +109,7 @@
     method public float component1();
     method public androidx.compose.ui.BiasAlignment.Horizontal copy(float bias);
     method public float getBias();
+    method public androidx.compose.ui.Alignment plus(androidx.compose.ui.Alignment.Vertical other);
     property public final float bias;
   }
 
@@ -115,6 +119,7 @@
     method public float component1();
     method public androidx.compose.ui.BiasAlignment.Vertical copy(float bias);
     method public float getBias();
+    method public androidx.compose.ui.Alignment plus(androidx.compose.ui.Alignment.Horizontal other);
     property public final float bias;
   }
 
@@ -1927,6 +1932,10 @@
     property public final long uptimeMillis;
   }
 
+  public fun interface PointerInputEventHandler {
+    method public suspend operator Object? invoke(androidx.compose.ui.input.pointer.PointerInputScope, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+  }
+
   public abstract class PointerInputFilter {
     ctor public PointerInputFilter();
     method public boolean getInterceptOutOfBoundsChildEvents();
@@ -1989,24 +1998,34 @@
   }
 
   public final class SuspendingPointerInputFilterKt {
-    method public static androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNode SuspendingPointerInputModifierNode(kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> pointerInputHandler);
-    method public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, Object? key1, Object? key2, kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> block);
-    method public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, Object? key1, kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> block);
-    method public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, Object?[] keys, kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> block);
+    method public static androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNode SuspendingPointerInputModifierNode(androidx.compose.ui.input.pointer.PointerInputEventHandler pointerInputEventHandler);
+    method @Deprecated public static androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNode SuspendingPointerInputModifierNode(kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> pointerInputHandler);
+    method public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, Object? key1, androidx.compose.ui.input.pointer.PointerInputEventHandler block);
+    method public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, Object? key1, Object? key2, androidx.compose.ui.input.pointer.PointerInputEventHandler block);
+    method @Deprecated public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, Object? key1, Object? key2, kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> block);
+    method @Deprecated public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, Object? key1, kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> block);
+    method @Deprecated public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, java.lang.Object?... keys, kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> block);
+    method public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, Object?[] keys, androidx.compose.ui.input.pointer.PointerInputEventHandler block);
     method @Deprecated public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> block);
   }
 
   public sealed interface SuspendingPointerInputModifierNode extends androidx.compose.ui.node.PointerInputModifierNode {
-    method public kotlin.jvm.functions.Function2<androidx.compose.ui.input.pointer.PointerInputScope,kotlin.coroutines.Continuation<? super kotlin.Unit>,java.lang.Object?> getPointerInputHandler();
+    method public default androidx.compose.ui.input.pointer.PointerInputEventHandler getPointerInputEventHandler();
+    method @Deprecated public kotlin.jvm.functions.Function2<androidx.compose.ui.input.pointer.PointerInputScope,kotlin.coroutines.Continuation<? super kotlin.Unit>,java.lang.Object?> getPointerInputHandler();
     method public void resetPointerInputHandler();
-    method public void setPointerInputHandler(kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?>);
-    property public abstract kotlin.jvm.functions.Function2<androidx.compose.ui.input.pointer.PointerInputScope,kotlin.coroutines.Continuation<? super kotlin.Unit>,java.lang.Object?> pointerInputHandler;
+    method public default void setPointerInputEventHandler(androidx.compose.ui.input.pointer.PointerInputEventHandler);
+    method @Deprecated public void setPointerInputHandler(kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?>);
+    property public default androidx.compose.ui.input.pointer.PointerInputEventHandler pointerInputEventHandler;
+    property @Deprecated public abstract kotlin.jvm.functions.Function2<androidx.compose.ui.input.pointer.PointerInputScope,kotlin.coroutines.Continuation<? super kotlin.Unit>,java.lang.Object?> pointerInputHandler;
   }
 
 }
 
 package androidx.compose.ui.input.pointer.util {
 
+  @SuppressCompatibility @kotlin.RequiresOptIn(message="This an opt-in flag to test the Velocity Tracker strategy algorithm used " + "for calculating gesture velocities in Compose.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalVelocityTrackerApi {
+  }
+
   public final class VelocityTracker {
     ctor public VelocityTracker();
     method public void addPosition(long timeMillis, long position);
@@ -2027,9 +2046,9 @@
 
   public final class VelocityTrackerKt {
     method public static void addPointerInputChange(androidx.compose.ui.input.pointer.util.VelocityTracker, androidx.compose.ui.input.pointer.PointerInputChange event);
-    method public static boolean getVelocityTrackerStrategyUseImpulse();
-    method public static void setVelocityTrackerStrategyUseImpulse(boolean);
-    property public static final boolean VelocityTrackerStrategyUseImpulse;
+    method @SuppressCompatibility @androidx.compose.ui.input.pointer.util.ExperimentalVelocityTrackerApi public static boolean getVelocityTrackerStrategyUseImpulse();
+    method @SuppressCompatibility @androidx.compose.ui.input.pointer.util.ExperimentalVelocityTrackerApi public static void setVelocityTrackerStrategyUseImpulse(boolean);
+    property @SuppressCompatibility @androidx.compose.ui.input.pointer.util.ExperimentalVelocityTrackerApi public static final boolean VelocityTrackerStrategyUseImpulse;
   }
 
 }
@@ -3362,6 +3381,7 @@
     method public int getCheckbox();
     method public int getDropdownList();
     method public int getImage();
+    method public int getNumberPicker();
     method public int getRadioButton();
     method public int getSwitch();
     method public int getTab();
@@ -3369,6 +3389,7 @@
     property public final int Checkbox;
     property public final int DropdownList;
     property public final int Image;
+    property public final int NumberPicker;
     property public final int RadioButton;
     property public final int Switch;
     property public final int Tab;
diff --git a/compose/ui/ui/benchmark/src/androidTest/java/androidx/compose/ui/benchmark/focus/FocusBenchmark.kt b/compose/ui/ui/benchmark/src/androidTest/java/androidx/compose/ui/benchmark/focus/FocusBenchmark.kt
index b228824..b37f732 100644
--- a/compose/ui/ui/benchmark/src/androidTest/java/androidx/compose/ui/benchmark/focus/FocusBenchmark.kt
+++ b/compose/ui/ui/benchmark/src/androidTest/java/androidx/compose/ui/benchmark/focus/FocusBenchmark.kt
@@ -17,11 +17,22 @@
 package androidx.compose.ui.benchmark.focus
 
 import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.ReusableContent
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
 import androidx.compose.testutils.LayeredComposeTestCase
+import androidx.compose.testutils.ToggleableTestCase
 import androidx.compose.testutils.benchmark.ComposeBenchmarkRule
 import androidx.compose.testutils.benchmark.benchmarkToFirstPixel
+import androidx.compose.testutils.benchmark.toggleStateBenchmarkRecompose
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.benchmark.repeatModifier
+import androidx.compose.ui.focus.FocusRequester
+import androidx.compose.ui.focus.focusRequester
 import androidx.compose.ui.focus.focusTarget
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
@@ -36,6 +47,40 @@
     @get:Rule val composeBenchmarkRule = ComposeBenchmarkRule()
 
     @Test
+    fun modifyActiveHierarchy() {
+        composeBenchmarkRule.toggleStateBenchmarkRecompose({
+            object : LayeredComposeTestCase(), ToggleableTestCase {
+                private val focusRequester = FocusRequester()
+                private var shouldAddNode by mutableStateOf(false)
+
+                @Composable
+                override fun MeasuredContent() {
+                    Box(Modifier.thenIf(shouldAddNode) { focusTargetModifierChain() }) {
+                        Box(focusTargetModifierChain())
+                    }
+                }
+
+                @Composable
+                override fun ContentWrappers(content: @Composable () -> Unit) {
+                    Box(focusTargetModifierChain()) {
+                        Column {
+                            content()
+                            Box(Modifier.focusRequester(focusRequester).focusTarget())
+                            LaunchedEffect(Unit) { focusRequester.requestFocus() }
+                        }
+                    }
+                }
+
+                override fun toggleState() {
+                    shouldAddNode = !shouldAddNode
+                }
+
+                private fun focusTargetModifierChain() = repeatModifier(100, Modifier::focusTarget)
+            }
+        })
+    }
+
+    @Test
     fun focusTarget() {
         composeBenchmarkRule.benchmarkToFirstPixel {
             object : LayeredComposeTestCase() {
@@ -46,4 +91,55 @@
             }
         }
     }
+
+    @Test
+    fun reuseInactiveFocusTarget() {
+        composeBenchmarkRule.toggleStateBenchmarkRecompose({
+            object : LayeredComposeTestCase(), ToggleableTestCase {
+
+                private var reuseKey by mutableStateOf(0)
+
+                @Composable
+                override fun MeasuredContent() {
+                    ReusableContent(reuseKey) { Box(Modifier.focusTarget()) }
+                }
+
+                override fun toggleState() {
+                    reuseKey++
+                }
+            }
+        })
+    }
+
+    @Test
+    fun reuseInactiveFocusTarget_insideActiveParent() {
+        composeBenchmarkRule.toggleStateBenchmarkRecompose({
+            object : LayeredComposeTestCase(), ToggleableTestCase {
+
+                private val focusRequester = FocusRequester()
+                private var reuseKey by mutableStateOf(0)
+
+                @Composable
+                override fun MeasuredContent() {
+                    ReusableContent(reuseKey) { Box(Modifier.focusTarget()) }
+                }
+
+                @Composable
+                override fun ContentWrappers(content: @Composable () -> Unit) {
+                    Box(Modifier.focusRequester(focusRequester).focusTarget()) {
+                        LaunchedEffect(Unit) { focusRequester.requestFocus() }
+                        content()
+                    }
+                }
+
+                override fun toggleState() {
+                    reuseKey++
+                }
+            }
+        })
+    }
+
+    private inline fun Modifier.thenIf(condition: Boolean, block: () -> Modifier): Modifier {
+        return if (condition) then(block()) else this
+    }
 }
diff --git a/compose/ui/ui/build.gradle b/compose/ui/ui/build.gradle
index 7659997..d2d517a 100644
--- a/compose/ui/ui/build.gradle
+++ b/compose/ui/ui/build.gradle
@@ -94,7 +94,7 @@
                 implementation('androidx.collection:collection:1.0.0')
                 implementation("androidx.customview:customview-poolingcontainer:1.0.0")
                 implementation("androidx.savedstate:savedstate-ktx:1.2.1")
-                api("androidx.lifecycle:lifecycle-runtime-compose:2.8.2")
+                api("androidx.lifecycle:lifecycle-runtime-compose:2.8.3")
                 implementation("androidx.lifecycle:lifecycle-viewmodel:2.6.1")
                 implementation("androidx.emoji2:emoji2:1.2.0")
 
@@ -104,13 +104,13 @@
                 // converting `lifecycle-runtime-compose` to KMP triggered a Gradle bug. Adding
                 // the `livedata` dependency directly works around the issue.
                 // See https://github.com/gradle/gradle/issues/14220 for details.
-                compileOnly("androidx.lifecycle:lifecycle-livedata-core:2.8.2")
+                compileOnly("androidx.lifecycle:lifecycle-livedata-core:2.8.3")
 
                 // `compose-ui` has a transitive dependency on `lifecycle-viewmodel-savedstate`, and
                 // converting `lifecycle-runtime-compose` to KMP triggered a Gradle bug. Adding
                 // the `lifecycle-viewmodel-savedstate` dependency directly works around the issue.
                 // See https://github.com/gradle/gradle/issues/14220 for details.
-                compileOnly("androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.2")
+                compileOnly("androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.3")
             }
         }
 
@@ -123,14 +123,7 @@
             }
         }
 
-        jvmTest {
-            dependsOn(commonTest)
-            dependencies {
-            }
-        }
-
         androidInstrumentedTest {
-            dependsOn(jvmTest)
             dependencies {
                 implementation("androidx.fragment:fragment:1.3.0")
                 implementation("androidx.appcompat:appcompat:1.3.0")
@@ -166,7 +159,6 @@
         }
 
         androidUnitTest {
-            dependsOn(jvmTest)
             dependencies {
                 implementation(libs.testRules)
                 implementation(libs.testRunner)
@@ -183,19 +175,6 @@
                 implementation(project(":compose:test-utils"))
             }
         }
-
-        desktopTest {
-            dependsOn(jvmTest)
-            dependencies {
-                implementation(libs.truth)
-                implementation(libs.junit)
-                implementation(libs.mockitoCore)
-                implementation(libs.mockitoKotlin)
-                implementation(libs.skikoCurrentOs)
-                implementation(project(":compose:material:material"))
-                implementation(project(":compose:ui:ui-test-junit4"))
-            }
-        }
     }
 }
 
@@ -233,14 +212,6 @@
     samples(project(":compose:ui:ui:ui-samples"))
 }
 
-if (KmpPlatformsKt.enableDesktop(project)) {
-    tasks.withType(Test).configureEach {
-        if (name.equals("desktopTest")) {
-            systemProperties["GOLDEN_PATH"] = project.rootDir.absolutePath + "/../../golden"
-        }
-    }
-}
-
 android {
     testOptions.unitTests.includeAndroidResources = true
     buildTypes.configureEach {
diff --git a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/UiDemos.kt b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/UiDemos.kt
index a2d8987..7ade151 100644
--- a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/UiDemos.kt
+++ b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/UiDemos.kt
@@ -66,6 +66,8 @@
 import androidx.compose.ui.demos.gestures.NestedScrollDispatchDemo
 import androidx.compose.ui.demos.gestures.NestedScrollingDemo
 import androidx.compose.ui.demos.gestures.PointerInputDuringSubComp
+import androidx.compose.ui.demos.gestures.PointerInputLambdaExecutions
+import androidx.compose.ui.demos.gestures.PointerInputLambdaExecutionsUsingExternalFunctions
 import androidx.compose.ui.demos.gestures.PopupDragDemo
 import androidx.compose.ui.demos.gestures.PressIndicatorGestureFilterDemo
 import androidx.compose.ui.demos.gestures.RawDragGestureFilterDemo
@@ -143,7 +145,11 @@
                     ComposableDemo("Popup Drag") { PopupDragDemo() },
                     ComposableDemo("Double Tap in Tap") { DoubleTapInTapDemo() },
                     ComposableDemo("Nested Long Press") { NestedLongPressDemo() },
-                    ComposableDemo("Pointer Input During Sub Comp") { PointerInputDuringSubComp() }
+                    ComposableDemo("Pointer Input During Sub Comp") { PointerInputDuringSubComp() },
+                    ComposableDemo("Pointer Input Lambda Stats") { PointerInputLambdaExecutions() },
+                    ComposableDemo("Pointer Input Lambda Stats w/ external function") {
+                        PointerInputLambdaExecutionsUsingExternalFunctions()
+                    }
                 )
             ),
             DemoCategory(
diff --git a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/focus/LazyListChildFocusDemos.kt b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/focus/LazyListChildFocusDemos.kt
index a98009f..ad4e177 100644
--- a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/focus/LazyListChildFocusDemos.kt
+++ b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/focus/LazyListChildFocusDemos.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.ui.demos.focus
 
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.border
 import androidx.compose.foundation.focusable
 import androidx.compose.foundation.layout.Box
@@ -46,6 +47,7 @@
 import androidx.compose.ui.unit.dp
 import kotlinx.coroutines.launch
 
+@OptIn(ExperimentalFoundationApi::class)
 @Preview(widthDp = 200, heightDp = 400)
 @Composable
 fun LazyListChildFocusDemos() {
diff --git a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/gestures/PointerInputLambdaExecutions.kt b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/gestures/PointerInputLambdaExecutions.kt
new file mode 100644
index 0000000..025e442
--- /dev/null
+++ b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/gestures/PointerInputLambdaExecutions.kt
@@ -0,0 +1,235 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.ui.demos.gestures
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.material.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.input.pointer.PointerEventType
+import androidx.compose.ui.input.pointer.PointerInputEventHandler
+import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.dp
+
+/** Shows how underlying lambdas are executed. */
+@Composable
+fun PointerInputLambdaExecutions() {
+
+    var topBoxText by remember { mutableStateOf("Click button to see details") }
+    var firstPointerInputLambdaExecutionCount by remember { mutableIntStateOf(0) }
+    var firstPointerInputPressCounter by remember { mutableIntStateOf(0) }
+    var firstPointerInputMoveCounter by remember { mutableIntStateOf(0) }
+    var firstPointerInputReleaseCounter by remember { mutableIntStateOf(0) }
+
+    var bottomBoxText by remember { mutableStateOf("Click button to see details") }
+    var secondPointerInputLambdaExecutionCount by remember { mutableIntStateOf(0) }
+    var secondPointerInputPressCounter by remember { mutableIntStateOf(0) }
+    var secondPointerInputMoveCounter by remember { mutableIntStateOf(0) }
+    var secondPointerInputReleaseCounter by remember { mutableIntStateOf(0) }
+
+    Column(modifier = Modifier.fillMaxSize().padding(8.dp)) {
+        Text(
+            modifier = Modifier.fillMaxWidth().weight(1f),
+            textAlign = TextAlign.Center,
+            text = "See how underlying lambdas are executed"
+        )
+
+        Column(modifier = Modifier.fillMaxSize().background(Color.LightGray).padding(8.dp)) {
+            Text(
+                modifier =
+                    Modifier.size(400.dp).background(Color.Green).weight(1f).pointerInput(Unit) {
+                        firstPointerInputLambdaExecutionCount++
+                        awaitPointerEventScope {
+                            while (true) {
+                                val event = awaitPointerEvent()
+                                when (event.type) {
+                                    PointerEventType.Press -> {
+                                        firstPointerInputPressCounter++
+                                    }
+                                    PointerEventType.Move -> {
+                                        firstPointerInputMoveCounter++
+                                    }
+                                    PointerEventType.Release -> {
+                                        firstPointerInputReleaseCounter++
+                                    }
+                                }
+                                topBoxText =
+                                    "Lambda Execution: $firstPointerInputLambdaExecutionCount,\n" +
+                                        "Press: $firstPointerInputPressCounter,\n" +
+                                        "Move: $firstPointerInputMoveCounter,\n" +
+                                        "Release: $firstPointerInputReleaseCounter"
+                            }
+                        }
+                    },
+                textAlign = TextAlign.Center,
+                text = topBoxText
+            )
+
+            Text(
+                modifier =
+                    Modifier.size(400.dp).background(Color.Red).weight(1f).pointerInput(Unit) {
+                        secondPointerInputLambdaExecutionCount++
+                        awaitPointerEventScope {
+                            while (true) {
+                                val event = awaitPointerEvent()
+                                when (event.type) {
+                                    PointerEventType.Press -> {
+                                        secondPointerInputPressCounter++
+                                    }
+                                    PointerEventType.Move -> {
+                                        secondPointerInputMoveCounter++
+                                    }
+                                    PointerEventType.Release -> {
+                                        secondPointerInputReleaseCounter++
+                                    }
+                                }
+                                bottomBoxText =
+                                    "Lambda Execution: $secondPointerInputLambdaExecutionCount,\n" +
+                                        "Press: $secondPointerInputPressCounter,\n" +
+                                        "Move: $secondPointerInputMoveCounter,\n" +
+                                        "Release: $secondPointerInputReleaseCounter"
+                            }
+                        }
+                    },
+                textAlign = TextAlign.Center,
+                text = bottomBoxText
+            )
+        }
+    }
+}
+
+/**
+ * Shows how underlying lambdas are executed but instead of passing the lambdas directly, we call a
+ * separate external function to return the PointerInputEventHandler.
+ */
+@Composable
+fun PointerInputLambdaExecutionsUsingExternalFunctions() {
+
+    var topBoxText by remember { mutableStateOf("Click button to see details") }
+    var firstPointerInputLambdaExecutionCount by remember { mutableIntStateOf(0) }
+    var firstPointerInputPressCounter by remember { mutableIntStateOf(0) }
+    var firstPointerInputMoveCounter by remember { mutableIntStateOf(0) }
+    var firstPointerInputReleaseCounter by remember { mutableIntStateOf(0) }
+
+    var bottomBoxText by remember { mutableStateOf("Click button to see details") }
+    var secondPointerInputLambdaExecutionCount by remember { mutableIntStateOf(0) }
+    var secondPointerInputPressCounter by remember { mutableIntStateOf(0) }
+    var secondPointerInputMoveCounter by remember { mutableIntStateOf(0) }
+    var secondPointerInputReleaseCounter by remember { mutableIntStateOf(0) }
+
+    Column(modifier = Modifier.fillMaxSize().padding(8.dp)) {
+        Text(
+            modifier = Modifier.fillMaxWidth().weight(1f),
+            textAlign = TextAlign.Center,
+            text = "See how underlying lambdas are executed"
+        )
+
+        Column(modifier = Modifier.fillMaxSize().background(Color.LightGray).padding(8.dp)) {
+            Text(
+                modifier =
+                    Modifier.size(400.dp)
+                        .background(Color.Green)
+                        .weight(1f)
+                        .pointerInput(
+                            Unit,
+                            createPointerInputEventHandlerReturnTypeInterface {
+                                firstPointerInputLambdaExecutionCount++
+                                awaitPointerEventScope {
+                                    while (true) {
+                                        val event = awaitPointerEvent()
+                                        when (event.type) {
+                                            PointerEventType.Press -> {
+                                                firstPointerInputPressCounter++
+                                            }
+                                            PointerEventType.Move -> {
+                                                firstPointerInputMoveCounter++
+                                            }
+                                            PointerEventType.Release -> {
+                                                firstPointerInputReleaseCounter++
+                                            }
+                                        }
+                                        topBoxText =
+                                            "Lambda Execution: $firstPointerInputLambdaExecutionCount,\n" +
+                                                "Press: $firstPointerInputPressCounter,\n" +
+                                                "Move: $firstPointerInputMoveCounter,\n" +
+                                                "Release: $firstPointerInputReleaseCounter"
+                                    }
+                                }
+                            }
+                        ),
+                textAlign = TextAlign.Center,
+                text = topBoxText
+            )
+
+            Text(
+                modifier =
+                    Modifier.size(400.dp)
+                        .background(Color.Red)
+                        .weight(1f)
+                        .pointerInput(
+                            Unit,
+                            createPointerInputEventHandlerReturnTypeInterface {
+                                secondPointerInputLambdaExecutionCount++
+                                awaitPointerEventScope {
+                                    while (true) {
+                                        val event = awaitPointerEvent()
+                                        when (event.type) {
+                                            PointerEventType.Press -> {
+                                                secondPointerInputPressCounter++
+                                            }
+                                            PointerEventType.Move -> {
+                                                secondPointerInputMoveCounter++
+                                            }
+                                            PointerEventType.Release -> {
+                                                secondPointerInputReleaseCounter++
+                                            }
+                                        }
+                                        bottomBoxText =
+                                            "Lambda Execution: $secondPointerInputLambdaExecutionCount,\n" +
+                                                "Press: $secondPointerInputPressCounter,\n" +
+                                                "Move: $secondPointerInputMoveCounter,\n" +
+                                                "Release: $secondPointerInputReleaseCounter"
+                                    }
+                                }
+                            }
+                        ),
+                textAlign = TextAlign.Center,
+                text = bottomBoxText
+            )
+        }
+    }
+}
+
+// The return type (PointerInputEventHandler) is actually an interface, so Kotlin will create class
+// type based on calling location/order.
+private fun createPointerInputEventHandlerReturnTypeInterface(
+    lambda: PointerInputEventHandler
+): PointerInputEventHandler {
+    return lambda
+}
diff --git a/compose/ui/ui/proguard-rules.pro b/compose/ui/ui/proguard-rules.pro
index fd62154..29f2984 100644
--- a/compose/ui/ui/proguard-rules.pro
+++ b/compose/ui/ui/proguard-rules.pro
@@ -40,3 +40,10 @@
     # For methods returning Nothing
     static java.lang.Void throw*Exception(...);
 }
+
+# When pointer input modifier nodes are added dynamically and have the same keys (common when
+# developers `Unit` for their keys), we need a way to differentiate them and using a
+# functional interface and comparing classes allows us to do that.
+-keepnames class androidx.compose.ui.input.pointer.PointerInputEventHandler {
+    *;
+}
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/AndroidAccessibilityTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/AndroidAccessibilityTest.kt
index f14d476..7a2f9bc95 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/AndroidAccessibilityTest.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/AndroidAccessibilityTest.kt
@@ -565,6 +565,21 @@
     }
 
     @Test
+    fun testCreateAccessibilityNodeInfo_numberPicker_expectedClassName() {
+        // Arrange.
+        setContent { Box(Modifier.semantics { role = Role.NumberPicker }.testTag(tag)) }
+        val virtualId = rule.onNodeWithTag(tag).semanticsId
+
+        // Act.
+        val info = rule.runOnIdle { createAccessibilityNodeInfo(virtualId) }
+
+        // Assert.
+        rule.runOnIdle {
+            with(info) { assertThat(className).isEqualTo("android.widget.NumberPicker") }
+        }
+    }
+
+    @Test
     fun testCreateAccessibilityNodeInfo_progressIndicator_determinate() {
         // Arrange.
         setContent { Box(Modifier.progressSemantics(0.5f).testTag(tag)) { BasicText("Text") } }
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/AndroidAssistTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/AndroidAssistTest.kt
index 2d08cc5..7420f15 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/AndroidAssistTest.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/AndroidAssistTest.kt
@@ -40,11 +40,11 @@
     private val contentTag = "content_tag"
     private val accessibilityClassName = "android.view.ViewGroup"
 
-    // Test that the assistStructure only has its classname set on API levels 26 and 27. See
-    // b/251152083 for more information.
+    // Test that the assistStructure only has its classname set on API levels 23 to 27. See
+    // b/251152083 and b/320768586 for more information.
     @Test
     @SmallTest
-    @SdkSuppress(minSdkVersion = 26, maxSdkVersion = 27)
+    @SdkSuppress(minSdkVersion = 23, maxSdkVersion = 27)
     fun verifyAssistStructureSet() {
         val viewStructure: ViewStructure = FakeViewStructure()
 
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/autofill/FakeViewStructure.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/autofill/FakeViewStructure.kt
index 0a70dd6..73b2b54 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/autofill/FakeViewStructure.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/autofill/FakeViewStructure.kt
@@ -46,7 +46,7 @@
  * @param autofillHints The autofill hint. If this value not specified, we use heuristics to
  *   determine what data to use while performing autofill.
  */
-@RequiresApi(Build.VERSION_CODES.O)
+@RequiresApi(Build.VERSION_CODES.M)
 internal data class FakeViewStructure(
     var virtualId: Int = 0,
     var packageName: String? = null,
@@ -54,7 +54,8 @@
     var entryName: String? = null,
     var children: MutableList<FakeViewStructure> = mutableListOf(),
     var bounds: Rect? = null,
-    private val autofillId: AutofillId? = generateAutofillId(),
+    private val autofillId: AutofillId? =
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) generateAutofillId() else null,
     internal var autofillType: Int = View.AUTOFILL_TYPE_NONE,
     internal var autofillHints: Array<out String> = arrayOf()
 ) : ViewStructure() {
@@ -92,6 +93,9 @@
         @GuardedBy("this") private var previousId = 0
         private val NO_SESSION = 0
 
+        // Android API level 26 introduced Autofill. Prior to API level 26, no autofill ID will be
+        // provided.
+        @RequiresApi(Build.VERSION_CODES.O)
         @Synchronized
         private fun generateAutofillId(): AutofillId {
             var autofillId: AutofillId? = null
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/draw/DrawModifierTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/draw/DrawModifierTest.kt
index 39e6b37..f58c9ee 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/draw/DrawModifierTest.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/draw/DrawModifierTest.kt
@@ -91,6 +91,7 @@
 import org.junit.Assert.assertNotNull
 import org.junit.Assert.assertTrue
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -130,6 +131,7 @@
         assertTrue(graphicsLayer!!.isReleased)
     }
 
+    @Ignore
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
     @Test
     fun testGraphicsLayerRecordAfterPersisted() {
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/focus/FocusTargetAttachDetachTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/focus/FocusTargetAttachDetachTest.kt
index 1ce4a09..9d66b02 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/focus/FocusTargetAttachDetachTest.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/focus/FocusTargetAttachDetachTest.kt
@@ -18,10 +18,13 @@
 
 import android.os.Build.VERSION.SDK_INT
 import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.focus.FocusStateImpl.ActiveParent
+import androidx.compose.ui.focus.FocusStateImpl.Inactive
 import androidx.compose.ui.input.InputMode
 import androidx.compose.ui.input.InputModeManager
 import androidx.compose.ui.input.key.Key
@@ -647,15 +650,75 @@
     }
 
     @Test
+    fun addedFocusTarget_withinInactiveNode() {
+        // Arrange.
+        val focusTarget1 = FocusTargetNode()
+        val focusTarget2 = FocusTargetNode()
+        var addFocusTarget2 by mutableStateOf(false)
+        rule.setFocusableContent {
+            Box(
+                Modifier.then(elementFor(instance = focusTarget1)).thenIf(addFocusTarget2) {
+                    elementFor(instance = focusTarget2)
+                }
+            )
+        }
+
+        // Act.
+        rule.runOnIdle { addFocusTarget2 = true }
+
+        // Assert.
+        rule.runOnIdle {
+            assertThat(focusTarget1.isInitialized()).isTrue()
+            assertThat(focusTarget1.focusState).isEqualTo(Inactive)
+            assertThat(focusTarget2.isInitialized()).isTrue()
+            assertThat(focusTarget2.focusState).isEqualTo(Inactive)
+        }
+    }
+
+    @Test
+    fun addedMultipleFocusTargets_withinInactiveHierarchy() {
+        // Arrange.
+        val focusTarget1 = FocusTargetNode()
+        val focusTarget2 = FocusTargetNode()
+        val focusTarget3 = FocusTargetNode()
+        var addFocusTarget2 by mutableStateOf(false)
+        var addFocusTarget3 by mutableStateOf(false)
+        rule.setFocusableContent {
+            Column(Modifier.then(elementFor(instance = focusTarget1))) {
+                if (addFocusTarget2) Box(Modifier.then(elementFor(instance = focusTarget2)))
+                if (addFocusTarget3) Box(Modifier.then(elementFor(instance = focusTarget3)))
+            }
+        }
+
+        // Act.
+        rule.runOnIdle {
+            addFocusTarget2 = true
+            addFocusTarget3 = true
+        }
+
+        // Assert.
+        rule.runOnIdle {
+            assertThat(focusTarget1.isInitialized()).isTrue()
+            assertThat(focusTarget1.focusState).isEqualTo(Inactive)
+            assertThat(focusTarget2.isInitialized()).isTrue()
+            assertThat(focusTarget2.focusState).isEqualTo(Inactive)
+            assertThat(focusTarget3.isInitialized()).isTrue()
+            assertThat(focusTarget3.focusState).isEqualTo(Inactive)
+        }
+    }
+
+    @Test
     fun addedFocusTarget_withinActiveNode() {
         // Arrange.
+        val focusTarget = FocusTargetNode()
         lateinit var focusState: FocusState
         val focusRequester = FocusRequester()
         var addFocusTarget by mutableStateOf(false)
         rule.setFocusableContent {
             Box(
                 Modifier.thenIf(addFocusTarget) {
-                        Modifier.onFocusChanged { focusState = it }.focusTarget()
+                        Modifier.onFocusChanged { focusState = it }
+                            .then(elementFor(instance = focusTarget))
                     }
                     .focusRequester(focusRequester)
                     .focusTarget()
@@ -667,19 +730,25 @@
         rule.runOnIdle { addFocusTarget = true }
 
         // Assert.
-        rule.runOnIdle { assertThat(focusState).isEqualTo(FocusStateImpl.ActiveParent) }
+        rule.runOnIdle {
+            assertThat(focusTarget.isInitialized()).isTrue()
+            assertThat(focusTarget.focusState).isEqualTo(ActiveParent)
+            assertThat(focusState).isEqualTo(ActiveParent)
+        }
     }
 
     @Test
     fun addedFocusTarget_withinActiveHierarchy() {
         // Arrange.
+        val focusTarget = FocusTargetNode()
         lateinit var focusState: FocusState
         val focusRequester = FocusRequester()
         var addFocusTarget by mutableStateOf(false)
         rule.setFocusableContent {
             Box(
                 Modifier.thenIf(addFocusTarget) {
-                    Modifier.onFocusChanged { focusState = it }.focusTarget()
+                    Modifier.onFocusChanged { focusState = it }
+                        .then(elementFor(instance = focusTarget))
                 }
             ) {
                 Box(Modifier.focusRequester(focusRequester).focusTarget())
@@ -691,7 +760,11 @@
         rule.runOnIdle { addFocusTarget = true }
 
         // Assert.
-        rule.runOnIdle { assertThat(focusState).isEqualTo(FocusStateImpl.ActiveParent) }
+        rule.runOnIdle {
+            assertThat(focusTarget.isInitialized()).isTrue()
+            assertThat(focusTarget.focusState).isEqualTo(ActiveParent)
+            assertThat(focusState).isEqualTo(ActiveParent)
+        }
     }
 
     @Test
@@ -724,8 +797,8 @@
 
         // Assert.
         rule.runOnIdle {
-            assertThat(focusState1).isEqualTo(FocusStateImpl.ActiveParent)
-            assertThat(focusState2).isEqualTo(FocusStateImpl.ActiveParent)
+            assertThat(focusState1).isEqualTo(ActiveParent)
+            assertThat(focusState2).isEqualTo(ActiveParent)
         }
     }
 
@@ -762,8 +835,8 @@
 
         // Assert.
         rule.runOnIdle {
-            assertThat(focusState1).isEqualTo(FocusStateImpl.ActiveParent)
-            assertThat(focusState2).isEqualTo(FocusStateImpl.ActiveParent)
+            assertThat(focusState1).isEqualTo(ActiveParent)
+            assertThat(focusState2).isEqualTo(ActiveParent)
         }
     }
 
@@ -791,7 +864,7 @@
         rule.runOnIdle { addFocusTarget = true }
 
         // Assert.
-        rule.runOnIdle { assertThat(focusState).isEqualTo(FocusStateImpl.ActiveParent) }
+        rule.runOnIdle { assertThat(focusState).isEqualTo(ActiveParent) }
     }
 
     @Test
@@ -818,7 +891,7 @@
         rule.runOnIdle { addFocusTarget = true }
 
         // Assert.
-        rule.runOnIdle { assertThat(focusState).isEqualTo(FocusStateImpl.ActiveParent) }
+        rule.runOnIdle { assertThat(focusState).isEqualTo(ActiveParent) }
     }
 
     @Test
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/AndroidPointerInputTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/AndroidPointerInputTest.kt
index 99bdb0d..fa6a985 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/AndroidPointerInputTest.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/AndroidPointerInputTest.kt
@@ -2693,25 +2693,8 @@
     }
 
     /*
-     * Tests TOUCH events are triggered incorrectly when dynamically adding a pointer input modifier
-     * (which uses Unit for its key [bad]) ABOVE an existing pointer input modifier. This is more
-     * of an "education test" for developers to see how things can go wrong if you use "Unit" for
-     * your key in pointer input and pointer input modifiers are later added dynamically.
-     *
-     * Note: Even though we are dynamically adding a new pointer input modifier above the existing
-     * pointer input modifier, Compose actually reuses the existing pointer input modifier to
-     * contain the new pointer input modifier. It then adds a new pointer input modifier below that
-     * one and copies in the original (non-dynamic) pointer input modifier into that. However, in
-     * this case, because we are using the "Unit" for both keys, Compose thinks they are the same
-     * pointer input modifier, so it never replaces the existing lambda with the dynamic pointer
-     * input modifier node's lambda. This is why you should not use Unit for your key.
-     *
-     * Why can't the lambdas passed into pointer input be compared? We can't memoize them because
-     * they are outside of a Compose scope (defined in a Modifier extension function), so
-     * developers need to pass a unique key(s) as a way to let us know when to update the lambda.
-     * You can do that with a unique key for each pointer input modifier and/or take it a step
-     * further and use captured values in the lambda as keys (ones that change lambda
-     * behavior).
+     * Tests TOUCH events are triggered correctly when dynamically adding a pointer input modifier
+     * (which uses Unit for its key) ABOVE an existing pointer input modifier.
      *
      * Specific events:
      *  1. UI Element (modifier 1 only): PRESS (touch)
@@ -2723,7 +2706,7 @@
      *  7. UI Element (modifier 1 and 2): RELEASE (touch)
      */
     @Test
-    fun dynamicInputModifierWithUnitKey_addsAboveExistingModifier_failsToTriggerNewModifier() {
+    fun dynamicInputModifierWithUnitKey_addsAboveExistingModifier_triggersBothModifiers() {
         // --> Arrange
         var box1LayoutCoordinates: LayoutCoordinates? = null
 
@@ -2907,20 +2890,16 @@
             // executed again to allow devs to reset their gesture detectors for the new Modifier
             // chain changes.
             assertThat(originalPointerInputScopeExecutionCount).isEqualTo(2)
-            // The dynamic one has been added, so we execute its thing as well.
-            assertThat(dynamicPointerInputScopeExecutionCount).isEqualTo(0)
+            // The dynamic one has been added, so we execute its lambda as well.
+            assertThat(dynamicPointerInputScopeExecutionCount).isEqualTo(1)
 
             // Verify Box 1 existing modifier events
-            // This is 2 because the dynamic modifier added before the existing one, is using Unit
-            // for the key, so the comparison shows that it doesn't need to update the lambda...
-            // Thus, it uses the old lambda (why it is very important you don't use Unit for your
-            // key.
-            assertThat(preexistingModifierPress).isEqualTo(3)
+            assertThat(preexistingModifierPress).isEqualTo(2)
             assertThat(preexistingModifierMove).isEqualTo(1)
             assertThat(preexistingModifierRelease).isEqualTo(1)
 
             // Verify Box 1 dynamically added modifier events
-            assertThat(dynamicModifierPress).isEqualTo(0)
+            assertThat(dynamicModifierPress).isEqualTo(1)
             assertThat(dynamicModifierMove).isEqualTo(0)
             assertThat(dynamicModifierRelease).isEqualTo(0)
 
@@ -2936,16 +2915,16 @@
         )
         rule.runOnUiThread {
             assertThat(originalPointerInputScopeExecutionCount).isEqualTo(2)
-            assertThat(dynamicPointerInputScopeExecutionCount).isEqualTo(0)
+            assertThat(dynamicPointerInputScopeExecutionCount).isEqualTo(1)
 
             // Verify Box 1 existing modifier events
-            assertThat(preexistingModifierPress).isEqualTo(3)
-            assertThat(preexistingModifierMove).isEqualTo(3)
+            assertThat(preexistingModifierPress).isEqualTo(2)
+            assertThat(preexistingModifierMove).isEqualTo(2)
             assertThat(preexistingModifierRelease).isEqualTo(1)
 
             // Verify Box 1 dynamically added modifier events
-            assertThat(dynamicModifierPress).isEqualTo(0)
-            assertThat(dynamicModifierMove).isEqualTo(0)
+            assertThat(dynamicModifierPress).isEqualTo(1)
+            assertThat(dynamicModifierMove).isEqualTo(1)
             assertThat(dynamicModifierRelease).isEqualTo(0)
 
             assertThat(pointerEvent).isNotNull()
@@ -2960,17 +2939,17 @@
         )
         rule.runOnUiThread {
             assertThat(originalPointerInputScopeExecutionCount).isEqualTo(2)
-            assertThat(dynamicPointerInputScopeExecutionCount).isEqualTo(0)
+            assertThat(dynamicPointerInputScopeExecutionCount).isEqualTo(1)
 
             // Verify Box 1 existing modifier events
-            assertThat(preexistingModifierPress).isEqualTo(3)
-            assertThat(preexistingModifierMove).isEqualTo(3)
-            assertThat(preexistingModifierRelease).isEqualTo(3)
+            assertThat(preexistingModifierPress).isEqualTo(2)
+            assertThat(preexistingModifierMove).isEqualTo(2)
+            assertThat(preexistingModifierRelease).isEqualTo(2)
 
             // Verify Box 1 dynamically added modifier events
-            assertThat(dynamicModifierPress).isEqualTo(0)
-            assertThat(dynamicModifierMove).isEqualTo(0)
-            assertThat(dynamicModifierRelease).isEqualTo(0)
+            assertThat(dynamicModifierPress).isEqualTo(1)
+            assertThat(dynamicModifierMove).isEqualTo(1)
+            assertThat(dynamicModifierRelease).isEqualTo(1)
 
             assertThat(pointerEvent).isNotNull()
             assertThat(eventsThatShouldNotTrigger).isFalse()
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/HitPathTrackerTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/HitPathTrackerTest.kt
index 13dd9a6..6f7d4a3 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/HitPathTrackerTest.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/HitPathTrackerTest.kt
@@ -3388,7 +3388,8 @@
     override fun createLayer(
         drawBlock: (Canvas, GraphicsLayer?) -> Unit,
         invalidateParentLayer: () -> Unit,
-        explicitLayer: GraphicsLayer?
+        explicitLayer: GraphicsLayer?,
+        forceUseOldLayers: Boolean
     ): OwnedLayer {
         return object : OwnedLayer {
             override fun updateLayerProperties(scope: ReusableGraphicsLayerScope) {}
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/PointerInputEventProcessorTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/PointerInputEventProcessorTest.kt
index 71465b6..8853994 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/PointerInputEventProcessorTest.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/PointerInputEventProcessorTest.kt
@@ -2986,7 +2986,8 @@
     override fun createLayer(
         drawBlock: (Canvas, GraphicsLayer?) -> Unit,
         invalidateParentLayer: () -> Unit,
-        explicitLayer: GraphicsLayer?
+        explicitLayer: GraphicsLayer?,
+        forceUseOldLayers: Boolean
     ): OwnedLayer {
         TODO("Not yet implemented")
     }
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilterTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilterTest.kt
index 2a6af69..be8afd9 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilterTest.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilterTest.kt
@@ -20,9 +20,11 @@
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.size
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.MutableState
 import androidx.compose.runtime.ReusableContent
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberUpdatedState
 import androidx.compose.runtime.setValue
 import androidx.compose.testutils.assertModifierIsPure
@@ -729,9 +731,9 @@
         isDebugInspectorInfoEnabled = true
 
         rule.setContent {
-            val pointerInputHandler: suspend PointerInputScope.() -> Unit = {}
+            val pointerInputEventHandler = PointerInputEventHandler {}
             val modifier =
-                Modifier.pointerInput(Unit, pointerInputHandler) as SuspendPointerInputElement
+                Modifier.pointerInput(Unit, pointerInputEventHandler) as SuspendPointerInputElement
 
             assertThat(modifier.nameFallback).isEqualTo("pointerInput")
             assertThat(modifier.valueOverride).isNull()
@@ -740,7 +742,7 @@
                     ValueElement("key1", Unit),
                     ValueElement("key2", null),
                     ValueElement("keys", null),
-                    ValueElement("pointerInputHandler", pointerInputHandler)
+                    ValueElement("pointerInputEventHandler", pointerInputEventHandler)
                 )
         }
     }
@@ -748,7 +750,7 @@
     @Test
     @SmallTest
     fun testEquality_key() {
-        val block: suspend PointerInputScope.() -> Unit = {}
+        val block = PointerInputEventHandler {}
 
         assertModifierIsPure { toggleInput -> Modifier.pointerInput(toggleInput, block = block) }
     }
@@ -756,8 +758,8 @@
     @Test
     @SmallTest
     fun testEquality_block() {
-        val block1: suspend PointerInputScope.() -> Unit = {}
-        val block2: suspend PointerInputScope.() -> Unit = {}
+        val block1 = PointerInputEventHandler {}
+        val block2 = PointerInputEventHandler {}
 
         assertModifierIsPure { toggleInput ->
             val block = if (toggleInput) block1 else block2
@@ -1154,19 +1156,150 @@
         rule.runOnIdle { assertThat(cancelled).isTrue() }
     }
 
+    // Tests cases where the key does not change (`Unit` in this case), but the lambda (the `block`
+    // parameter) does change. Thus, the previous lambda/block is cancelled (what developers
+    // expect). For tests that bypass this behavior, see
+    // [changePointerInputBlockGeneratedViaExternalFunctionInside_blockNotCancelled].
     @Test
     @MediumTest
-    fun testUpdatingBlockDoesNotRestartPointerInput() {
+    fun testChangePointerInputBlockCancelsPreviousPointerInputBlock() {
         val tag = "box"
         var cancelled = false
-        val lambda1: suspend PointerInputScope.() -> Unit = {
+        // PointerInputEventHandler is an interface, so the class produced is unique to this
+        // call site.
+        val lambda1 = PointerInputEventHandler {
             try {
                 suspendCancellableCoroutine<Unit> {}
             } catch (e: CancellationException) {
                 cancelled = true
             }
         }
-        val lambda2: suspend PointerInputScope.() -> Unit = {}
+        // Same as above, this class will be unique/different from lambda1.
+        val lambda2 = PointerInputEventHandler {}
+        var block by mutableStateOf(lambda1)
+
+        rule.setContent {
+            Box(
+                Modifier.testTag(tag)
+                    .fillMaxSize()
+                    // Because we are using `Unit` for the key (and it doesn't change), the
+                    // class is used as the comparison to cancel and restart the block.
+                    .pointerInput(key1 = Unit, key2 = Unit, block = block)
+            )
+        }
+
+        rule.onNodeWithTag(tag).performClick()
+        rule.runOnIdle { assertThat(cancelled).isFalse() }
+
+        block = lambda2
+        // Because the lambda has changed, the previous block is cancelled.
+        rule.runOnIdle { assertThat(cancelled).isTrue() }
+    }
+
+    // This test is similar to the test above
+    // (`testChangePointerInputBlockCancelsPreviousPointerInputBlock()`), but it uses a custom
+    // function to create the new instances of the functional interfaces (PointerInputEventHandler)
+    // vs. creating them directly. The results are the same, because the custom function takes an
+    // argument of functional interface (meaning a new class is created based on test's call site,
+    // not from a site within the custom function). In the end, it behaves as if we are just
+    // creating an instance of the functional interface directly in the test.
+    @Test
+    @MediumTest
+    fun changePointerInputBlockGeneratedViaExternalFunctionParameter_cancelsPreviousBlock() {
+        val tag = "box"
+        var cancelled = false
+
+        // createPointerInputEventHandlerReturnTypeInterface() takes a PointerInputEventHandler
+        // parameter, so the new class will be created at this call site (unique to lambda2).
+        val lambda1 = createPointerInputEventHandlerReturnTypeInterface {
+            try {
+                suspendCancellableCoroutine<Unit> {}
+            } catch (e: CancellationException) {
+                cancelled = true
+            }
+        }
+        val lambda2 = createPointerInputEventHandlerReturnTypeInterface {}
+        var block by mutableStateOf(lambda1)
+
+        rule.setContent {
+            Box(Modifier.testTag(tag).fillMaxSize().pointerInput(key1 = Unit, block = block))
+        }
+
+        rule.onNodeWithTag(tag).performClick()
+        rule.runOnIdle { assertThat(cancelled).isFalse() }
+
+        block = lambda2
+        rule.runOnIdle { assertThat(cancelled).isTrue() }
+    }
+
+    // The next three tests cover the somewhat rare case of circumventing the behavior of
+    // `.pointerInput()` when `Unit` is used for key(s) and the `block` parameter changes (current
+    // behavior **cancels** the previous `block` and the new `block` executes when a new event
+    // arrives). Circumventing this behavior means the previous `block` won't cancel.
+    //
+    // These tests are to verify the behavior does not change. We do not recommend this approach to
+    // developers (it probably does not make sense to avoid cancelling the previous `block`).
+    //
+    // To bypass the current behavior, each `block` needs to be created from the same class, since
+    // we determine if a block has changed by class type. (Usually, a new class will be created
+    // for each call site when you pass in a trailing lambda to `.pointerInput()`.)
+    //
+    // These tests change the call sites from unique locations to the same location for all `block`
+    // creation (see tests for details).
+
+    // Test 1 of creating the same class type for all `block` parameters.
+    // The block instances are created inside a separate function
+    // ([createPointerInputEventHandlerWithSameClassEverytime()]) and returned to this test (all
+    // instances are of the same class). Since we are not using keys (just `Unit`) and the
+    // classes aren't different, the block will not be cancelled (even though it's changed). See
+    // above for more details.
+    @Test
+    @MediumTest
+    fun changePointerInputBlockGeneratedViaExternalFunctionInside_blockNotCancelled() {
+        val tag = "box"
+        var cancelled = false
+
+        val lambda1 = createPointerInputEventHandlerWithSameClassEverytime {
+            try {
+                suspendCancellableCoroutine<Unit> {}
+            } catch (e: CancellationException) {
+                cancelled = true
+            }
+        }
+        // Both lambda1 and lambda2 will be of the same class type (see fun for details).
+        val lambda2 = createPointerInputEventHandlerWithSameClassEverytime {}
+        var block by mutableStateOf(lambda1)
+
+        rule.setContent {
+            Box(Modifier.testTag(tag).fillMaxSize().pointerInput(key1 = Unit, block = block))
+        }
+
+        rule.onNodeWithTag(tag).performClick()
+        rule.runOnIdle { assertThat(cancelled).isFalse() }
+
+        block = lambda2
+        rule.runOnIdle { assertThat(cancelled).isFalse() }
+    }
+
+    // Test 2 of creating the same class type for all `block` parameters.
+    // The block instances are created all at once inside a separate function
+    // ([createPointerInputHandlersThatCaptureWithCompose()]) and returned to this test (all
+    // instances are of the same class). That function also captures values.
+    // Since we are not using keys (just `Unit`) and the classes aren't different so the block will
+    // not be cancelled (even though it's changed). See above for more details.
+    @Test
+    @MediumTest
+    fun multipleClassesCreatedFromFunInterfaceInSeparateFunctionWithKotlinCapture_classesMatch() {
+        val tag = "box"
+        var cancelled = false
+
+        val (lambda1, lambda2) = createPointerInputHandlersThatCapture { cancelled = true }
+        val (lambda1Copy, lambda2Copy) = createPointerInputHandlersThatCapture { cancelled = true }
+
+        // Classes
+        assertThat(lambda1::class).isEqualTo(lambda1Copy::class)
+        assertThat(lambda2::class).isEqualTo(lambda2Copy::class)
+
         var block by mutableStateOf(lambda1)
 
         rule.setContent {
@@ -1181,9 +1314,99 @@
 
         rule.runOnIdle { assertThat(cancelled).isFalse() }
 
+        // The keys have not changed, BUT the class are different between lambda1 and lambda2, so
+        // it will trigger a cancellation of lambda1.
         block = lambda2
 
+        rule.runOnIdle { assertThat(cancelled).isTrue() }
+
+        // Reset
+        block = lambda1
+        cancelled = false
+
+        rule.onNodeWithTag(tag).performClick()
+
         rule.runOnIdle { assertThat(cancelled).isFalse() }
+
+        // The keys have not changed AND the class between lambda1 and lambda1Copy are the same, so
+        // it will NOT trigger a cancellation.
+        block = lambda1Copy
+        rule.onNodeWithTag(tag).performClick()
+
+        rule.runOnIdle { assertThat(cancelled).isFalse() }
+    }
+
+    // Test 3 of creating the same class type for all `block` parameters.
+    // Same as test 2 above
+    // ([changePointerInputBlockGeneratedViaExternalFunctionInsideMultiple_blockNotCancelled()])
+    // but uses Compose for capture vs. standard Kotlin.
+    @Test
+    @MediumTest
+    fun multipleClassesCreatedFromFunInterfaceInSeparateFunctionWithComposeCapture_classesMatch() {
+        val tag = "box"
+        val cancelled = mutableStateOf(false)
+
+        lateinit var lambda1: PointerInputEventHandler
+        lateinit var lambda2: PointerInputEventHandler
+        lateinit var lambda1Copy: PointerInputEventHandler
+        lateinit var lambda2Copy: PointerInputEventHandler
+
+        // Initialized to empty block
+        var block: PointerInputEventHandler by mutableStateOf(PointerInputEventHandler {})
+
+        rule.setContent {
+            val capturedKey = remember { mutableStateOf("capturedKey") }
+
+            val lambdasResult =
+                createPointerInputHandlersThatCaptureWithCompose(capturedKey) {
+                    cancelled.value = true
+                }
+            val lambdasCopyResult =
+                createPointerInputHandlersThatCaptureWithCompose(capturedKey) {
+                    cancelled.value = true
+                }
+            lambda1 = lambdasResult.first
+            lambda2 = lambdasResult.second
+            lambda1Copy = lambdasCopyResult.first
+            lambda2Copy = lambdasCopyResult.second
+
+            Box(
+                Modifier.testTag(tag)
+                    .fillMaxSize()
+                    .pointerInput(key1 = Unit, key2 = Unit, block = block)
+            )
+        }
+
+        rule.runOnIdle {
+            assertThat(lambda1::class).isEqualTo(lambda1Copy::class)
+            assertThat(lambda2::class).isEqualTo(lambda2Copy::class)
+        }
+
+        block = lambda1
+
+        rule.onNodeWithTag(tag).performClick()
+
+        rule.runOnIdle { assertThat(cancelled.value).isFalse() }
+
+        // The keys have not changed, BUT the class are different between lambda1 and lambda2, so
+        // it will trigger a cancellation of lambda1.
+        block = lambda2
+
+        rule.runOnIdle { assertThat(cancelled.value).isTrue() }
+
+        // Reset
+        block = lambda1
+        cancelled.value = false
+
+        rule.onNodeWithTag(tag).performClick()
+
+        rule.runOnIdle { assertThat(cancelled.value).isFalse() }
+
+        // The keys have not changed AND the class between lambda1 and lambda1Copy are the same, so
+        // it will NOT trigger a cancellation.
+        block = lambda1Copy
+        rule.onNodeWithTag(tag).performClick()
+        rule.runOnIdle { assertThat(cancelled.value).isFalse() }
     }
 
     // Tests pointerInput with bad pointer data
@@ -1308,3 +1531,70 @@
             )
     }
 }
+
+// The return type (PointerInputEventHandler) is actually an interface, so Kotlin will create class
+// type based on calling location/order.
+// NOTE: Because the PointerInputEventHandler is passed as a parameter, the created class will be
+// created at the call site where this function is called, NOT within this function where the
+// parameter is defined! That means you will get a different class for every unique place this
+// function is called (the same way [.pointerInput's] `block` parameter operates).
+private fun createPointerInputEventHandlerReturnTypeInterface(
+    lambda: PointerInputEventHandler
+): PointerInputEventHandler {
+    return lambda
+}
+
+// The return type ([PointerInputEventHandler]) is actually an interface, and because the function
+// creates it inside the method, the call site will always be the same no matter where this
+// function is called externally. Thus, the same class will be used for all instances vs. a new
+// class for each call which is the normal case when using `.pointerInput()`.
+// More details can be found in test functions.
+private fun createPointerInputEventHandlerWithSameClassEverytime(
+    lambda: suspend PointerInputScope.() -> Unit
+): PointerInputEventHandler {
+    return PointerInputEventHandler { with(this) { lambda() } }
+}
+
+// Same as above but creates multiple [PointerInputEventHandler]s and captures.
+private fun createPointerInputHandlersThatCapture(
+    lambda1CancellationLambda: () -> Unit
+): Pair<PointerInputEventHandler, PointerInputEventHandler> {
+    val lambda1 = PointerInputEventHandler {
+        try {
+            suspendCancellableCoroutine<Unit> {}
+        } catch (e: CancellationException) {
+            lambda1CancellationLambda()
+        }
+    }
+
+    val lambda2 = PointerInputEventHandler {}
+
+    return Pair(lambda1, lambda2)
+}
+
+// Same as above but creates multiple [PointerInputEventHandler]s and captures with Compose.
+@Composable
+private fun createPointerInputHandlersThatCaptureWithCompose(
+    key: MutableState<String>,
+    lambda1CancellationLambda: () -> Unit
+): Pair<PointerInputEventHandler, PointerInputEventHandler> {
+
+    var capturedKey by remember { key }
+
+    val lambda1 = PointerInputEventHandler {
+        println("$this")
+        println("\tcapturedKey: $capturedKey")
+        try {
+            suspendCancellableCoroutine<Unit> {}
+        } catch (e: CancellationException) {
+            lambda1CancellationLambda()
+        }
+    }
+
+    val lambda2 = PointerInputEventHandler {
+        println("$this")
+        println("\tcapturedKey: $capturedKey")
+    }
+
+    return Pair(lambda1, lambda2)
+}
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/layout/ComposeViewLayoutTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/layout/ComposeViewLayoutTest.kt
new file mode 100644
index 0000000..4cb23b0
--- /dev/null
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/layout/ComposeViewLayoutTest.kt
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.ui.layout
+
+import android.view.ViewGroup.LayoutParams
+import android.widget.HorizontalScrollView
+import android.widget.ScrollView
+import androidx.activity.ComponentActivity
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxHeight
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.ComposeView
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.junit4.createAndroidComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.onRoot
+import androidx.compose.ui.unit.LayoutDirection
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.viewinterop.AndroidView
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import com.google.common.truth.Truth.assertThat
+import java.util.Locale
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+class ComposeViewLayoutTest {
+    @get:Rule val rule = createAndroidComposeRule<ComponentActivity>()
+
+    @Test
+    fun largeWidth() {
+        var width by mutableStateOf(0)
+        var height by mutableStateOf(0)
+        rule.setContent {
+            AndroidView(
+                factory = { context ->
+                    HorizontalScrollView(context).also { scrollView ->
+                        scrollView.addView(
+                            ComposeView(context).also { view ->
+                                view.setContent {
+                                    with(LocalDensity.current) {
+                                        Box(
+                                            Modifier.fillMaxHeight().width(2000.toDp()).onPlaced {
+                                                coordinates ->
+                                                width = coordinates.size.width
+                                                height = coordinates.size.height
+                                            }
+                                        )
+                                    }
+                                }
+                                view.layoutParams = LayoutParams(1 shl 28, 2000)
+                            }
+                        )
+                    }
+                }
+            )
+        }
+
+        rule.runOnIdle {
+            assertThat(width).isEqualTo(2000)
+            assertThat(height).isEqualTo(2000)
+        }
+    }
+
+    @Test
+    fun largeHeight() {
+        var width by mutableStateOf(0)
+        var height by mutableStateOf(0)
+        rule.setContent {
+            AndroidView(
+                factory = { context ->
+                    ScrollView(context).also { scrollView ->
+                        scrollView.addView(
+                            ComposeView(context).also { view ->
+                                view.setContent {
+                                    with(LocalDensity.current) {
+                                        Box(
+                                            Modifier.fillMaxWidth().height(2000.toDp()).onPlaced {
+                                                coordinates ->
+                                                width = coordinates.size.width
+                                                height = coordinates.size.height
+                                            }
+                                        )
+                                    }
+                                }
+                                view.layoutParams = LayoutParams(2000, 1 shl 28)
+                            }
+                        )
+                    }
+                }
+            )
+        }
+
+        rule.runOnIdle {
+            assertThat(width).isEqualTo(2000)
+            assertThat(height).isEqualTo(2000)
+        }
+    }
+
+    @Test
+    fun rootViewConfiguration() {
+        val tag = "myLayout"
+        rule.setContent { Box(Modifier.size(10.dp).testTag(tag)) }
+        assertThat(rule.onRoot().fetchSemanticsNode().layoutInfo.viewConfiguration)
+            .isSameInstanceAs(
+                rule.onNodeWithTag(tag).fetchSemanticsNode().layoutInfo.viewConfiguration
+            )
+    }
+
+    @Test
+    fun rootLayoutDirectionLtr() {
+        rule.runOnUiThread {
+            val resources = rule.activity.resources
+            val configuration = resources.configuration
+            configuration.setLayoutDirection(Locale.US)
+        }
+        rule.setContent { Box(Modifier.size(10.dp)) }
+        assertThat(rule.onRoot().fetchSemanticsNode().layoutInfo.layoutDirection)
+            .isEqualTo(LayoutDirection.Ltr)
+    }
+
+    @Test
+    fun rootLayoutDirectionRtl() {
+        rule.runOnUiThread {
+            val configuration = rule.activity.resources.configuration
+            configuration.setLayoutDirection(Locale("fa"))
+        }
+        rule.setContent { Box(Modifier.size(10.dp)) }
+        assertThat(rule.onRoot().fetchSemanticsNode().layoutInfo.layoutDirection)
+            .isEqualTo(LayoutDirection.Rtl)
+    }
+}
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/layout/Helpers.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/layout/Helpers.kt
index ed0c79c..afc7901 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/layout/Helpers.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/layout/Helpers.kt
@@ -249,8 +249,9 @@
     override fun createLayer(
         drawBlock: (canvas: Canvas, parentLayer: GraphicsLayer?) -> Unit,
         invalidateParentLayer: () -> Unit,
-        explicitLayer: GraphicsLayer?
-    ) = createLayer()
+        explicitLayer: GraphicsLayer?,
+        forceUseOldLayers: Boolean
+    ): OwnedLayer = createLayer()
 
     override fun requestOnPositionedCallback(layoutNode: LayoutNode) {
         TODO("Not yet implemented")
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/node/NodeChainTester.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/node/NodeChainTester.kt
index 838297d..7825101 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/node/NodeChainTester.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/node/NodeChainTester.kt
@@ -539,7 +539,8 @@
     override fun createLayer(
         drawBlock: (Canvas, GraphicsLayer?) -> Unit,
         invalidateParentLayer: () -> Unit,
-        explicitLayer: GraphicsLayer?
+        explicitLayer: GraphicsLayer?,
+        forceUseOldLayers: Boolean
     ): OwnedLayer {
         val transform = Matrix()
         val inverseTransform = Matrix()
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/scrollcapture/ScrollCaptureIntegrationTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/scrollcapture/ScrollCaptureIntegrationTest.kt
index 4a2f2e5..55bc110 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/scrollcapture/ScrollCaptureIntegrationTest.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/scrollcapture/ScrollCaptureIntegrationTest.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.ui.scrollcapture
 
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.gestures.scrollBy
 import androidx.compose.foundation.horizontalScroll
 import androidx.compose.foundation.layout.Box
@@ -238,6 +239,7 @@
             assertThat(targets.isEmpty())
         }
 
+    @OptIn(ExperimentalFoundationApi::class)
     @Test
     fun capture_LazyColumn_stickyHeadersDisabled_byLayout() =
         captureTester.runTest {
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/text/input/PlatformTextInputViewIntegrationTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/text/input/PlatformTextInputViewIntegrationTest.kt
index c4ad2bf..cde7762 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/text/input/PlatformTextInputViewIntegrationTest.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/text/input/PlatformTextInputViewIntegrationTest.kt
@@ -452,7 +452,7 @@
     // closeConnection is only supported on API 24+
     @SdkSuppress(minSdkVersion = 24)
     @Test
-    fun connectionClosed_whenCreateConnectionCalledAgain() {
+    fun connectionNotClosed_whenCreateConnectionCalledAgain() {
         class TestConnection(view: View) : BaseInputConnection(view, true) {
             var closeCalls = 0
 
@@ -484,15 +484,15 @@
 
             assertThat(connections).hasSize(2)
             val connection2 = connections.last()
-            assertThat(connection1.closeCalls).isEqualTo(1)
+            assertThat(connection1.closeCalls).isEqualTo(0)
             assertThat(connection2.closeCalls).isEqualTo(0)
 
             hostView.onCreateInputConnection(EditorInfo())
 
             assertThat(connections).hasSize(3)
             val connection3 = connections.last()
-            assertThat(connection1.closeCalls).isEqualTo(1)
-            assertThat(connection2.closeCalls).isEqualTo(1)
+            assertThat(connection1.closeCalls).isEqualTo(0)
+            assertThat(connection2.closeCalls).isEqualTo(0)
             assertThat(connection3.closeCalls).isEqualTo(0)
         }
 
@@ -501,7 +501,7 @@
 
     @SdkSuppress(minSdkVersion = 24)
     @Test
-    fun innerSessionCanceled_whenIsolatedFromOuterSession_whenConnectionClosed() {
+    fun innerSessionNotCanceled_whenIsolatedFromOuterSession_whenConnectionClosed() {
         setupContent()
         lateinit var innerJob: Job
         val outerJob =
@@ -520,15 +520,14 @@
         }
 
         rule.runOnIdle {
-            // Outer job isn't canceled, only the inner one.
             assertThat(outerJob.isActive).isTrue()
-            assertThat(innerJob.isActive).isFalse()
+            assertThat(innerJob.isActive).isTrue()
         }
     }
 
     @SdkSuppress(minSdkVersion = 24)
     @Test
-    fun cancellationPropagates_whenConnectionClosed() {
+    fun cancellationDoesNotPropagate_whenConnectionClosed() {
         setupContent()
         val sessionJob =
             coroutineScope.launch {
@@ -541,7 +540,7 @@
             connection.closeConnection()
         }
 
-        rule.runOnIdle { assertThat(sessionJob.isActive).isFalse() }
+        rule.runOnIdle { assertThat(sessionJob.isActive).isTrue() }
     }
 
     @Test
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/viewinterop/AndroidViewTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/viewinterop/AndroidViewTest.kt
index 358cef9..f178b053 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/viewinterop/AndroidViewTest.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/viewinterop/AndroidViewTest.kt
@@ -122,6 +122,7 @@
 import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility
 import androidx.test.espresso.matcher.ViewMatchers.withText
 import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.LargeTest
 import androidx.test.filters.MediumTest
 import androidx.test.filters.SdkSuppress
@@ -1646,9 +1647,69 @@
 
     // regression test for b/339527377
     @Test
-    @LargeTest
     fun androidView_layoutChangesInvokeGlobalLayoutListener() {
         lateinit var textView1: TextView
+        var callbackInvocations = 0
+
+        @Composable
+        fun GlobalLayoutAwareTextView(init: (TextView) -> Unit, modifier: Modifier = Modifier) {
+            AndroidView(
+                factory = {
+                    TextView(it).apply {
+                        layoutParams = ViewGroup.LayoutParams(WRAP_CONTENT, WRAP_CONTENT)
+                        init(this)
+                    }
+                },
+                modifier = modifier
+            )
+        }
+
+        rule.activityRule.withActivity {
+            window.decorView.viewTreeObserver.addOnGlobalLayoutListener { callbackInvocations++ }
+        }
+
+        rule.setContent {
+            Column(modifier = Modifier.fillMaxSize()) {
+                GlobalLayoutAwareTextView(
+                    init = { textView1 = it },
+                    modifier = Modifier.fillMaxWidth().height(100.dp)
+                )
+            }
+        }
+
+        rule.waitForIdle()
+        assertWithMessage(
+                "The initial layout did not invoke the viewTreeObserver's OnGlobalLayoutListener"
+            )
+            .that(callbackInvocations)
+            .isAtLeast(1)
+        callbackInvocations = 0
+
+        rule.runOnUiThread { textView1.text = "Foo".repeat(20) }
+        rule.waitForIdle()
+
+        assertWithMessage(
+                "Expected an invocation of the viewTreeObserver's OnGlobalLayoutListener " +
+                    "after re-laying out the contained AndroidView."
+            )
+            .that(callbackInvocations)
+            .isAtLeast(1)
+    }
+
+    // secondary regression test for b/339527377
+    @Test
+    @FlakyTest(
+        detail =
+            "This test flakes in CI because the platform may invoke the global layout " +
+                "callback in a way that this test can't account for. This test asserts an upper " +
+                "bound on the number of invocations to the global layout listener that we will " +
+                "dispatch, which affects performance instead of correctness. This test should always " +
+                "pass locally, but it is acceptable to flake and be ignored by CI since the test " +
+                "`androidView_layoutChangesInvokeGlobalLayoutListener` asserts the lower bound " +
+                "of the required behavior."
+    )
+    fun androidView_layoutChangesInvokeGlobalLayoutListenerExactlyOnce() {
+        lateinit var textView1: TextView
         lateinit var textView2: TextView
         var callbackInvocations = 0
 
@@ -1691,25 +1752,6 @@
             .isAtLeast(1)
         callbackInvocations = 0
 
-        rule.runOnUiThread { textView1.text = "Foo".repeat(20) }
-        rule.waitForIdle()
-
-        assertWithMessage(
-                "Expected exactly one invocation of the viewTreeObserver's OnGlobalLayoutListener " +
-                    "after re-laying out the contained AndroidView."
-            )
-            .that(callbackInvocations)
-            .isEqualTo(1)
-
-        // Reset the layouts
-        rule.runOnUiThread {
-            textView1.text = ""
-            textView2.text = ""
-        }
-        rule.waitForIdle()
-        callbackInvocations = 0
-
-        // Go again, but layout two Views.
         rule.runOnUiThread {
             textView1.text = "Foo".repeat(20)
             textView2.text = "Bar".repeat(20)
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/autofill/AutofillUtils.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/autofill/AutofillUtils.android.kt
index fbfd6d5e..dc2dc2f 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/autofill/AutofillUtils.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/autofill/AutofillUtils.android.kt
@@ -238,5 +238,6 @@
         Role.RadioButton -> "android.widget.RadioButton"
         Role.Image -> "android.widget.ImageView"
         Role.DropdownList -> "android.widget.Spinner"
+        Role.NumberPicker -> "android.widget.NumberPicker"
         else -> ClassName
     }
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt
index 905fdae..b2a4b98 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt
@@ -410,10 +410,28 @@
 
     private val canvasHolder = CanvasHolder()
 
+    // Backed by mutableStateOf so that the ambient provider recomposes when it changes
+    override var layoutDirection by
+        mutableStateOf(
+            // We don't use the attached View's layout direction here since that layout direction
+            // may not
+            // be resolved since composables may be composed without attaching to the RootViewImpl.
+            // In Jetpack Compose, use the locale layout direction (i.e. layoutDirection came from
+            // configuration) as a default layout direction.
+            toLayoutDirection(context.resources.configuration.layoutDirection)
+                ?: LayoutDirection.Ltr
+        )
+        private set
+
+    override val viewConfiguration: ViewConfiguration =
+        AndroidViewConfiguration(android.view.ViewConfiguration.get(context))
+
     override val root =
         LayoutNode().also {
             it.measurePolicy = RootMeasurePolicy
             it.density = density
+            it.layoutDirection = layoutDirection
+            it.viewConfiguration = viewConfiguration
             // Composed modifiers cannot be added here directly
             it.modifier =
                 Modifier.then(semanticsModifier)
@@ -528,9 +546,6 @@
     override val measureIteration: Long
         get() = measureAndLayoutDelegate.measureIteration
 
-    override val viewConfiguration: ViewConfiguration =
-        AndroidViewConfiguration(android.view.ViewConfiguration.get(context))
-
     override val hasPendingMeasureOrLayout
         get() = measureAndLayoutDelegate.hasPendingMeasureOrLayout
 
@@ -637,19 +652,6 @@
     private val Configuration.fontWeightAdjustmentCompat: Int
         get() = if (SDK_INT >= S) fontWeightAdjustment else 0
 
-    // Backed by mutableStateOf so that the ambient provider recomposes when it changes
-    override var layoutDirection by
-        mutableStateOf(
-            // We don't use the attached View's layout direction here since that layout direction
-            // may not
-            // be resolved since composables may be composed without attaching to the RootViewImpl.
-            // In Jetpack Compose, use the locale layout direction (i.e. layoutDirection came from
-            // configuration) as a default layout direction.
-            toLayoutDirection(context.resources.configuration.layoutDirection)
-                ?: LayoutDirection.Ltr
-        )
-        private set
-
     /** Provide haptic feedback to the user. Use the Android version of haptic feedback. */
     override val hapticFeedBack: HapticFeedback = PlatformHapticFeedback(this)
 
@@ -818,12 +820,12 @@
     }
 
     /**
-     * Avoid Android 8 crash by not traversing assist structure. Autofill assistStructure will be
-     * dispatched via `dispatchProvideAutofillStructure`, not this method. See b/251152083 for more
-     * details.
+     * Avoid crash by not traversing assist structure. Autofill assistStructure will be dispatched
+     * via `dispatchProvideAutofillStructure` from Android 8 and on. See b/251152083 and b/320768586
+     * more details.
      */
     override fun dispatchProvideStructure(structure: ViewStructure) {
-        if (SDK_INT == 26 || SDK_INT == 27) {
+        if (SDK_INT in 23..27) {
             AndroidComposeViewAssistHelperMethodsO.setClassName(structure, view)
         } else {
             super.dispatchProvideStructure(structure)
@@ -860,7 +862,8 @@
     }
 
     override fun focusSearch(focused: View?, direction: Int): View? {
-        if (focused != null) {
+        // do not propagate search if a measurement is happening
+        if (focused != null && !measureAndLayoutDelegate.duringMeasureLayout) {
             // Find the next composable using FocusOwner.
             val focusedBounds = focused.calculateBoundingRect()
             val focusDirection = toFocusDirection(direction) ?: Down
@@ -1377,7 +1380,13 @@
             val (minWidth, maxWidth) = convertMeasureSpec(widthMeasureSpec)
             val (minHeight, maxHeight) = convertMeasureSpec(heightMeasureSpec)
 
-            val constraints = Constraints(minWidth, maxWidth, minHeight, maxHeight)
+            val constraints =
+                Constraints.fitPrioritizingHeight(
+                    minWidth = minWidth,
+                    maxWidth = maxWidth,
+                    minHeight = minHeight,
+                    maxHeight = maxHeight
+                )
             if (onMeasureConstraints == null) {
                 // first onMeasure after last onLayout
                 onMeasureConstraints = constraints
@@ -1458,7 +1467,8 @@
     override fun createLayer(
         drawBlock: (canvas: Canvas, parentLayer: GraphicsLayer?) -> Unit,
         invalidateParentLayer: () -> Unit,
-        explicitLayer: GraphicsLayer?
+        explicitLayer: GraphicsLayer?,
+        forceUseOldLayers: Boolean
     ): OwnedLayer {
         if (explicitLayer != null) {
             return GraphicsLayerOwnerLayer(
@@ -1469,22 +1479,24 @@
                 invalidateParentLayer = invalidateParentLayer
             )
         }
-        // First try the layer cache
-        val layer = layerCache.pop()
-        if (layer !== null) {
-            layer.reuseLayer(drawBlock, invalidateParentLayer)
-            return layer
-        }
+        if (!forceUseOldLayers) {
+            // First try the layer cache
+            val layer = layerCache.pop()
+            if (layer !== null) {
+                layer.reuseLayer(drawBlock, invalidateParentLayer)
+                return layer
+            }
 
-        // enable new layers on versions supporting render nodes
-        if (isHardwareAccelerated && SDK_INT >= M && SDK_INT != P) {
-            return GraphicsLayerOwnerLayer(
-                graphicsLayer = graphicsContext.createGraphicsLayer(),
-                context = graphicsContext,
-                ownerView = this,
-                drawBlock = drawBlock,
-                invalidateParentLayer = invalidateParentLayer
-            )
+            // enable new layers on versions supporting render nodes
+            if (isHardwareAccelerated && SDK_INT >= M && SDK_INT != P) {
+                return GraphicsLayerOwnerLayer(
+                    graphicsLayer = graphicsContext.createGraphicsLayer(),
+                    context = graphicsContext,
+                    ownerView = this,
+                    drawBlock = drawBlock,
+                    invalidateParentLayer = invalidateParentLayer
+                )
+            }
         }
 
         // RenderNode is supported on Q+ for certain, but may also be supported on M-O.
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidPlatformTextInputSession.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidPlatformTextInputSession.android.kt
index 6fc34fa..df73f76 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidPlatformTextInputSession.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidPlatformTextInputSession.android.kt
@@ -21,9 +21,11 @@
 import android.view.View
 import android.view.inputmethod.EditorInfo
 import android.view.inputmethod.InputConnection
+import androidx.compose.runtime.collection.mutableVectorOf
 import androidx.compose.ui.InternalComposeUiApi
 import androidx.compose.ui.SessionMutex
 import androidx.compose.ui.node.Owner
+import androidx.compose.ui.node.WeakReference
 import androidx.compose.ui.text.InternalTextApi
 import androidx.compose.ui.text.input.NullableInputConnectionWrapper
 import androidx.compose.ui.text.input.TextInputService
@@ -67,8 +69,11 @@
 
     override suspend fun startInputMethod(request: PlatformTextInputMethodRequest): Nothing =
         methodSessionMutex.withSessionCancellingPrevious(
-            sessionInitializer = { coroutineScope ->
-                InputMethodSession(request, onConnectionClosed = { coroutineScope.cancel() })
+            sessionInitializer = {
+                InputMethodSession(
+                    request = request,
+                    onAllConnectionsClosed = { coroutineScope.cancel() }
+                )
             }
         ) { methodSession ->
             @Suppress("RemoveExplicitTypeArguments")
@@ -105,13 +110,16 @@
  * [AndroidPlatformTextInputSession]'s input method session. Instances of this class correspond to
  * calls to [AndroidPlatformTextInputSession.startInputMethod]. This class ensures that old
  * connections are disposed before new ones are created.
+ *
+ * @param onAllConnectionsClosed Called when all created [InputConnection]s receive
+ *   [InputConnection.closeConnection] call.
  */
 private class InputMethodSession(
     private val request: PlatformTextInputMethodRequest,
-    private val onConnectionClosed: () -> Unit
+    private val onAllConnectionsClosed: () -> Unit
 ) {
     private val lock = Any()
-    private var connection: NullableInputConnectionWrapper? = null
+    private var connections = mutableVectorOf<WeakReference<NullableInputConnectionWrapper>>()
     private var disposed = false
 
     val isActive: Boolean
@@ -127,28 +135,48 @@
     fun createInputConnection(outAttrs: EditorInfo): InputConnection? {
         synchronized(lock) {
             if (disposed) return null
-            // Manually close the delegate in case the system won't until later.
-            connection?.disposeDelegate()
+
+            // Do not manually dispose a previous InputConnection until it's collected by the GC or
+            // an explicit call is received to its `onConnectionClosed` callback.
 
             val connectionDelegate = request.createInputConnection(outAttrs)
             return NullableInputConnectionWrapper(
                     delegate = connectionDelegate,
-                    onConnectionClosed = onConnectionClosed
+                    onConnectionClosed = { closedConnection ->
+                        // We should not cancel any ongoing input session because connection is
+                        // closed
+                        // from InputConnection. This may happen at any time and does not indicate
+                        // whether the system is trying to stop an input session. The platform may
+                        // request a new InputConnection immediately after closing this one.
+                        // Instead we should just clear all the resources used by this
+                        // inputConnection,
+                        // because the platform guarantees that it will never reuse a closed
+                        // connection.
+                        closedConnection.disposeDelegate()
+                        val removeIndex = connections.indexOfFirst { it == closedConnection }
+                        if (removeIndex >= 0) connections.removeAt(removeIndex)
+                        if (connections.isEmpty()) {
+                            onAllConnectionsClosed()
+                        }
+                    }
                 )
-                .also { connection = it }
+                .also { connections.add(WeakReference(it)) }
         }
     }
 
     /**
      * Disposes the current [InputConnection]. After calling this method, all future calls to
      * [createInputConnection] will return null.
+     *
+     * This function is only called from coroutine cancellation routine so it's not required to
+     * cancel the coroutine from here.
      */
     fun dispose() {
         synchronized(lock) {
             // Manually close the delegate in case the system forgets to.
             disposed = true
-            connection?.disposeDelegate()
-            connection = null
+            connections.forEach { it.get()?.disposeDelegate() }
+            connections.clear()
         }
     }
 }
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/PlatformTextInputMethodRequest.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/PlatformTextInputMethodRequest.android.kt
index 0297a8d..5bafc46 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/PlatformTextInputMethodRequest.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/PlatformTextInputMethodRequest.android.kt
@@ -29,25 +29,30 @@
     /**
      * Called when the platform requests an [InputConnection] via [View.onCreateInputConnection].
      *
-     * This method makes stricter ordering guarantees about the lifetime of the returned
+     * This method makes relatively stricter ordering guarantees about the lifetime of the returned
      * [InputConnection] than Android does, to make working with connections simpler. Namely, it
      * guarantees:
-     * - For a given [PlatformTextInputMethodRequest] instance, only one [InputConnection] will ever
-     *   be active at a time.
-     * - References to an [InputConnection] will be cleared as soon as the connection becomes
-     *   inactive. Even if Android leaks its reference to the connection, the connection returned
-     *   from this method will not be leaked.
-     * - On API levels that support [InputConnection.closeConnection] (24+), a connection will
-     *   always be closed before a new connection is requested.
+     * - References to an [InputConnection] will be cleared as soon as the connection get closed via
+     *   [InputConnection.closeConnection]. Even if Android leaks its reference to the connection,
+     *   the connection returned from this method will not be leaked.
+     *
+     * However it does not guarantee that only one [InputConnection] will ever be active at a time
+     * for a given [PlatformTextInputMethodRequest] instance. On the other hand Android platform
+     * does guarantee that even though the platform may create multiple [InputConnection]s, only one
+     * of them will ever communicate with the app, invalidating any other [InputConnection] that
+     * remained open at the time of communication.
      *
      * Android may call [View.onCreateInputConnection] multiple times for the same session – each
-     * system call will result in a 1:1 call to this method, although the old connection will always
-     * be closed first.
+     * system call will result in a 1:1 call to this method. Unfortunately Android platform may
+     * decide to use an earlier [InputConnection] returned from this function, invalidating the ones
+     * that were created later. Please do not rely on the order of calls to this function.
      *
      * @param outAttributes The [EditorInfo] from [View.onCreateInputConnection].
      * @return The [InputConnection] that will be used to talk to the IME as long as the session is
      *   active. This connection will not receive any calls after the requesting coroutine is
      *   cancelled.
      */
+    // Please take a look at go/text-input-session-android-gotchas to learn more about corner cases
+    // of Android InputConnection management
     fun createInputConnection(outAttributes: EditorInfo): InputConnection
 }
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/SemanticsUtils.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/SemanticsUtils.android.kt
index 58d2c72..22c4b62 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/SemanticsUtils.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/SemanticsUtils.android.kt
@@ -122,6 +122,7 @@
         Role.RadioButton -> "android.widget.RadioButton"
         Role.Image -> "android.widget.ImageView"
         Role.DropdownList -> "android.widget.Spinner"
+        Role.NumberPicker -> "android.widget.NumberPicker"
         else -> null
     }
 
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/text/input/NullableInputConnectionWrapper.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/text/input/NullableInputConnectionWrapper.android.kt
index c2956a7..dc8c5ed 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/text/input/NullableInputConnectionWrapper.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/text/input/NullableInputConnectionWrapper.android.kt
@@ -40,11 +40,12 @@
  *   `disposeDelegate` or `closeConnection` are called.
  * @param onConnectionClosed A callback that will be invoked the first time `closeConnection` is
  *   called. Will not be invoked by `disposeDelegate`, and will not be invoked if `disposeDelegate`
- *   is called before `closeConnection`.
+ *   is called before `closeConnection`. Passed in [NullableInputConnectionWrapper] is the same
+ *   instance that is created here.
  */
 internal fun NullableInputConnectionWrapper(
     delegate: InputConnection,
-    onConnectionClosed: () -> Unit
+    onConnectionClosed: (NullableInputConnectionWrapper) -> Unit
 ): NullableInputConnectionWrapper =
     when {
         Build.VERSION.SDK_INT >= 34 ->
@@ -82,7 +83,7 @@
 
 private open class NullableInputConnectionWrapperApi21(
     delegate: InputConnection,
-    private val onConnectionClosed: () -> Unit
+    private val onConnectionClosed: (NullableInputConnectionWrapper) -> Unit
 ) : NullableInputConnectionWrapper {
 
     protected var delegate: InputConnection? = delegate
@@ -98,7 +99,7 @@
     final override fun closeConnection() {
         delegate?.let {
             disposeDelegate()
-            onConnectionClosed()
+            onConnectionClosed(this)
         }
     }
 
@@ -174,7 +175,7 @@
 @RequiresApi(24)
 private open class NullableInputConnectionWrapperApi24(
     delegate: InputConnection,
-    onConnectionClosed: () -> Unit
+    onConnectionClosed: (NullableInputConnectionWrapper) -> Unit
 ) : NullableInputConnectionWrapperApi21(delegate, onConnectionClosed) {
 
     final override fun deleteSurroundingTextInCodePoints(p0: Int, p1: Int): Boolean =
@@ -190,7 +191,7 @@
 @RequiresApi(25)
 private open class NullableInputConnectionWrapperApi25(
     delegate: InputConnection,
-    onConnectionClosed: () -> Unit
+    onConnectionClosed: (NullableInputConnectionWrapper) -> Unit
 ) : NullableInputConnectionWrapperApi24(delegate, onConnectionClosed) {
 
     final override fun commitContent(p0: InputContentInfo, p1: Int, p2: Bundle?): Boolean =
@@ -200,7 +201,7 @@
 @RequiresApi(34)
 private open class NullableInputConnectionWrapperApi34(
     delegate: InputConnection,
-    onConnectionClosed: () -> Unit
+    onConnectionClosed: (NullableInputConnectionWrapper) -> Unit
 ) : NullableInputConnectionWrapperApi25(delegate, onConnectionClosed) {
     final override fun performHandwritingGesture(
         gesture: HandwritingGesture,
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/viewinterop/AndroidViewHolder.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/viewinterop/AndroidViewHolder.android.kt
index 351f9ed..9dd30ec 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/viewinterop/AndroidViewHolder.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/viewinterop/AndroidViewHolder.android.kt
@@ -30,6 +30,7 @@
 import androidx.compose.ui.draw.drawBehind
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
+import androidx.compose.ui.graphics.graphicsLayer
 import androidx.compose.ui.graphics.nativeCanvas
 import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
 import androidx.compose.ui.input.nestedscroll.NestedScrollDispatcher
@@ -330,6 +331,14 @@
     val layoutNode: LayoutNode = run {
         // Prepare layout node that proxies measure and layout passes to the View.
         val layoutNode = LayoutNode()
+
+        // there is an issue in how SurfaceViews being drawn into the new layers. this flag is
+        // a workaround until we find a better solution. it allows us to create an extra rendernode
+        // wrapping android views using the old implementation of layers, where we don't do
+        // layer persistence logic, as it causes SurfaceView flickering.
+        // we should find a better fix as part of b/348144529
+        layoutNode.forceUseOldLayers = true
+
         @OptIn(InternalComposeUiApi::class)
         layoutNode.interopViewFactoryHolder = this@AndroidViewHolder
 
@@ -337,6 +346,8 @@
             Modifier.nestedScroll(NoOpScrollConnection, dispatcher)
                 .semantics(true) {}
                 .pointerInteropFilter(this)
+                // we don't normally need an extra layer here, it is a workaround for b/348144529
+                .graphicsLayer()
                 .drawBehind {
                     drawIntoCanvas { canvas ->
                         if (view.visibility != GONE) {
diff --git a/compose/ui/ui/src/androidUnitTest/kotlin/androidx/compose/ui/input/pointer/util/VelocityTrackerTest.kt b/compose/ui/ui/src/androidUnitTest/kotlin/androidx/compose/ui/input/pointer/util/VelocityTrackerTest.kt
index 3a7f568..a02d8dd 100644
--- a/compose/ui/ui/src/androidUnitTest/kotlin/androidx/compose/ui/input/pointer/util/VelocityTrackerTest.kt
+++ b/compose/ui/ui/src/androidUnitTest/kotlin/androidx/compose/ui/input/pointer/util/VelocityTrackerTest.kt
@@ -75,6 +75,7 @@
         }
     }
 
+    @OptIn(ExperimentalVelocityTrackerApi::class)
     @Test
     fun calculateVelocity_gapOf40MillisecondsInPositions_positionsAfterGapIgnored() {
         val tracker = VelocityTracker()
@@ -143,6 +144,7 @@
 internal class PointerInputData(val uptime: Long, val position: Offset, val down: Boolean)
 
 // Expected velocities for "velocityEventData". See below.
+@OptIn(ExperimentalVelocityTrackerApi::class)
 internal val expected2DVelocities =
     if (VelocityTrackerStrategyUseImpulse) {
         listOf(
diff --git a/compose/ui/ui/src/androidUnitTest/kotlin/androidx/compose/ui/layout/AlignmentCombineTest.kt b/compose/ui/ui/src/androidUnitTest/kotlin/androidx/compose/ui/layout/AlignmentCombineTest.kt
new file mode 100644
index 0000000..46b889b
--- /dev/null
+++ b/compose/ui/ui/src/androidUnitTest/kotlin/androidx/compose/ui/layout/AlignmentCombineTest.kt
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.ui.layout
+
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.BiasAbsoluteAlignment
+import androidx.compose.ui.BiasAlignment
+import androidx.compose.ui.unit.IntOffset
+import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.unit.LayoutDirection
+import kotlin.test.assertTrue
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class AlignmentCombineTest {
+    private val space = IntSize(200, 200)
+
+    /** A custom, non-[BiasAlignment] horizontal alignment implementation. */
+    private fun inverseHorizontal(bias: Float) =
+        Alignment.Horizontal { size, space, ld ->
+            BiasAlignment.Horizontal(-bias).align(size, space, ld)
+        }
+
+    /** A custom, non-[BiasAlignment] vertical alignment implementation. */
+    private fun inverseVertical(bias: Float) =
+        Alignment.Vertical { size, space -> BiasAlignment.Vertical(-bias).align(size, space) }
+
+    @Test
+    fun testCombineHorizontalAndVertical() {
+        val h = inverseHorizontal(.58f)
+        val v = inverseVertical(.76f)
+        val a = h + v
+        assertEquals(IntOffset(42, 24), a.align(IntSize.Zero, space, LayoutDirection.Ltr))
+        assertEquals(IntOffset(158, 24), a.align(IntSize.Zero, space, LayoutDirection.Rtl))
+    }
+
+    @Test
+    fun testCombineHorizontalAndBiasVertical() {
+        val h = inverseHorizontal(.58f)
+        val v = BiasAlignment.Vertical(-.76f)
+        val a = h + v
+        assertEquals(IntOffset(42, 24), a.align(IntSize.Zero, space, LayoutDirection.Ltr))
+        assertEquals(IntOffset(158, 24), a.align(IntSize.Zero, space, LayoutDirection.Rtl))
+    }
+
+    @Test
+    fun testCombineBiasHorizontalAndVertical() {
+        val h = BiasAlignment.Horizontal(-.58f)
+        val v = inverseVertical(.76f)
+        val a = h + v
+        assertEquals(IntOffset(42, 24), a.align(IntSize.Zero, space, LayoutDirection.Ltr))
+        assertEquals(IntOffset(158, 24), a.align(IntSize.Zero, space, LayoutDirection.Rtl))
+    }
+
+    @Test
+    fun testCombineBiasHorizontalAndBiasVertical() {
+        val h = BiasAlignment.Horizontal(-.58f)
+        val v = BiasAlignment.Vertical(-.76f)
+        val a = h + v
+        assertEquals(IntOffset(42, 24), a.align(IntSize.Zero, space, LayoutDirection.Ltr))
+        assertEquals(IntOffset(158, 24), a.align(IntSize.Zero, space, LayoutDirection.Rtl))
+        // Ensure optimization applied.
+        assertTrue(a is BiasAlignment)
+    }
+
+    @Test
+    fun testCombineBiasAbsoluteHorizontalAndVertical() {
+        val h = BiasAbsoluteAlignment.Horizontal(-.58f)
+        val v = inverseVertical(.76f)
+        val a = h + v
+        assertEquals(IntOffset(42, 24), a.align(IntSize.Zero, space, LayoutDirection.Ltr))
+        assertEquals(IntOffset(42, 24), a.align(IntSize.Zero, space, LayoutDirection.Rtl))
+    }
+
+    @Test
+    fun testCombineBiasAbsoluteHorizontalAndBiasVertical() {
+        val h = BiasAbsoluteAlignment.Horizontal(-.58f)
+        val v = BiasAlignment.Vertical(-.76f)
+        val a = h + v
+        assertEquals(IntOffset(42, 24), a.align(IntSize.Zero, space, LayoutDirection.Ltr))
+        assertEquals(IntOffset(42, 24), a.align(IntSize.Zero, space, LayoutDirection.Rtl))
+        // Ensure optimization applied.
+        assertTrue(a is BiasAbsoluteAlignment)
+    }
+
+    @Test
+    fun testCombineVerticalAndHorizontal() {
+        val v = inverseVertical(.76f)
+        val h = inverseHorizontal(.58f)
+        val a = v + h
+        assertEquals(IntOffset(42, 24), a.align(IntSize.Zero, space, LayoutDirection.Ltr))
+        assertEquals(IntOffset(158, 24), a.align(IntSize.Zero, space, LayoutDirection.Rtl))
+    }
+
+    @Test
+    fun testCombineVerticalAndBiasHorizontal() {
+        val v = inverseVertical(.76f)
+        val h = BiasAlignment.Horizontal(-.58f)
+        val a = v + h
+        assertEquals(IntOffset(42, 24), a.align(IntSize.Zero, space, LayoutDirection.Ltr))
+        assertEquals(IntOffset(158, 24), a.align(IntSize.Zero, space, LayoutDirection.Rtl))
+    }
+
+    @Test
+    fun testCombineVerticalAndBiasAbsoluteHorizontal() {
+        val v = inverseVertical(.76f)
+        val h = BiasAbsoluteAlignment.Horizontal(-.58f)
+        val a = v + h
+        assertEquals(IntOffset(42, 24), a.align(IntSize.Zero, space, LayoutDirection.Ltr))
+        assertEquals(IntOffset(42, 24), a.align(IntSize.Zero, space, LayoutDirection.Rtl))
+    }
+
+    @Test
+    fun testCombineBiasVerticalAndHorizontal() {
+        val v = BiasAlignment.Vertical(-.76f)
+        val h = inverseHorizontal(.58f)
+        val a = v + h
+        assertEquals(IntOffset(42, 24), a.align(IntSize.Zero, space, LayoutDirection.Ltr))
+        assertEquals(IntOffset(158, 24), a.align(IntSize.Zero, space, LayoutDirection.Rtl))
+    }
+
+    @Test
+    fun testCombineBiasVerticalAndBiasHorizontal() {
+        val v = BiasAlignment.Vertical(-.76f)
+        val h = BiasAlignment.Horizontal(-.58f)
+        val a = v + h
+        assertEquals(IntOffset(42, 24), a.align(IntSize.Zero, space, LayoutDirection.Ltr))
+        assertEquals(IntOffset(158, 24), a.align(IntSize.Zero, space, LayoutDirection.Rtl))
+        // Ensure optimization applied.
+        assertTrue(a is BiasAlignment)
+    }
+
+    @Test
+    fun testCombineBiasVerticalAndBiasAbsoluteHorizontal() {
+        val v = BiasAlignment.Vertical(-.76f)
+        val h = BiasAbsoluteAlignment.Horizontal(-.58f)
+        val a = v + h
+        assertEquals(IntOffset(42, 24), a.align(IntSize.Zero, space, LayoutDirection.Ltr))
+        assertEquals(IntOffset(42, 24), a.align(IntSize.Zero, space, LayoutDirection.Rtl))
+        // Ensure optimization applied.
+        assertTrue(a is BiasAbsoluteAlignment)
+    }
+}
diff --git a/compose/ui/ui/src/androidUnitTest/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt b/compose/ui/ui/src/androidUnitTest/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt
index e349ba4..c53b374 100644
--- a/compose/ui/ui/src/androidUnitTest/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt
+++ b/compose/ui/ui/src/androidUnitTest/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt
@@ -2468,7 +2468,8 @@
     override fun createLayer(
         drawBlock: (Canvas, GraphicsLayer?) -> Unit,
         invalidateParentLayer: () -> Unit,
-        explicitLayer: GraphicsLayer?
+        explicitLayer: GraphicsLayer?,
+        forceUseOldLayers: Boolean
     ): OwnedLayer {
         val transform = Matrix()
         val inverseTransform = Matrix()
diff --git a/compose/ui/ui/src/androidUnitTest/kotlin/androidx/compose/ui/node/ModifierLocalConsumerEntityTest.kt b/compose/ui/ui/src/androidUnitTest/kotlin/androidx/compose/ui/node/ModifierLocalConsumerEntityTest.kt
index 6dca249..268355cc 100644
--- a/compose/ui/ui/src/androidUnitTest/kotlin/androidx/compose/ui/node/ModifierLocalConsumerEntityTest.kt
+++ b/compose/ui/ui/src/androidUnitTest/kotlin/androidx/compose/ui/node/ModifierLocalConsumerEntityTest.kt
@@ -409,7 +409,8 @@
         override fun createLayer(
             drawBlock: (Canvas, GraphicsLayer?) -> Unit,
             invalidateParentLayer: () -> Unit,
-            explicitLayer: GraphicsLayer?
+            explicitLayer: GraphicsLayer?,
+            forceUseOldLayers: Boolean
         ) = TODO("Not yet implemented")
 
         override fun onRequestRelayout(
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/Alignment.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/Alignment.kt
index deb3ad6..1a1c34a 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/Alignment.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/Alignment.kt
@@ -53,6 +53,12 @@
          * size` meaning that the box will be positioned partially or completely outside the area.
          */
         fun align(size: Int, space: Int, layoutDirection: LayoutDirection): Int
+
+        /**
+         * Combine this instance's horizontal alignment with [other]'s vertical alignment to create
+         * an [Alignment].
+         */
+        operator fun plus(other: Vertical): Alignment = CombinedAlignment(this, other)
     }
 
     /**
@@ -68,6 +74,12 @@
          * meaning that the box will be positioned partially or completely outside the area.
          */
         fun align(size: Int, space: Int): Int
+
+        /**
+         * Combine this instance's vertical alignment with [other]'s horizontal alignment to create
+         * an [Alignment].
+         */
+        operator fun plus(other: Horizontal): Alignment = CombinedAlignment(other, this)
     }
 
     /** A collection of common [Alignment]s aware of layout direction. */
@@ -95,6 +107,17 @@
     }
 }
 
+private class CombinedAlignment(
+    private val horizontal: Alignment.Horizontal,
+    private val vertical: Alignment.Vertical,
+) : Alignment {
+    override fun align(size: IntSize, space: IntSize, layoutDirection: LayoutDirection): IntOffset {
+        val x = horizontal.align(size.width, space.width, layoutDirection)
+        val y = vertical.align(size.height, space.height)
+        return IntOffset(x, y)
+    }
+}
+
 /** A collection of common [Alignment]s unaware of the layout direction. */
 object AbsoluteAlignment {
     // 2D AbsoluteAlignments.
@@ -158,6 +181,13 @@
             val resolvedBias = if (layoutDirection == LayoutDirection.Ltr) bias else -1 * bias
             return (center * (1 + resolvedBias)).fastRoundToInt()
         }
+
+        override fun plus(other: Alignment.Vertical): Alignment {
+            return when (other) {
+                is Vertical -> BiasAlignment(bias, other.bias)
+                else -> super.plus(other)
+            }
+        }
     }
 
     /**
@@ -177,6 +207,14 @@
             val center = (space - size).toFloat() / 2f
             return (center * (1 + bias)).fastRoundToInt()
         }
+
+        override fun plus(other: Alignment.Horizontal): Alignment {
+            return when (other) {
+                is Horizontal -> BiasAlignment(other.bias, bias)
+                is BiasAbsoluteAlignment.Horizontal -> BiasAbsoluteAlignment(other.bias, bias)
+                else -> super.plus(other)
+            }
+        }
     }
 }
 
@@ -229,5 +267,12 @@
             val center = (space - size).toFloat() / 2f
             return (center * (1 + bias)).fastRoundToInt()
         }
+
+        override fun plus(other: Alignment.Vertical): Alignment {
+            return when (other) {
+                is BiasAlignment.Vertical -> BiasAbsoluteAlignment(bias, other.bias)
+                else -> super.plus(other)
+            }
+        }
     }
 }
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusInvalidationManager.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusInvalidationManager.kt
index be26679..b9cb7f3 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusInvalidationManager.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusInvalidationManager.kt
@@ -16,12 +16,11 @@
 
 package androidx.compose.ui.focus
 
-import androidx.collection.MutableScatterSet
-import androidx.collection.mutableScatterSetOf
 import androidx.compose.ui.focus.FocusStateImpl.Inactive
 import androidx.compose.ui.internal.checkPrecondition
 import androidx.compose.ui.node.Nodes
 import androidx.compose.ui.node.visitSelfAndChildren
+import androidx.compose.ui.util.fastForEach
 
 /**
  * The [FocusInvalidationManager] allows us to schedule focus related nodes for invalidation. These
@@ -30,12 +29,13 @@
  */
 internal class FocusInvalidationManager(
     private val onRequestApplyChangesListener: (() -> Unit) -> Unit,
-    private val invalidateOwnerFocusState: () -> Unit
+    private val invalidateOwnerFocusState: () -> Unit,
+    private val rootFocusStateFetcher: () -> FocusState
 ) {
-    private val focusTargetNodes = mutableScatterSetOf<FocusTargetNode>()
-    private val focusEventNodes = mutableScatterSetOf<FocusEventModifierNode>()
-    private val focusPropertiesNodes = mutableScatterSetOf<FocusPropertiesModifierNode>()
-    private val focusTargetsWithInvalidatedFocusEvents = mutableScatterSetOf<FocusTargetNode>()
+    private val focusTargetNodes = mutableListOf<FocusTargetNode>()
+    private val focusEventNodes = mutableListOf<FocusEventModifierNode>()
+    private val focusPropertiesNodes = mutableListOf<FocusPropertiesModifierNode>()
+    private val focusTargetsWithInvalidatedFocusEvents = mutableListOf<FocusTargetNode>()
 
     fun scheduleInvalidation(node: FocusTargetNode) {
         focusTargetNodes.scheduleInvalidation(node)
@@ -55,7 +55,7 @@
             focusEventNodes.isNotEmpty()
     }
 
-    private fun <T> MutableScatterSet<T>.scheduleInvalidation(node: T) {
+    private fun <T> MutableList<T>.scheduleInvalidation(node: T) {
         if (add(node)) {
             // If this is the first node scheduled for invalidation,
             // we set up a listener that runs after onApplyChanges.
@@ -66,11 +66,27 @@
     }
 
     private fun invalidateNodes() {
+        if (!rootFocusStateFetcher().hasFocus) {
+            // If root doesn't have focus, skip full invalidation and default to the Inactive state.
+            focusEventNodes.fastForEach { it.onFocusEvent(Inactive) }
+            focusTargetNodes.fastForEach { node ->
+                if (node.isAttached && !node.isInitialized()) {
+                    node.initializeFocusState(Inactive)
+                }
+            }
+            focusTargetNodes.clear()
+            focusEventNodes.clear()
+            focusPropertiesNodes.clear()
+            focusTargetsWithInvalidatedFocusEvents.clear()
+            invalidateOwnerFocusState()
+            return
+        }
+
         // Process all the invalidated FocusProperties nodes.
-        focusPropertiesNodes.forEach {
+        focusPropertiesNodes.fastForEach {
             // We don't need to invalidate a focus properties node if it was scheduled for
             // invalidation earlier in the composition but was then removed.
-            if (!it.node.isAttached) return@forEach
+            if (!it.node.isAttached) return@fastForEach
 
             it.visitSelfAndChildren(Nodes.FocusTarget) { focusTarget ->
                 focusTargetNodes.add(focusTarget)
@@ -79,7 +95,7 @@
         focusPropertiesNodes.clear()
 
         // Process all the focus events nodes.
-        focusEventNodes.forEach { focusEventNode ->
+        focusEventNodes.fastForEach { focusEventNode ->
             // When focus nodes are removed, the corresponding focus events are scheduled for
             // invalidation. If the focus event was also removed, we don't need to invalidate it.
             // We call onFocusEvent with the default value, just to make it easier for the user,
@@ -87,7 +103,7 @@
             // removed (Which would cause it to lose focus).
             if (!focusEventNode.node.isAttached) {
                 focusEventNode.onFocusEvent(Inactive)
-                return@forEach
+                return@fastForEach
             }
 
             var requiresUpdate = true
@@ -127,10 +143,10 @@
         focusEventNodes.clear()
 
         // Process all the focus target nodes.
-        focusTargetNodes.forEach {
+        focusTargetNodes.fastForEach {
             // We don't need to invalidate the focus target if it was scheduled for invalidation
             // earlier in the composition but was then removed.
-            if (!it.isAttached) return@forEach
+            if (!it.isAttached) return@fastForEach
 
             val preInvalidationState = it.focusState
             it.invalidateFocus()
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusOwnerImpl.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusOwnerImpl.kt
index 6b6fe83..c1444f8 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusOwnerImpl.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusOwnerImpl.kt
@@ -65,7 +65,11 @@
     internal var rootFocusNode = FocusTargetNode(focusability = Focusability.Never)
 
     private val focusInvalidationManager =
-        FocusInvalidationManager(onRequestApplyChangesListener, ::invalidateOwnerFocusState)
+        FocusInvalidationManager(
+            onRequestApplyChangesListener,
+            ::invalidateOwnerFocusState,
+            ::rootState
+        )
 
     override val focusTransactionManager: FocusTransactionManager = FocusTransactionManager()
 
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTargetNode.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTargetNode.kt
index 9586f10..dbb84ed 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTargetNode.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTargetNode.kt
@@ -76,7 +76,7 @@
                 field = value
                 // Avoid invalidating if we have not been initialized yet: there is no need to
                 // invalidate since these property changes cannot affect anything.
-                if (isAttached && committedFocusState != null) {
+                if (isAttached && isInitialized()) {
                     // Invalidate focus if needed
                     onObservedReadsChanged()
                 }
@@ -199,7 +199,7 @@
     }
 
     internal fun invalidateFocus() {
-        if (committedFocusState == null) initializeFocusState()
+        if (!isInitialized()) initializeFocusState()
         when (focusState) {
             // Clear focus from the current FocusTarget.
             // This currently clears focus from the entire hierarchy, but we can change the
@@ -250,10 +250,9 @@
         override fun equals(other: Any?) = other === this
     }
 
-    private fun initializeFocusState() {
+    internal fun isInitialized(): Boolean = committedFocusState != null
 
-        fun FocusTargetNode.isInitialized(): Boolean = committedFocusState != null
-
+    internal fun initializeFocusState(initialFocusState: FocusStateImpl? = null) {
         fun isInActiveSubTree(): Boolean {
             visitAncestors(Nodes.FocusTarget) {
                 if (!it.isInitialized()) return@visitAncestors
@@ -287,7 +286,9 @@
         requireTransactionManager().withNewTransaction {
             // Note: hasActiveChild() is expensive since it searches the entire subtree. So we only
             // do this if we are part of the active subtree.
-            focusState = if (isInActiveSubTree() && hasActiveChild()) ActiveParent else Inactive
+            this.focusState =
+                initialFocusState
+                    ?: if (isInActiveSubTree() && hasActiveChild()) ActiveParent else Inactive
         }
     }
 }
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilter.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilter.kt
index d909400..81e55d6 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilter.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilter.kt
@@ -183,38 +183,17 @@
 fun Modifier.pointerInput(block: suspend PointerInputScope.() -> Unit): Modifier =
     error(PointerInputModifierNoParamError)
 
-/**
- * Create a modifier for processing pointer input within the region of the modified element.
- *
- * [pointerInput] [block]s may call [PointerInputScope.awaitPointerEventScope] to install a pointer
- * input handler that can [AwaitPointerEventScope.awaitPointerEvent] to receive and consume pointer
- * input events. Extension functions on [PointerInputScope] or [AwaitPointerEventScope] may be
- * defined to perform higher-level gesture detection. The pointer input handling [block] will be
- * cancelled and **re-started** when [pointerInput] is recomposed with a different [key1].
- *
- * When a [pointerInput] modifier is created by composition, if [block] captures any local variables
- * to operate on, two patterns are common for working with changes to those variables depending on
- * the desired behavior.
- *
- * Specifying the captured value as a [key][key1] parameter will cause [block] to cancel and restart
- * from the beginning if the value changes:
- *
- * @sample androidx.compose.ui.samples.keyedPointerInputModifier
- *
- * If [block] should **not** restart when a captured value is changed but the value should still be
- * updated for its next use, use
- * [rememberUpdatedState][androidx.compose.runtime.rememberUpdatedState] to update a value holder
- * that is accessed by [block]:
- *
- * @sample androidx.compose.ui.samples.rememberedUpdatedParameterPointerInputModifier
- *
- * ***Note*** Any removal operations on Android Views from `pointerInput` should wrap the `block` in
- * a `post { }` block to guarantee the event dispatch completes before executing the removal. (You
- * do not need to do this when removing a composable because Compose guarantees it completes via the
- * snapshot state system.)
- */
+@Deprecated(
+    "This function is deprecated. Use the PointerInputEventHandler block variation instead",
+    level = DeprecationLevel.HIDDEN,
+    replaceWith =
+        ReplaceWith(
+            "pointerInput(key1 = key1, pointerInputEventHandler = block)",
+            "androidx.compose.ui.input.pointer.Modifier.pointerInput"
+        )
+)
 fun Modifier.pointerInput(key1: Any?, block: suspend PointerInputScope.() -> Unit): Modifier =
-    this then SuspendPointerInputElement(key1 = key1, pointerInputHandler = block)
+    this then SuspendPointerInputElement(key1 = key1, pointerInputEventHandler = block)
 
 /**
  * Create a modifier for processing pointer input within the region of the modified element.
@@ -223,7 +202,8 @@
  * input handler that can [AwaitPointerEventScope.awaitPointerEvent] to receive and consume pointer
  * input events. Extension functions on [PointerInputScope] or [AwaitPointerEventScope] may be
  * defined to perform higher-level gesture detection. The pointer input handling [block] will be
- * cancelled and **re-started** when [pointerInput] is recomposed with a different [key1] or [key2].
+ * cancelled and **re-started** when [pointerInput] is recomposed with a different [key1] or the
+ * [block] class is different.
  *
  * When a [pointerInput] modifier is created by composition, if [block] captures any local variables
  * to operate on, two patterns are common for working with changes to those variables depending on
@@ -246,12 +226,24 @@
  * do not need to do this when removing a composable because Compose guarantees it completes via the
  * snapshot state system.)
  */
+fun Modifier.pointerInput(key1: Any?, block: PointerInputEventHandler): Modifier =
+    this then SuspendPointerInputElement(key1 = key1, pointerInputEventHandler = block)
+
+@Deprecated(
+    "This function is deprecated. Use the PointerInputEventHandler block variation instead",
+    level = DeprecationLevel.HIDDEN,
+    replaceWith =
+        ReplaceWith(
+            "pointerInput(key1 = key1, key2 = key2, pointerInputEventHandler = block)",
+            "androidx.compose.ui.input.pointer.Modifier.pointerInput"
+        )
+)
 fun Modifier.pointerInput(
     key1: Any?,
     key2: Any?,
     block: suspend PointerInputScope.() -> Unit
 ): Modifier =
-    this then SuspendPointerInputElement(key1 = key1, key2 = key2, pointerInputHandler = block)
+    this then SuspendPointerInputElement(key1 = key1, key2 = key2, pointerInputEventHandler = block)
 
 /**
  * Create a modifier for processing pointer input within the region of the modified element.
@@ -260,7 +252,56 @@
  * input handler that can [AwaitPointerEventScope.awaitPointerEvent] to receive and consume pointer
  * input events. Extension functions on [PointerInputScope] or [AwaitPointerEventScope] may be
  * defined to perform higher-level gesture detection. The pointer input handling [block] will be
- * cancelled and **re-started** when [pointerInput] is recomposed with any different [keys].
+ * cancelled and **re-started** when [pointerInput] is recomposed with a different [key1] or [key2],
+ * or the [block] class is different.
+ *
+ * When a [pointerInput] modifier is created by composition, if [block] captures any local variables
+ * to operate on, two patterns are common for working with changes to those variables depending on
+ * the desired behavior.
+ *
+ * Specifying the captured value as a [key][key1] parameter will cause [block] to cancel and restart
+ * from the beginning if the value changes:
+ *
+ * @sample androidx.compose.ui.samples.keyedPointerInputModifier
+ *
+ * If [block] should **not** restart when a captured value is changed but the value should still be
+ * updated for its next use, use
+ * [rememberUpdatedState][androidx.compose.runtime.rememberUpdatedState] to update a value holder
+ * that is accessed by [block]:
+ *
+ * @sample androidx.compose.ui.samples.rememberedUpdatedParameterPointerInputModifier
+ *
+ * ***Note*** Any removal operations on Android Views from `pointerInput` should wrap the `block` in
+ * a `post { }` block to guarantee the event dispatch completes before executing the removal. (You
+ * do not need to do this when removing a composable because Compose guarantees it completes via the
+ * snapshot state system.)
+ */
+fun Modifier.pointerInput(key1: Any?, key2: Any?, block: PointerInputEventHandler): Modifier =
+    this then SuspendPointerInputElement(key1 = key1, key2 = key2, pointerInputEventHandler = block)
+
+@Deprecated(
+    "This function is deprecated. Use the PointerInputEventHandler block variation instead",
+    level = DeprecationLevel.HIDDEN,
+    replaceWith =
+        ReplaceWith(
+            "pointerInput(keys = keys, pointerInputEventHandler = block)",
+            "androidx.compose.ui.input.pointer.Modifier.pointerInput"
+        )
+)
+fun Modifier.pointerInput(
+    vararg keys: Any?,
+    block: suspend PointerInputScope.() -> Unit
+): Modifier = this then SuspendPointerInputElement(keys = keys, pointerInputEventHandler = block)
+
+/**
+ * Create a modifier for processing pointer input within the region of the modified element.
+ *
+ * [pointerInput] [block]s may call [PointerInputScope.awaitPointerEventScope] to install a pointer
+ * input handler that can [AwaitPointerEventScope.awaitPointerEvent] to receive and consume pointer
+ * input events. Extension functions on [PointerInputScope] or [AwaitPointerEventScope] may be
+ * defined to perform higher-level gesture detection. The pointer input handling [block] will be
+ * cancelled and **re-started** when [pointerInput] is recomposed with any different [keys] or the
+ * [block] class is different.
  *
  * When a [pointerInput] modifier is created by composition, if [block] captures any local variables
  * to operate on, two patterns are common for working with changes to those variables depending on
@@ -283,31 +324,37 @@
  * do not need to do this when removing a composable because Compose guarantees it completes via the
  * snapshot state system.)
  */
-fun Modifier.pointerInput(
-    vararg keys: Any?,
-    block: suspend PointerInputScope.() -> Unit
-): Modifier = this then SuspendPointerInputElement(keys = keys, pointerInputHandler = block)
+fun Modifier.pointerInput(vararg keys: Any?, block: PointerInputEventHandler): Modifier =
+    this then SuspendPointerInputElement(keys = keys, pointerInputEventHandler = block)
+
+/*
+ * Represents the 'block' lambda passed into [Modifier.pointerInput]. It's used to receive and
+ * consume pointer input events.
+ */
+fun interface PointerInputEventHandler {
+    suspend operator fun PointerInputScope.invoke()
+}
 
 internal class SuspendPointerInputElement(
     val key1: Any? = null,
     val key2: Any? = null,
     val keys: Array<out Any?>? = null,
-    val pointerInputHandler: suspend PointerInputScope.() -> Unit
+    val pointerInputEventHandler: PointerInputEventHandler
 ) : ModifierNodeElement<SuspendingPointerInputModifierNodeImpl>() {
     override fun InspectorInfo.inspectableProperties() {
         name = "pointerInput"
         properties["key1"] = key1
         properties["key2"] = key2
         properties["keys"] = keys
-        properties["pointerInputHandler"] = pointerInputHandler
+        properties["pointerInputEventHandler"] = pointerInputEventHandler
     }
 
     override fun create(): SuspendingPointerInputModifierNodeImpl {
-        return SuspendingPointerInputModifierNodeImpl(key1, key2, keys, pointerInputHandler)
+        return SuspendingPointerInputModifierNodeImpl(key1, key2, keys, pointerInputEventHandler)
     }
 
     override fun update(node: SuspendingPointerInputModifierNodeImpl) {
-        node.update(key1, key2, keys, pointerInputHandler)
+        node.update(key1, key2, keys, pointerInputEventHandler)
     }
 
     override fun equals(other: Any?): Boolean {
@@ -321,20 +368,39 @@
             if (!keys.contentEquals(other.keys)) return false
         } else if (other.keys != null) return false
 
-        return pointerInputHandler === other.pointerInputHandler
+        return pointerInputEventHandler === other.pointerInputEventHandler
     }
 
     override fun hashCode(): Int {
         var result = key1?.hashCode() ?: 0
         result = 31 * result + (key2?.hashCode() ?: 0)
         result = 31 * result + (keys?.contentHashCode() ?: 0)
-        result = 31 * result + pointerInputHandler.hashCode()
+        result = 31 * result + pointerInputEventHandler.hashCode()
         return result
     }
 }
 
 private val EmptyPointerEvent = PointerEvent(emptyList())
 
+/** Deprecated, use [SuspendingPointerInputModifierNode] instead. */
+@Deprecated(
+    message =
+        "This function is deprecated. Use 'SuspendingPointerInputModifierNode' with the" +
+            "PointerInputEventHandler instead.",
+    level = DeprecationLevel.HIDDEN,
+    replaceWith =
+        ReplaceWith(
+            "SuspendingPointerInputModifierNode { pointerInputEventHandler }",
+            "androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNode"
+        )
+)
+@Suppress("DEPRECATION")
+fun SuspendingPointerInputModifierNode(
+    pointerInputHandler: suspend PointerInputScope.() -> Unit
+): SuspendingPointerInputModifierNode {
+    return SuspendingPointerInputModifierNodeImpl(null, null, null, pointerInputHandler)
+}
+
 /**
  * Supports suspending pointer event handling. This is used by [pointerInput], so in most cases you
  * should just use [pointerInput] for suspending pointer input. Creating a
@@ -342,9 +408,9 @@
  * suspending pointer input as part of the implementation of a complex [Modifier.Node].
  */
 fun SuspendingPointerInputModifierNode(
-    pointerInputHandler: suspend PointerInputScope.() -> Unit
+    pointerInputEventHandler: PointerInputEventHandler
 ): SuspendingPointerInputModifierNode {
-    return SuspendingPointerInputModifierNodeImpl(null, null, null, pointerInputHandler)
+    return SuspendingPointerInputModifierNodeImpl(null, null, null, pointerInputEventHandler)
 }
 
 /**
@@ -358,14 +424,35 @@
      * Handler for pointer input events. When changed, any previously executing pointerInputHandler
      * will be canceled.
      */
+    @Deprecated(
+        message = "This property is deprecated. Use 'pointerInputEventHandler' instead.",
+        level = DeprecationLevel.ERROR,
+        replaceWith =
+            ReplaceWith(
+                "pointerInputEventHandler",
+                "androidx.compose.ui.input.pointer." +
+                    "SuspendingPointerInputModifierNode.pointerInputEventHandler"
+            )
+    )
     var pointerInputHandler: suspend PointerInputScope.() -> Unit
 
     /**
+     * Handler for pointer input events. When changed, any previously executing
+     * pointerInputEventHandler will be canceled.
+     */
+    // Supports more dynamic use cases than previous functional type version.
+    // NOTE: If you implement this interface, replace the default implementation. For more
+    // technical details, see aosp/3070509
+    var pointerInputEventHandler: PointerInputEventHandler
+        get() = TODO("pointerInputEventHandler must be implemented (get()).")
+        set(value) = TODO("pointerInputEventHandler must be implemented (set($value)).")
+
+    /**
      * Resets the underlying coroutine used to run the handler for input pointer events. This should
      * be called whenever a large change has been made that forces the gesture detection to be
      * completely invalid.
      *
-     * For example, if [pointerInputHandler] has different modes for detecting a gesture (long
+     * For example, if [pointerInputEventHandler] has different modes for detecting a gesture (long
      * press, double click, etc.), and by switching the modes, any currently-running gestures are no
      * longer valid.
      */
@@ -375,7 +462,7 @@
 /**
  * Implementation notes: This class does a lot of lifting. [PointerInputModifierNode] receives,
  * interprets, and, consumes [PointerInputChange]s while the state (and the coroutineScope used to
- * execute [pointerInputHandler]) is retained in [Modifier.Node].
+ * execute [pointerInputEventHandler]) is retained in [Modifier.Node].
  *
  * [SuspendingPointerInputModifierNodeImpl] implements the [PointerInputScope] used to offer the
  * [Modifier.pointerInput] DSL and provides the [Density] from [LocalDensity] lazily from the layout
@@ -388,49 +475,47 @@
     private var key1: Any? = null,
     private var key2: Any? = null,
     private var keys: Array<out Any?>? = null,
-    pointerInputHandler: suspend PointerInputScope.() -> Unit
+    pointerInputEventHandler: PointerInputEventHandler
 ) : Modifier.Node(), SuspendingPointerInputModifierNode, PointerInputScope, Density {
-
-    internal fun update(
+    @Deprecated("Exists to maintain compatibility with previous API shape")
+    constructor(
         key1: Any?,
         key2: Any?,
         keys: Array<out Any?>?,
-        pointerInputHandler: suspend PointerInputScope.() -> Unit
+        pointerInputEvent: suspend PointerInputScope.() -> Unit
+    ) : this(
+        key1 = key1,
+        key2 = key2,
+        keys = keys,
+        pointerInputEventHandler = PointerInputEventHandler {} // Empty Lambda, not used.
     ) {
-        var needsReset = false
-        if (this.key1 != key1) {
-            needsReset = true
-        }
-        this.key1 = key1
-        if (this.key2 != key2) {
-            needsReset = true
-        }
-        this.key2 = key2
-        if (this.keys != null && keys == null) {
-            needsReset = true
-        }
-        if (this.keys == null && keys != null) {
-            needsReset = true
-        }
-        if (this.keys != null && keys != null && !keys.contentEquals(this.keys)) {
-            needsReset = true
-        }
-        this.keys = keys
-        if (needsReset) {
-            resetPointerInputHandler()
-        }
-        // Avoids calling resetPointerInputHandler when setting this if no keys have changed
-        _pointerInputHandler = pointerInputHandler
+        // If the _deprecatedPointerInputHandler is set, we will use that instead of the
+        // pointerInputEventHandler (why empty lambda above doesn't matter).
+        _deprecatedPointerInputHandler = pointerInputEvent
     }
 
-    private var _pointerInputHandler = pointerInputHandler
+    // Previously used to execute pointer input handlers (now pointerInputEventHandler covers that).
+    // This exists purely for backwards compatibility.
+    private var _deprecatedPointerInputHandler: (suspend PointerInputScope.() -> Unit)? = null
 
-    override var pointerInputHandler
+    // Main handler for pointer input events
+    private var _pointerInputEventHandler = pointerInputEventHandler
+
+    @Deprecated("Super property deprecated")
+    override var pointerInputHandler: suspend PointerInputScope.() -> Unit
+        get() = _deprecatedPointerInputHandler ?: {}
         set(value) {
             resetPointerInputHandler()
-            _pointerInputHandler = value
+            _deprecatedPointerInputHandler = value
         }
-        get() = _pointerInputHandler
+
+    override var pointerInputEventHandler
+        set(value) {
+            resetPointerInputHandler()
+            _deprecatedPointerInputHandler = null
+            _pointerInputEventHandler = value
+        }
+        get() = _pointerInputEventHandler
 
     override val density: Float
         get() = requireLayoutNode().density.density
@@ -507,12 +592,12 @@
     }
 
     /**
-     * This cancels the existing coroutine and essentially resets pointerInputHandler's execution.
-     * Note, the pointerInputHandler still executes lazily, meaning nothing will be done again until
-     * a new event comes in. More details: This is triggered from a LayoutNode if the Density or
-     * ViewConfiguration change (in an older implementation using composed, these values were used
-     * as keys so it would reset everything when either change, we do that manually now through this
-     * function). It is also used for testing.
+     * This cancels the existing coroutine and essentially resets pointerInputEventHandler's
+     * execution. Note, the pointerInputEventHandler still executes lazily, meaning nothing will be
+     * done again until a new event comes in. More details: This is triggered from a LayoutNode if
+     * the Density or ViewConfiguration change (in an older implementation using composed, these
+     * values were used as keys so it would reset everything when either change, we do that manually
+     * now through this function). It is also used for testing.
      */
     override fun resetPointerInputHandler() {
         val localJob = pointerInputJob
@@ -522,6 +607,55 @@
         }
     }
 
+    internal fun update(
+        key1: Any?,
+        key2: Any?,
+        keys: Array<out Any?>?,
+        pointerInputEventHandler: PointerInputEventHandler
+    ) {
+        var needsReset = false
+
+        // key1
+        if (this.key1 != key1) {
+            needsReset = true
+        }
+        this.key1 = key1
+
+        // key2
+        if (this.key2 != key2) {
+            needsReset = true
+        }
+        this.key2 = key2
+
+        // keys
+        if (this.keys != null && keys == null) {
+            needsReset = true
+        }
+        if (this.keys == null && keys != null) {
+            needsReset = true
+        }
+        if (this.keys != null && keys != null && !keys.contentEquals(this.keys)) {
+            needsReset = true
+        }
+        this.keys = keys
+
+        // Lambda literals will have a new instance every time they are executed (even if it is from
+        // the same code location), so we can not use them as a comparison mechanism to avoid
+        // restarting pointer input handlers when they are functionally the same. However, we can
+        // get around this by using a SAM interface and a class comparison instead. (Even though the
+        // instances are different, they will have the same class type.)
+        if (this.pointerInputEventHandler::class != pointerInputEventHandler::class) {
+            needsReset = true
+        }
+
+        // Only reset when keys have changed or pointerInputEventHandler is called from a different
+        // call site (determined by class comparison).
+        if (needsReset) {
+            resetPointerInputHandler()
+        }
+        _pointerInputEventHandler = pointerInputEventHandler
+    }
+
     /**
      * Snapshot the current [pointerHandlers] and run [block] on each one. May not be called
      * reentrant or concurrent with itself.
@@ -570,7 +704,13 @@
         if (pointerInputJob == null) {
             // 'start = CoroutineStart.UNDISPATCHED' required so handler doesn't miss first event.
             pointerInputJob =
-                coroutineScope.launch(start = CoroutineStart.UNDISPATCHED) { pointerInputHandler() }
+                coroutineScope.launch(start = CoroutineStart.UNDISPATCHED) {
+                    if (_deprecatedPointerInputHandler != null) {
+                        _deprecatedPointerInputHandler!!()
+                    } else {
+                        with(pointerInputEventHandler) { invoke() }
+                    }
+                }
         }
 
         dispatchPointerEvent(pointerEvent, pass)
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/util/VelocityTracker.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/util/VelocityTracker.kt
index 0e95d07..f06a924 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/util/VelocityTracker.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/util/VelocityTracker.kt
@@ -45,6 +45,7 @@
  *
  * The quality of the velocity estimation will be better if more data points have been received.
  */
+@OptIn(ExperimentalVelocityTrackerApi::class)
 class VelocityTracker {
 
     private val strategy =
@@ -630,4 +631,14 @@
  */
 @Suppress("GetterSetterNames", "OPT_IN_MARKER_ON_WRONG_TARGET")
 @get:Suppress("GetterSetterNames")
+@get:ExperimentalVelocityTrackerApi
+@set:ExperimentalVelocityTrackerApi
+@ExperimentalVelocityTrackerApi
 var VelocityTrackerStrategyUseImpulse = false
+
+@RequiresOptIn(
+    "This an opt-in flag to test the Velocity Tracker strategy algorithm used " +
+        "for calculating gesture velocities in Compose."
+)
+@Retention(AnnotationRetention.BINARY)
+annotation class ExperimentalVelocityTrackerApi
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt
index e08dbbc..3b7749b 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt
@@ -48,9 +48,6 @@
 import androidx.compose.ui.node.LayoutNode.LayoutState.LookaheadMeasuring
 import androidx.compose.ui.node.LayoutNode.LayoutState.Measuring
 import androidx.compose.ui.node.Nodes.Draw
-import androidx.compose.ui.node.Nodes.FocusEvent
-import androidx.compose.ui.node.Nodes.FocusProperties
-import androidx.compose.ui.node.Nodes.FocusTarget
 import androidx.compose.ui.node.Nodes.PointerInput
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.platform.LocalLayoutDirection
@@ -95,6 +92,8 @@
     InteroperableComposeUiNode,
     Owner.OnLayoutCompletedListener {
 
+    var forceUseOldLayers: Boolean = false
+
     override var compositeKeyHash: Int = 0
 
     internal var isVirtualLookaheadRoot: Boolean = false
@@ -494,9 +493,6 @@
         onAttach?.invoke(owner)
 
         layoutDelegate.updateParentData()
-        if (!isDeactivated) {
-            invalidateFocusOnAttach()
-        }
     }
 
     /**
@@ -1072,16 +1068,6 @@
         requireOwner().requestOnPositionedCallback(this)
     }
 
-    private fun invalidateFocusOnAttach() {
-        if (nodes.has(FocusTarget or FocusProperties or FocusEvent)) {
-            nodes.headToTail {
-                if (it.isKind(FocusTarget) or it.isKind(FocusProperties) or it.isKind(FocusEvent)) {
-                    autoInvalidateInsertedNode(it)
-                }
-            }
-        }
-    }
-
     internal inline fun ignoreRemeasureRequests(block: () -> Unit) {
         ignoreRemeasureRequests = true
         block()
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/MeasureAndLayoutDelegate.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/MeasureAndLayoutDelegate.kt
index 622270a..9972f90 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/MeasureAndLayoutDelegate.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/MeasureAndLayoutDelegate.kt
@@ -51,7 +51,7 @@
         get() = onPositionedDispatcher.isNotEmpty()
 
     /** Flag to indicate that we're currently measuring. */
-    private var duringMeasureLayout = false
+    internal var duringMeasureLayout = false
     /**
      * True when we are currently executing a full measure/layout pass, which mean we will iterate
      * through all the nodes in [relayoutNodes].
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeCoordinator.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeCoordinator.kt
index 77fa83e..a032794 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeCoordinator.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeCoordinator.kt
@@ -480,10 +480,17 @@
             this.layerBlock = layerBlock
             if (layer == null) {
                 layer =
-                    layoutNode.requireOwner().createLayer(drawBlock, invalidateParentLayer).apply {
-                        resize(measuredSize)
-                        move(position)
-                    }
+                    layoutNode
+                        .requireOwner()
+                        .createLayer(
+                            drawBlock,
+                            invalidateParentLayer,
+                            forceUseOldLayers = layoutNode.forceUseOldLayers
+                        )
+                        .apply {
+                            resize(measuredSize)
+                            move(position)
+                        }
                 updateLayerParameters()
                 layoutNode.innerLayerCoordinatorIsDirty = true
                 invalidateParentLayer()
@@ -496,7 +503,7 @@
                 it.destroy()
                 layoutNode.innerLayerCoordinatorIsDirty = true
                 invalidateParentLayer()
-                if (isAttached) {
+                if (isAttached && layoutNode.isPlaced) {
                     layoutNode.owner?.onLayoutChange(layoutNode)
                 }
             }
@@ -505,10 +512,11 @@
         }
     }
 
-    private fun updateLayerParameters(invokeOnLayoutChange: Boolean = true) {
+    /** returns true if some of the positional properties did change. */
+    private fun updateLayerParameters(invokeOnLayoutChange: Boolean = true): Boolean {
         if (explicitLayer != null) {
             // the parameters of the explicit layers are configured differently.
-            return
+            return false
         }
         val layer = layer
         if (layer != null) {
@@ -527,15 +535,23 @@
             val layerPositionalProperties =
                 layerPositionalProperties
                     ?: LayerPositionalProperties().also { layerPositionalProperties = it }
+            tmpLayerPositionalProperties.copyFrom(layerPositionalProperties)
             layerPositionalProperties.copyFrom(graphicsLayerScope)
             layer.updateLayerProperties(graphicsLayerScope)
+            val wasClipping = isClipping
             isClipping = graphicsLayerScope.clip
             lastLayerAlpha = graphicsLayerScope.alpha
-            if (invokeOnLayoutChange) {
+            val positionalPropertiesChanged =
+                !tmpLayerPositionalProperties.hasSameValuesAs(layerPositionalProperties)
+            if (
+                invokeOnLayoutChange && (positionalPropertiesChanged || wasClipping != isClipping)
+            ) {
                 layoutNode.owner?.onLayoutChange(layoutNode)
             }
+            return positionalPropertiesChanged
         } else {
             checkPrecondition(layerBlock == null) { "null layer with a non-null layerBlock" }
+            return false
         }
     }
 
@@ -1292,28 +1308,21 @@
             if (coordinator.isValidOwnerScope) {
                 // coordinator.layerPositionalProperties should always be non-null here, but
                 // we'll just be careful with a null check.
-                // todo how this will be communicated to us in the new impl?
-                val layerPositionalProperties = coordinator.layerPositionalProperties
-                if (layerPositionalProperties == null) {
-                    coordinator.updateLayerParameters()
-                } else {
-                    tmpLayerPositionalProperties.copyFrom(layerPositionalProperties)
-                    coordinator.updateLayerParameters()
-                    if (!tmpLayerPositionalProperties.hasSameValuesAs(layerPositionalProperties)) {
-                        val layoutNode = coordinator.layoutNode
-                        val layoutDelegate = layoutNode.layoutDelegate
-                        if (layoutDelegate.childrenAccessingCoordinatesDuringPlacement > 0) {
-                            if (
-                                layoutDelegate.coordinatesAccessedDuringModifierPlacement ||
-                                    layoutDelegate.coordinatesAccessedDuringPlacement
-                            ) {
-                                layoutNode.requestRelayout()
-                            }
-                            layoutDelegate.measurePassDelegate
-                                .notifyChildrenUsingCoordinatesWhilePlacing()
+                val positionalPropertiesChanged = coordinator.updateLayerParameters()
+                if (positionalPropertiesChanged) {
+                    val layoutNode = coordinator.layoutNode
+                    val layoutDelegate = layoutNode.layoutDelegate
+                    if (layoutDelegate.childrenAccessingCoordinatesDuringPlacement > 0) {
+                        if (
+                            layoutDelegate.coordinatesAccessedDuringModifierPlacement ||
+                                layoutDelegate.coordinatesAccessedDuringPlacement
+                        ) {
+                            layoutNode.requestRelayout()
                         }
-                        layoutNode.owner?.requestOnPositionedCallback(layoutNode)
+                        layoutDelegate.measurePassDelegate
+                            .notifyChildrenUsingCoordinatesWhilePlacing()
                     }
+                    layoutNode.owner?.requestOnPositionedCallback(layoutNode)
                 }
             }
         }
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeKind.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeKind.kt
index 2393af7..044193b 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeKind.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeKind.kt
@@ -315,7 +315,7 @@
         node.invalidateParentData()
     }
     if (Nodes.FocusTarget in selfKindSet && node is FocusTargetNode) {
-        if (phase != Removed) {
+        if (phase == Inserted) {
             node.invalidateFocusTarget()
         }
     }
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/Owner.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/Owner.kt
index 7f93d14..1f93d1c 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/Owner.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/Owner.kt
@@ -244,7 +244,8 @@
     fun createLayer(
         drawBlock: (canvas: Canvas, parentLayer: GraphicsLayer?) -> Unit,
         invalidateParentLayer: () -> Unit,
-        explicitLayer: GraphicsLayer? = null
+        explicitLayer: GraphicsLayer? = null,
+        forceUseOldLayers: Boolean = false
     ): OwnedLayer
 
     /**
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/platform/PlatformTextInputModifierNode.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/platform/PlatformTextInputModifierNode.kt
index 27774fc..3498baf 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/platform/PlatformTextInputModifierNode.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/platform/PlatformTextInputModifierNode.kt
@@ -112,8 +112,11 @@
  * - The session function throws an exception.
  * - The requesting coroutine is cancelled.
  * - Another session is started via this method, either from the same modifier or a different one.
- * - The system closes the connection (currently only supported on Android, and there only depending
- *   on OS version).
+ *   The session may remain open when:
+ * - The system closes the connection. This behavior currently only exists on Android depending on
+ *   OS version. Android platform may intermittently close the active connection to immediately
+ *   start it back again. In these cases the session will not be prematurely closed, so that it can
+ *   serve the follow-up requests.
  *
  * This function should only be called from the modifier node's
  * [coroutineScope][Modifier.Node.coroutineScope]. If it is not, the session will _not_
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsProperties.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsProperties.kt
index 0284257..3d505bd 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsProperties.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsProperties.kt
@@ -670,6 +670,12 @@
          * accessibility: [SemanticsActions.OnClick]
          */
         val DropdownList = Role(6)
+
+        /**
+         * This element is a number picker that a user can perform gesture to adjust and select the
+         * next or previous value.
+         */
+        val NumberPicker = Role(7)
     }
 
     override fun toString() =
@@ -681,6 +687,7 @@
             Tab -> "Tab"
             Image -> "Image"
             DropdownList -> "DropdownList"
+            NumberPicker -> "NumberPicker"
             else -> "Unknown"
         }
 }
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/desktop/TestThread.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/desktop/TestThread.kt
deleted file mode 100644
index 4c62c78..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/desktop/TestThread.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.desktop
-
-internal class TestThread(private val _run: () -> Unit) : Thread() {
-    private var exception: Exception? = null
-
-    override fun run() {
-        try {
-            _run()
-        } catch (e: InterruptedException) {
-            // ignore
-        } catch (e: Exception) {
-            exception = e
-        }
-    }
-
-    fun joinAndThrow() {
-        join()
-        if (exception != null) {
-            throw exception!!
-        }
-    }
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/ComposeSceneTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/ComposeSceneTest.kt
deleted file mode 100644
index 36df49d..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/ComposeSceneTest.kt
+++ /dev/null
@@ -1,570 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui
-
-import androidx.compose.animation.core.LinearEasing
-import androidx.compose.animation.core.TweenSpec
-import androidx.compose.animation.core.animateFloatAsState
-import androidx.compose.foundation.Canvas
-import androidx.compose.foundation.background
-import androidx.compose.foundation.clickable
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.offset
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.lazy.LazyColumn
-import androidx.compose.foundation.lazy.LazyListState
-import androidx.compose.foundation.lazy.items
-import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material.Surface
-import androidx.compose.material.TextField
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.draw.clipToBounds
-import androidx.compose.ui.focus.FocusRequester
-import androidx.compose.ui.focus.FocusState
-import androidx.compose.ui.focus.focusProperties
-import androidx.compose.ui.focus.focusRequester
-import androidx.compose.ui.focus.onFocusChanged
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.geometry.Size
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.graphicsLayer
-import androidx.compose.ui.input.key.Key
-import androidx.compose.ui.input.key.KeyEventType
-import androidx.compose.ui.input.key.keyEvent
-import androidx.compose.ui.input.pointer.AwaitPointerEventScope
-import androidx.compose.ui.input.pointer.PointerButtons
-import androidx.compose.ui.input.pointer.PointerEvent
-import androidx.compose.ui.input.pointer.PointerEventType
-import androidx.compose.ui.input.pointer.PointerKeyboardModifiers
-import androidx.compose.ui.input.pointer.pointerInput
-import androidx.compose.ui.layout.Layout
-import androidx.compose.ui.platform.renderingTest
-import androidx.compose.ui.test.InternalTestApi
-import androidx.compose.ui.test.junit4.DesktopScreenshotTestRule
-import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.compose.ui.test.onRoot
-import androidx.compose.ui.test.performKeyPress
-import androidx.compose.ui.unit.dp
-import com.google.common.truth.Truth.assertThat
-import java.awt.event.KeyEvent
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.runBlocking
-import org.junit.Assert.assertFalse
-import org.junit.Ignore
-import org.junit.Rule
-import org.junit.Test
-
-@OptIn(InternalTestApi::class)
-class ComposeSceneTest {
-    @get:Rule val screenshotRule = DesktopScreenshotTestRule("compose/ui/ui-desktop")
-
-    @get:Rule val composeRule = createComposeRule()
-
-    @Test(timeout = 5000)
-    fun `rendering of Box state change`() =
-        renderingTest(width = 40, height = 40) {
-            var size by mutableStateOf(20.dp)
-            setContent { Box(Modifier.size(size).background(Color.Blue)) }
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame1_initial_size_20")
-            assertFalse(hasRenders())
-
-            size = 10.dp
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame2_change_size_to_10")
-            assertFalse(hasRenders())
-
-            size = 5.dp
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame3_change_size_to_5")
-            assertFalse(hasRenders())
-
-            size = 10.dp
-            size = 20.dp
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame4_change_size_to_10_and_20")
-            assertFalse(hasRenders())
-
-            size = 20.dp
-            assertFalse(hasRenders())
-        }
-
-    @Test(timeout = 5000)
-    fun `rendering of Canvas state change`() =
-        renderingTest(width = 40, height = 40) {
-            var x by mutableStateOf(0f)
-            var clipToBounds by mutableStateOf(false)
-            setContent {
-                val modifier =
-                    if (clipToBounds) {
-                        Modifier.size(20.dp).clipToBounds()
-                    } else {
-                        Modifier.size(20.dp)
-                    }
-                Canvas(modifier) {
-                    drawRect(color = Color.Red, topLeft = Offset(x, 0f), size = Size(10f, 10f))
-                }
-            }
-
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame1_initial")
-            assertFalse(hasRenders())
-
-            x = 15f
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame2_translate")
-            assertFalse(hasRenders())
-
-            clipToBounds = true
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame3_clipToBounds")
-            assertFalse(hasRenders())
-        }
-
-    @Test(timeout = 5000)
-    fun `rendering of Layout state change`() =
-        renderingTest(width = 40, height = 40) {
-            var width by mutableStateOf(10)
-            var height by mutableStateOf(20)
-            var x by mutableStateOf(0)
-            setContent {
-                Row(Modifier.height(height.dp)) {
-                    Layout({ Box(Modifier.fillMaxSize().background(Color.Green)) }) {
-                        measureables,
-                        constraints ->
-                        val placeables = measureables.map { it.measure(constraints) }
-                        layout(width, constraints.maxHeight) {
-                            placeables.forEach { it.place(x, 0) }
-                        }
-                    }
-
-                    Box(Modifier.background(Color.Red).size(10.dp))
-                }
-            }
-
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame1_initial")
-            assertFalse(hasRenders())
-
-            width = 20
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame2_change_width")
-            assertFalse(hasRenders())
-
-            x = 10
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame3_change_x")
-            assertFalse(hasRenders())
-
-            height = 10
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame4_change_height")
-            assertFalse(hasRenders())
-
-            width = 10
-            height = 20
-            x = 0
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame5_change_all")
-            assertFalse(hasRenders())
-
-            width = 10
-            height = 20
-            x = 0
-            assertFalse(hasRenders())
-        }
-
-    @Test(timeout = 5000)
-    fun `rendering of layer offset`() =
-        renderingTest(width = 40, height = 40) {
-            var translationX by mutableStateOf(10f)
-            var offsetX by mutableStateOf(10.dp)
-            setContent {
-                Box(Modifier.offset(x = offsetX).graphicsLayer(translationX = translationX)) {
-                    Box(Modifier.background(Color.Green).size(10.dp))
-                }
-            }
-
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame1_initial")
-            assertFalse(hasRenders())
-
-            offsetX -= 10.dp
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame2_offset")
-            assertFalse(hasRenders())
-
-            translationX -= 10f
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame3_translation")
-            assertFalse(hasRenders())
-
-            offsetX += 10.dp
-            translationX += 10f
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame4_offset_and_translation")
-            assertFalse(hasRenders())
-        }
-
-    @Test(timeout = 5000)
-    fun `rendering of transition`() =
-        renderingTest(width = 40, height = 40) {
-            val startValue = 10f
-            var targetValue by mutableStateOf(startValue)
-            var lastComposedValue = Float.MIN_VALUE
-
-            setContent {
-                val value by
-                    animateFloatAsState(
-                        targetValue,
-                        animationSpec = TweenSpec(durationMillis = 30, easing = LinearEasing)
-                    )
-                Box(Modifier.size(value.dp).background(Color.Blue))
-                lastComposedValue = value
-            }
-
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame1_initial")
-
-            targetValue = 40f
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame2_target40_0ms")
-
-            // animation can start not immediately, but on the second/third frame
-            // so wait when the animation will change the animating value
-            while (lastComposedValue == startValue) {
-                currentTimeMillis += 10
-                awaitNextRender()
-            }
-
-            screenshotRule.snap(surface, "frame3_target40_10ms")
-
-            currentTimeMillis += 10
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame4_target40_20ms")
-
-            currentTimeMillis += 10
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame5_target40_30ms")
-
-            assertFalse(hasRenders())
-        }
-
-    @Test(timeout = 5000)
-    @Ignore("b/271123970 Fails in AOSP. Will be fixed after upstreaming Compose for Desktop")
-    fun `rendering of clickable`() =
-        renderingTest(width = 40, height = 40) {
-            setContent { Box(Modifier.size(20.dp).background(Color.Blue).clickable {}) }
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame1_initial")
-            assertFalse(hasRenders())
-
-            scene.sendPointerEvent(PointerEventType.Press, Offset(2f, 2f))
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame2_onMousePressed")
-            assertFalse(hasRenders())
-
-            scene.sendPointerEvent(PointerEventType.Move, Offset(1f, 1f))
-            assertFalse(hasRenders())
-
-            scene.sendPointerEvent(PointerEventType.Release, Offset(1f, 1f))
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame3_onMouseReleased")
-
-            scene.sendPointerEvent(PointerEventType.Move, Offset(1f, 1f))
-            scene.sendPointerEvent(PointerEventType.Press, Offset(3f, 3f))
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame4_onMouseMoved_onMousePressed")
-            assertFalse(hasRenders())
-        }
-
-    @Test(timeout = 5000)
-    @Ignore("b/271123970 Fails in AOSP. Will be fixed after upstreaming Compose for Desktop")
-    fun `rendering of LazyColumn`() =
-        renderingTest(width = 40, height = 40) {
-            var itemHeight by mutableStateOf(10.dp)
-            val padding = 10
-            val columnHeight = this.height - padding * 2
-            val state = LazyListState()
-            setContent {
-                Box(Modifier.padding(padding.dp)) {
-                    LazyColumn(state = state) {
-                        items(
-                            listOf(Color.Red, Color.Green, Color.Blue, Color.Black, Color.Gray)
-                        ) { color ->
-                            Box(Modifier.size(width = 30.dp, height = itemHeight).background(color))
-                        }
-                    }
-                }
-            }
-
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame1_initial")
-            assertFalse(hasRenders())
-
-            state.scroll { scrollBy(columnHeight.toFloat()) }
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame2_onMouseScroll")
-            assertFalse(hasRenders())
-
-            state.scroll { scrollBy(10 * columnHeight.toFloat()) }
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame3_onMouseScroll")
-            assertFalse(hasRenders())
-
-            itemHeight = 5.dp
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame4_change_height")
-            assertFalse(hasRenders())
-        }
-
-    @Test(timeout = 5000)
-    fun `rendering, change state before first onRender`() =
-        renderingTest(width = 40, height = 40) {
-            var size by mutableStateOf(20.dp)
-            setContent { Box(Modifier.size(size).background(Color.Blue)) }
-
-            size = 10.dp
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame1_initial")
-            assertFalse(hasRenders())
-        }
-
-    @Test(timeout = 5000)
-    fun `launch effect`() =
-        renderingTest(width = 40, height = 40) {
-            var effectIsLaunched = false
-
-            setContent { LaunchedEffect(Unit) { effectIsLaunched = true } }
-
-            awaitNextRender()
-            assertThat(effectIsLaunched).isTrue()
-        }
-
-    @Test(timeout = 5000)
-    fun `change density`() =
-        renderingTest(width = 40, height = 40) {
-            @Composable
-            fun redRect() {
-                Box(Modifier.size(4.dp).background(Color.Red))
-            }
-
-            @Composable
-            fun greenRectOnCanvas() {
-                Canvas(Modifier.size(100.dp)) {
-                    drawRect(
-                        Color.Green,
-                        topLeft = Offset(4f * density, 4f * density),
-                        size = Size(4f * density, 4f * density)
-                    )
-                }
-            }
-
-            @Composable
-            fun blueRectInRoundedLayer() {
-                Box(
-                    Modifier.offset(8.dp, 8.dp)
-                        .graphicsLayer(shape = RoundedCornerShape(2.dp), clip = true)
-                ) {
-                    Box(Modifier.size(4.dp).background(Color.Blue))
-                }
-            }
-
-            @Composable
-            fun elevation() {
-                Box(Modifier.offset(8.dp, 0.dp)) {
-                    Surface(modifier = Modifier.size(4.dp), elevation = 2.dp) {}
-                }
-            }
-
-            setContent {
-                redRect()
-                greenRectOnCanvas()
-                blueRectInRoundedLayer()
-                elevation()
-            }
-
-            density = 2f
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame1_density2")
-
-            density = 3f
-            awaitNextRender()
-            screenshotRule.snap(surface, "frame2_density3")
-
-            assertFalse(hasRenders())
-        }
-
-    @Test(timeout = 5000)
-    fun `receive buttons`() =
-        renderingTest(width = 40, height = 40, context = Dispatchers.Unconfined) {
-            val receivedButtons = mutableListOf<PointerButtons>()
-
-            setContent {
-                Box(
-                    Modifier.size(40.dp).onPointerEvent(PointerEventType.Press) {
-                        receivedButtons.add(it.buttons)
-                    }
-                )
-            }
-
-            var buttons = PointerButtons(isSecondaryPressed = true, isBackPressed = true)
-            scene.sendPointerEvent(PointerEventType.Press, Offset(0f, 0f), buttons = buttons)
-            assertThat(receivedButtons.size).isEqualTo(1)
-            assertThat(receivedButtons.last()).isEqualTo(buttons)
-
-            buttons =
-                PointerButtons(
-                    isPrimaryPressed = true,
-                    isTertiaryPressed = true,
-                    isForwardPressed = true
-                )
-            scene.sendPointerEvent(PointerEventType.Press, Offset(0f, 0f), buttons = buttons)
-            assertThat(receivedButtons.size).isEqualTo(2)
-            assertThat(receivedButtons.last()).isEqualTo(buttons)
-        }
-
-    @Test(timeout = 5000)
-    fun `receive modifiers`() =
-        renderingTest(width = 40, height = 40, context = Dispatchers.Unconfined) {
-            val receivedKeyboardModifiers = mutableListOf<PointerKeyboardModifiers>()
-
-            setContent {
-                Box(
-                    Modifier.size(40.dp).onPointerEvent(PointerEventType.Press) {
-                        receivedKeyboardModifiers.add(it.keyboardModifiers)
-                    }
-                )
-            }
-
-            var keyboardModifiers = PointerKeyboardModifiers(isAltPressed = true)
-            scene.sendPointerEvent(
-                PointerEventType.Press,
-                Offset(0f, 0f),
-                keyboardModifiers = keyboardModifiers
-            )
-            assertThat(receivedKeyboardModifiers.size).isEqualTo(1)
-            assertThat(receivedKeyboardModifiers.last()).isEqualTo(keyboardModifiers)
-
-            keyboardModifiers =
-                PointerKeyboardModifiers(
-                    isCtrlPressed = true,
-                    isMetaPressed = true,
-                    isAltPressed = false,
-                    isShiftPressed = true,
-                    isAltGraphPressed = true,
-                    isSymPressed = true,
-                    isFunctionPressed = true,
-                    isCapsLockOn = true,
-                    isScrollLockOn = true,
-                    isNumLockOn = true,
-                )
-            scene.sendPointerEvent(
-                PointerEventType.Press,
-                Offset(0f, 0f),
-                keyboardModifiers = keyboardModifiers
-            )
-            assertThat(receivedKeyboardModifiers.size).isEqualTo(2)
-            assertThat(receivedKeyboardModifiers.last()).isEqualTo(keyboardModifiers)
-        }
-
-    @Test(expected = TestException::class)
-    fun `catch exception in LaunchedEffect`() {
-        runBlocking(Dispatchers.Main) {
-            composeRule.setContent { LaunchedEffect(Unit) { throw TestException() } }
-            composeRule.awaitIdle()
-        }
-    }
-
-    private class TestException : RuntimeException()
-
-    @Test
-    fun `focus management by keys`() {
-        var field1FocusState: FocusState? = null
-        var field2FocusState: FocusState? = null
-        val (focusItem1, focusItem2) = FocusRequester.createRefs()
-        composeRule.setContent {
-            var text by remember { mutableStateOf("") }
-            Row {
-                TextField(
-                    text,
-                    onValueChange = { text = it },
-                    maxLines = 1,
-                    modifier =
-                        Modifier.onFocusChanged { field1FocusState = it }
-                            .focusRequester(focusItem1)
-                            .focusProperties { next = focusItem2 }
-                )
-                TextField(
-                    text,
-                    onValueChange = { text = it },
-                    maxLines = 1,
-                    modifier =
-                        Modifier.onFocusChanged { field2FocusState = it }
-                            .focusRequester(focusItem2)
-                            .focusProperties { previous = focusItem1 }
-                )
-            }
-        }
-        composeRule.runOnIdle { focusItem1.requestFocus() }
-
-        composeRule.runOnIdle {
-            assertThat(field1FocusState!!.isFocused).isTrue()
-            assertThat(field2FocusState!!.isFocused).isFalse()
-        }
-
-        composeRule.onRoot().performKeyPress(keyEvent(Key.Tab, KeyEventType.KeyDown))
-
-        composeRule.runOnIdle {
-            assertThat(field1FocusState!!.isFocused).isFalse()
-            assertThat(field2FocusState!!.isFocused).isTrue()
-        }
-
-        composeRule
-            .onRoot()
-            .performKeyPress(keyEvent(Key.Tab, KeyEventType.KeyDown, KeyEvent.SHIFT_DOWN_MASK))
-
-        composeRule.runOnIdle {
-            assertThat(field1FocusState!!.isFocused).isTrue()
-            assertThat(field2FocusState!!.isFocused).isFalse()
-        }
-    }
-
-    private fun Modifier.onPointerEvent(
-        eventType: PointerEventType,
-        onEvent: AwaitPointerEventScope.(event: PointerEvent) -> Unit
-    ) =
-        pointerInput(eventType, onEvent) {
-            awaitPointerEventScope {
-                while (true) {
-                    val event = awaitPointerEvent()
-                    if (event.type == eventType) {
-                        onEvent(event)
-                    }
-                }
-            }
-        }
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/LeakDetector.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/LeakDetector.kt
deleted file mode 100644
index b7819c6..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/LeakDetector.kt
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui
-
-import java.lang.ref.WeakReference
-
-// similar to leanback/leanback/src/androidTest/java/androidx/leanback/testutils/LeakDetector.java
-class LeakDetector {
-    private val weakReferences = ArrayList<WeakReference<*>>()
-
-    fun observeObject(obj: Any) {
-        weakReferences.add(WeakReference(obj))
-    }
-
-    fun noLeak(): Boolean {
-        System.gc()
-        @Suppress("deprecation") // b/316643753
-        System.runFinalization()
-        for (weakReference in weakReferences) {
-            var count = 0
-            while (weakReference.get() != null && count < 5) {
-                System.gc()
-                @Suppress("deprecation") // b/316643753
-                System.runFinalization()
-                Thread.sleep(1000)
-                count++
-            }
-
-            if (weakReference.get() != null) {
-                return false
-            }
-        }
-        return true
-    }
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/TestUtils.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/TestUtils.kt
deleted file mode 100644
index 183e4da..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/TestUtils.kt
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui
-
-import androidx.compose.ui.graphics.Canvas
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.ImageBitmap
-import androidx.compose.ui.graphics.Paint
-import androidx.compose.ui.graphics.painter.BitmapPainter
-import androidx.compose.ui.graphics.painter.Painter
-import java.awt.Image
-import java.awt.Window
-import java.awt.event.KeyEvent
-import java.awt.event.MouseEvent
-import java.awt.event.MouseWheelEvent
-import java.awt.image.BufferedImage
-import java.awt.image.MultiResolutionImage
-import javax.swing.Icon
-import javax.swing.ImageIcon
-import javax.swing.JFrame
-
-fun testImage(color: Color): Painter = run {
-    val bitmap = ImageBitmap(100, 100)
-    val paint = Paint().apply { this.color = color }
-    Canvas(bitmap).drawRect(0f, 0f, 100f, 100f, paint)
-    BitmapPainter(bitmap)
-}
-
-fun Image.readFirstPixel(): Color {
-    val image = (this as MultiResolutionImage).getResolutionVariant(1.0, 1.0) as BufferedImage
-    return Color(image.getRGB(0, 0))
-}
-
-fun Icon.readFirstPixel() = (this as ImageIcon).image.readFirstPixel()
-
-private val os = System.getProperty("os.name").lowercase()
-internal val isLinux = os.startsWith("linux")
-internal val isWindows = os.startsWith("win")
-internal val isMacOs = os.startsWith("mac")
-
-fun Window.sendKeyEvent(code: Int, modifiers: Int = 0): Boolean {
-    val event =
-        KeyEvent(
-            // if we would just use `focusOwner` then it will be null if the window is minimized
-            mostRecentFocusOwner,
-            KeyEvent.KEY_PRESSED,
-            0,
-            modifiers,
-            code,
-            code.toChar(),
-            KeyEvent.KEY_LOCATION_STANDARD
-        )
-    dispatchEvent(event)
-    return event.isConsumed
-}
-
-fun JFrame.sendMouseEvent(id: Int, x: Int, y: Int, modifiers: Int = 0): Boolean {
-    // we use width and height instead of x and y because we can send (-1, -1), but still need
-    // the component inside window
-    val component = findComponentAt(width / 2, height / 2)
-    val event = MouseEvent(component, id, 0, modifiers, x, y, 1, false)
-    component.dispatchEvent(event)
-    return event.isConsumed
-}
-
-fun JFrame.sendMouseWheelEvent(
-    id: Int,
-    x: Int,
-    y: Int,
-    scrollType: Int,
-    wheelRotation: Int,
-    modifiers: Int = 0,
-): Boolean {
-    // we use width and height instead of x and y because we can send (-1, -1), but still need
-    // the component inside window
-    val component = findComponentAt(width / 2, height / 2)
-    val event =
-        MouseWheelEvent(component, id, 0, modifiers, x, y, 1, false, scrollType, 1, wheelRotation)
-    component.dispatchEvent(event)
-    return event.isConsumed
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/awt/ComposePanelTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/awt/ComposePanelTest.kt
deleted file mode 100644
index 2f07f1e..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/awt/ComposePanelTest.kt
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package androidx.compose.ui.awt
-
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.requiredSize
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.layout.layout
-import androidx.compose.ui.unit.Constraints
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.window.density
-import com.google.common.truth.Truth.assertThat
-import java.awt.Dimension
-import java.awt.GraphicsEnvironment
-import javax.swing.JFrame
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.swing.Swing
-import org.junit.Assume
-import org.junit.Test
-
-class ComposePanelTest {
-    @Test
-    fun `don't override user preferred size`() {
-        Assume.assumeFalse(GraphicsEnvironment.getLocalGraphicsEnvironment().isHeadlessInstance)
-
-        runBlocking(Dispatchers.Swing) {
-            val composePanel = ComposePanel()
-            composePanel.preferredSize = Dimension(234, 345)
-            assertThat(composePanel.preferredSize).isEqualTo(Dimension(234, 345))
-
-            val frame = JFrame()
-            try {
-                frame.contentPane.add(composePanel)
-                frame.isUndecorated = true
-
-                assertThat(composePanel.preferredSize).isEqualTo(Dimension(234, 345))
-
-                frame.pack()
-                assertThat(composePanel.size).isEqualTo(Dimension(234, 345))
-                assertThat(frame.size).isEqualTo(Dimension(234, 345))
-            } finally {
-                frame.dispose()
-            }
-        }
-    }
-
-    @Test
-    fun `pack to Compose content`() {
-        Assume.assumeFalse(GraphicsEnvironment.getLocalGraphicsEnvironment().isHeadlessInstance)
-
-        runBlocking(Dispatchers.Swing) {
-            val composePanel = ComposePanel()
-            composePanel.setContent { Box(Modifier.requiredSize(300.dp, 400.dp)) }
-
-            val frame = JFrame()
-            try {
-                frame.contentPane.add(composePanel)
-                frame.isUndecorated = true
-
-                frame.pack()
-                assertThat(composePanel.preferredSize).isEqualTo(Dimension(300, 400))
-                assertThat(frame.preferredSize).isEqualTo(Dimension(300, 400))
-
-                frame.isVisible = true
-                assertThat(composePanel.preferredSize).isEqualTo(Dimension(300, 400))
-                assertThat(frame.preferredSize).isEqualTo(Dimension(300, 400))
-            } finally {
-                frame.dispose()
-            }
-        }
-    }
-
-    @Test
-    fun `a single layout pass at the window start`() {
-        Assume.assumeFalse(GraphicsEnvironment.getLocalGraphicsEnvironment().isHeadlessInstance)
-
-        val layoutPassConstraints = mutableListOf<Constraints>()
-
-        runBlocking(Dispatchers.Swing) {
-            val composePanel = ComposePanel()
-            composePanel.setContent {
-                Box(
-                    Modifier.fillMaxSize().layout { _, constraints ->
-                        layoutPassConstraints.add(constraints)
-                        layout(0, 0) {}
-                    }
-                )
-            }
-
-            val frame = JFrame()
-            try {
-                frame.contentPane.add(composePanel)
-                frame.size = Dimension(300, 400)
-                frame.isUndecorated = true
-                frame.isVisible = true
-                frame.paint(frame.graphics)
-
-                assertThat(layoutPassConstraints)
-                    .isEqualTo(
-                        listOf(
-                            Constraints.fixed(
-                                width = (300 * frame.density.density).toInt(),
-                                height = (400 * frame.density.density).toInt()
-                            )
-                        )
-                    )
-            } finally {
-                frame.dispose()
-            }
-        }
-    }
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/awt/ComposeWindowTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/awt/ComposeWindowTest.kt
deleted file mode 100644
index c0a859e..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/awt/ComposeWindowTest.kt
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package androidx.compose.ui.awt
-
-import androidx.compose.foundation.background
-import androidx.compose.foundation.clickable
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.requiredSize
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.layout.layout
-import androidx.compose.ui.sendMouseEvent
-import androidx.compose.ui.unit.Constraints
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.window.density
-import androidx.compose.ui.window.runApplicationTest
-import com.google.common.truth.Truth.assertThat
-import java.awt.Dimension
-import java.awt.GraphicsEnvironment
-import java.awt.event.MouseEvent.BUTTON1_DOWN_MASK
-import java.awt.event.MouseEvent.MOUSE_ENTERED
-import java.awt.event.MouseEvent.MOUSE_MOVED
-import java.awt.event.MouseEvent.MOUSE_PRESSED
-import java.awt.event.MouseEvent.MOUSE_RELEASED
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.swing.Swing
-import org.junit.Assume
-import org.junit.Test
-
-class ComposeWindowTest {
-    // bug https://github.com/JetBrains/compose-jb/issues/1448
-    @Test
-    fun `dispose window inside event handler`() = runApplicationTest {
-        var isClickHappened = false
-
-        val window = ComposeWindow()
-        window.isUndecorated = true
-        window.size = Dimension(200, 200)
-        window.setContent {
-            Box(
-                modifier =
-                    Modifier.fillMaxSize().background(Color.Blue).clickable {
-                        isClickHappened = true
-                        window.dispose()
-                    }
-            )
-        }
-
-        window.isVisible = true
-        awaitIdle()
-
-        window.sendMouseEvent(MOUSE_PRESSED, x = 100, y = 50)
-        window.sendMouseEvent(MOUSE_RELEASED, x = 100, y = 50)
-        awaitIdle()
-
-        assertThat(isClickHappened).isTrue()
-    }
-
-    @Test
-    fun `don't override user preferred size`() {
-        Assume.assumeFalse(GraphicsEnvironment.getLocalGraphicsEnvironment().isHeadlessInstance)
-
-        runBlocking(Dispatchers.Swing) {
-            val window = ComposeWindow()
-            try {
-                window.preferredSize = Dimension(234, 345)
-                window.isUndecorated = true
-                assertThat(window.preferredSize).isEqualTo(Dimension(234, 345))
-                window.pack()
-                assertThat(window.size).isEqualTo(Dimension(234, 345))
-            } finally {
-                window.dispose()
-            }
-        }
-    }
-
-    @Test
-    fun `pack to Compose content`() {
-        Assume.assumeFalse(GraphicsEnvironment.getLocalGraphicsEnvironment().isHeadlessInstance)
-
-        runBlocking(Dispatchers.Swing) {
-            val window = ComposeWindow()
-            try {
-                window.setContent { Box(Modifier.requiredSize(300.dp, 400.dp)) }
-                window.isUndecorated = true
-
-                window.pack()
-                assertThat(window.preferredSize).isEqualTo(Dimension(300, 400))
-                assertThat(window.size).isEqualTo(Dimension(300, 400))
-
-                window.isVisible = true
-                assertThat(window.preferredSize).isEqualTo(Dimension(300, 400))
-                assertThat(window.size).isEqualTo(Dimension(300, 400))
-            } finally {
-                window.dispose()
-            }
-        }
-    }
-
-    @Test
-    fun `a single layout pass at the window start`() {
-        Assume.assumeFalse(GraphicsEnvironment.getLocalGraphicsEnvironment().isHeadlessInstance)
-
-        val layoutPassConstraints = mutableListOf<Constraints>()
-
-        runBlocking(Dispatchers.Swing) {
-            val window = ComposeWindow()
-            try {
-                window.size = Dimension(300, 400)
-                window.setContent {
-                    Box(
-                        Modifier.fillMaxSize().layout { _, constraints ->
-                            layoutPassConstraints.add(constraints)
-                            layout(0, 0) {}
-                        }
-                    )
-                }
-
-                window.isUndecorated = true
-                window.isVisible = true
-                window.paint(window.graphics)
-                assertThat(layoutPassConstraints)
-                    .isEqualTo(
-                        listOf(
-                            Constraints.fixed(
-                                width = (300 * window.density.density).toInt(),
-                                height = (400 * window.density.density).toInt(),
-                            )
-                        )
-                    )
-            } finally {
-                window.dispose()
-            }
-        }
-    }
-
-    @Test
-    fun `dispose window in event handler`() = runApplicationTest {
-        val window = ComposeWindow()
-        try {
-            window.size = Dimension(300, 400)
-            window.setContent {
-                Box(
-                    modifier =
-                        Modifier.fillMaxSize().background(Color.Blue).clickable { window.dispose() }
-                )
-            }
-            window.isVisible = true
-            window.sendMouseEvent(MOUSE_ENTERED, x = 100, y = 50)
-            awaitIdle()
-            window.sendMouseEvent(MOUSE_MOVED, x = 100, y = 50)
-            awaitIdle()
-            window.sendMouseEvent(MOUSE_PRESSED, x = 100, y = 50, modifiers = BUTTON1_DOWN_MASK)
-            awaitIdle()
-            window.sendMouseEvent(MOUSE_RELEASED, x = 100, y = 50)
-            awaitIdle()
-        } finally {
-            window.dispose()
-        }
-    }
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/draw/DesktopDrawingPrebuiltGraphicsLayerTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/draw/DesktopDrawingPrebuiltGraphicsLayerTest.kt
deleted file mode 100644
index 69bf820..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/draw/DesktopDrawingPrebuiltGraphicsLayerTest.kt
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.draw
-
-import androidx.compose.foundation.Canvas
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.size
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.GraphicsContext
-import androidx.compose.ui.graphics.ImageBitmap
-import androidx.compose.ui.graphics.PixelMap
-import androidx.compose.ui.graphics.compositeOver
-import androidx.compose.ui.graphics.graphicsLayer
-import androidx.compose.ui.graphics.layer.GraphicsLayer
-import androidx.compose.ui.graphics.layer.drawLayer
-import androidx.compose.ui.graphics.rememberGraphicsLayer
-import androidx.compose.ui.graphics.toComposeImageBitmap
-import androidx.compose.ui.graphics.toPixelMap
-import androidx.compose.ui.platform.LocalGraphicsContext
-import androidx.compose.ui.platform.testTag
-import androidx.compose.ui.test.InternalTestApi
-import androidx.compose.ui.test.SemanticsNodeInteraction
-import androidx.compose.ui.test.getBoundsInRoot
-import androidx.compose.ui.test.junit4.DesktopComposeTestRule
-import androidx.compose.ui.test.onNodeWithTag
-import androidx.compose.ui.unit.IntOffset
-import androidx.compose.ui.unit.IntSize
-import com.google.common.truth.Truth
-import org.jetbrains.skia.IRect
-import org.jetbrains.skia.Surface
-import org.junit.After
-import org.junit.Assert
-import org.junit.Ignore
-import org.junit.Rule
-import org.junit.Test
-
-@OptIn(InternalTestApi::class)
-class DesktopDrawingPrebuiltGraphicsLayerTest {
-
-    @get:Rule val rule = DesktopComposeTestRule()
-
-    private val size = 2
-    private val sizeDp = with(rule.density) { size.toDp() }
-    private val expectedSize = IntSize(size, size)
-
-    private var layer: GraphicsLayer? = null
-    private var context: GraphicsContext? = null
-    private var drawPrebuiltLayer by mutableStateOf(false)
-
-    @After
-    fun releaseLayer() {
-        rule.runOnUiThread {
-            layer?.let { context!!.releaseGraphicsLayer(it) }
-            layer = null
-        }
-    }
-
-    @Test
-    fun continueDrawingPrebuiltLayer() {
-        rule.setContent {
-            if (!drawPrebuiltLayer) {
-                ColoredBox()
-            } else {
-                LayerDrawingBox()
-            }
-        }
-
-        rule.runOnIdle { drawPrebuiltLayer = true }
-
-        rule.onNodeWithTag(LayerDrawingBoxTag).captureToImage().assertPixels(expectedSize) {
-            Color.Red
-        }
-    }
-
-    @Test
-    fun sizeIsCorrect() {
-        rule.setContent { ColoredBox() }
-
-        rule.runOnIdle { Truth.assertThat(layer!!.size).isEqualTo(IntSize(size, size)) }
-    }
-
-    @Test
-    fun drawingWithAlpha() {
-        rule.setContent {
-            if (!drawPrebuiltLayer) {
-                ColoredBox()
-            } else {
-                LayerDrawingBox()
-            }
-        }
-
-        rule.runOnIdle {
-            drawPrebuiltLayer = true
-            layer!!.alpha = 0.5f
-        }
-
-        rule.onNodeWithTag(LayerDrawingBoxTag).captureToImage().assertPixels(expectedSize) {
-            Color.Red.copy(alpha = 0.5f).compositeOver(Color.White)
-        }
-    }
-
-    @Ignore("b/329262831")
-    @Test
-    fun keepComposingTheNodeWeTookLayerFrom() {
-        var color by mutableStateOf(Color.Blue)
-
-        rule.setContent {
-            Column {
-                ColoredBox(color = { color })
-                if (drawPrebuiltLayer) {
-                    LayerDrawingBox()
-                }
-            }
-        }
-
-        rule.runOnIdle { drawPrebuiltLayer = true }
-
-        rule.onNodeWithTag(ColoredBoxTag).captureToImage().assertPixels(expectedSize) { Color.Blue }
-        rule.onNodeWithTag(LayerDrawingBoxTag).captureToImage().assertPixels(expectedSize) {
-            Color.Blue
-        }
-
-        rule.runOnUiThread { color = Color.Green }
-
-        rule.onNodeWithTag(ColoredBoxTag).captureToImage().assertPixels(expectedSize) {
-            Color.Green
-        }
-        rule.onNodeWithTag(LayerDrawingBoxTag).captureToImage().assertPixels(expectedSize) {
-            Color.Green
-        }
-    }
-
-    @Test
-    fun drawNestedLayers_drawLayer() {
-        rule.setContent {
-            if (!drawPrebuiltLayer) {
-                Box(Modifier.drawIntoLayer()) {
-                    Canvas(Modifier.size(sizeDp).drawIntoLayer(rememberGraphicsLayer())) {
-                        drawRect(Color.Red)
-                    }
-                }
-            } else {
-                LayerDrawingBox()
-            }
-        }
-
-        rule.runOnIdle { drawPrebuiltLayer = true }
-
-        rule.onNodeWithTag(LayerDrawingBoxTag).captureToImage().assertPixels(expectedSize) {
-            Color.Red
-        }
-    }
-
-    @Test
-    fun keepDrawingNestedLayers_drawLayer_deeper() {
-        rule.setContent {
-            if (!drawPrebuiltLayer) {
-                Box(Modifier.drawIntoLayer()) {
-                    Box(Modifier.drawIntoLayer(rememberGraphicsLayer())) {
-                        Canvas(Modifier.size(sizeDp).drawIntoLayer(rememberGraphicsLayer())) {
-                            drawRect(Color.Red)
-                        }
-                    }
-                }
-            } else {
-                LayerDrawingBox()
-            }
-        }
-
-        rule.runOnIdle { drawPrebuiltLayer = true }
-
-        rule.onNodeWithTag(LayerDrawingBoxTag).captureToImage().assertPixels(expectedSize) {
-            Color.Red
-        }
-    }
-
-    @Ignore("remove annotation when Modifier.graphicsLayer() will use the same layer mechanism")
-    @Test
-    fun keepDrawingNestedLayers_graphicsLayerModifier() {
-        rule.setContent {
-            if (!drawPrebuiltLayer) {
-                Box(Modifier.drawIntoLayer()) {
-                    Box(Modifier.graphicsLayer()) {
-                        Canvas(Modifier.size(sizeDp).graphicsLayer()) { drawRect(Color.Red) }
-                    }
-                }
-            } else {
-                LayerDrawingBox()
-            }
-        }
-
-        rule.runOnIdle { drawPrebuiltLayer = true }
-
-        rule.onNodeWithTag(LayerDrawingBoxTag).captureToImage().assertPixels(expectedSize) {
-            Color.Red
-        }
-    }
-
-    @Test
-    fun keepDrawingLayerFromANodeScheduledForInvalidation() {
-        val counter = mutableStateOf(0)
-        rule.setContent {
-            if (!drawPrebuiltLayer) {
-                ColoredBox(
-                    color = {
-                        counter.value
-                        Color.Red
-                    }
-                )
-            } else {
-                LayerDrawingBox()
-            }
-        }
-
-        rule.runOnIdle {
-            drawPrebuiltLayer = true
-
-            // changing the counter to trigger the layer invalidation. the invalidation should
-            // be ignored in the end as we will release the layer before it will be drawn
-            counter.value++
-        }
-
-        rule.onNodeWithTag(LayerDrawingBoxTag).captureToImage().assertPixels(expectedSize) {
-            Color.Red
-        }
-    }
-
-    @Ignore("b/329417380")
-    @Test
-    fun updateLayerProperties() {
-        rule.setContent {
-            if (!drawPrebuiltLayer) {
-                ColoredBox()
-            } else {
-                LayerDrawingBox()
-            }
-        }
-
-        rule.runOnIdle {
-            drawPrebuiltLayer = true
-            layer!!.alpha = 1f
-        }
-
-        rule.runOnIdle { layer!!.alpha = 0.5f }
-
-        rule.onNodeWithTag(LayerDrawingBoxTag).captureToImage().assertPixels(expectedSize) {
-            Color.Red.copy(alpha = 0.5f).compositeOver(Color.White)
-        }
-    }
-
-    @Composable
-    private fun ColoredBox(modifier: Modifier = Modifier, color: () -> Color = { Color.Red }) {
-        Canvas(modifier.size(sizeDp).testTag(ColoredBoxTag).drawIntoLayer()) { drawRect(color()) }
-    }
-
-    @Composable
-    private fun obtainLayer(): GraphicsLayer {
-        context = LocalGraphicsContext.current
-        return layer ?: context!!.createGraphicsLayer().also { layer = it }
-    }
-
-    @Composable
-    private fun Modifier.drawIntoLayer(layer: GraphicsLayer = obtainLayer()): Modifier {
-        return drawWithContent {
-            layer.record { [email protected]() }
-            drawLayer(layer)
-        }
-    }
-
-    @Composable
-    private fun LayerDrawingBox() {
-        Canvas(Modifier.size(sizeDp).testTag(LayerDrawingBoxTag)) {
-            drawRect(Color.White)
-            layer?.let { drawLayer(it) }
-        }
-    }
-
-    fun SemanticsNodeInteraction.captureToImage(): ImageBitmap {
-        val size = rule.scene.contentSize
-        val surface = Surface.makeRasterN32Premul(size.width, size.height)
-        val canvas = surface.canvas
-        rule.scene.render(canvas, rule.mainClock.currentTime * 1_000_000)
-
-        val bounds = getBoundsInRoot()
-        val rect =
-            with(rule.density) {
-                IRect.makeLTRB(
-                    bounds.left.roundToPx(),
-                    bounds.top.roundToPx(),
-                    bounds.right.roundToPx(),
-                    bounds.bottom.roundToPx(),
-                )
-            }
-        return surface.makeImageSnapshot(rect)!!.toComposeImageBitmap()
-    }
-}
-
-private val LayerDrawingBoxTag = "LayerDrawingBoxTag"
-private val ColoredBoxTag = "RedBoxTag"
-
-// next two functions are copies from our Android utils:
-
-/**
- * A helper function to run asserts on [ImageBitmap].
- *
- * @param expectedSize The expected size of the bitmap. Leave null to skip the check.
- * @param expectedColorProvider Returns the expected color for the provided pixel position. The
- *   returned color is then asserted as the expected one on the given bitmap.
- * @throws AssertionError if size or colors don't match.
- */
-fun ImageBitmap.assertPixels(
-    expectedSize: IntSize? = null,
-    expectedColorProvider: (pos: IntOffset) -> Color?
-) {
-    if (expectedSize != null) {
-        if (width != expectedSize.width || height != expectedSize.height) {
-            throw AssertionError(
-                "Bitmap size is wrong! Expected '$expectedSize' but got " + "'$width x $height'"
-            )
-        }
-    }
-
-    val pixel = toPixelMap()
-    for (y in 0 until height) {
-        for (x in 0 until width) {
-            val pxPos = IntOffset(x, y)
-            val expectedClr = expectedColorProvider(pxPos)
-            if (expectedClr != null) {
-                pixel.assertPixelColor(expectedClr, x, y)
-            }
-        }
-    }
-}
-
-/** Asserts that the color at a specific pixel in the bitmap at ([x], [y]) is [expected]. */
-fun PixelMap.assertPixelColor(
-    expected: Color,
-    x: Int,
-    y: Int,
-    error: (Color) -> String = { color -> "Pixel($x, $y) expected to be $expected, but was $color" }
-) {
-    val color = this[x, y]
-    val errorString = error(color)
-    Assert.assertEquals(errorString, expected.red, color.red, 0.02f)
-    Assert.assertEquals(errorString, expected.green, color.green, 0.02f)
-    Assert.assertEquals(errorString, expected.blue, color.blue, 0.02f)
-    Assert.assertEquals(errorString, expected.alpha, color.alpha, 0.02f)
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/graphics/DesktopGraphicsLayerScopeTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/graphics/DesktopGraphicsLayerScopeTest.kt
deleted file mode 100644
index c3f8467..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/graphics/DesktopGraphicsLayerScopeTest.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.graphics
-
-import androidx.compose.ui.unit.Density
-import androidx.compose.ui.unit.dp
-import org.junit.Assert.assertEquals
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-/**
- * Any tests for SP need to run outside of common because they need a proper `actual` FontScalable
- * interface that doesn't depend on Android core.
- */
-@RunWith(JUnit4::class)
-class DesktopGraphicsLayerScopeTest {
-
-    @Test
-    fun testDpPixelConversions() {
-        val scope = GraphicsLayerScope() as ReusableGraphicsLayerScope
-        scope.graphicsDensity = Density(2.0f, 3.0f)
-        with(scope) {
-            assertEquals(4.0f, 2f.dp.toPx())
-            assertEquals(6.0f, 3f.dp.toSp().toPx())
-        }
-    }
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/input/key/KeyInputUtil.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/input/key/KeyInputUtil.kt
deleted file mode 100644
index d84a980..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/input/key/KeyInputUtil.kt
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.input.key
-
-import java.awt.Component
-import java.awt.event.KeyEvent as KeyEventAwt
-import java.awt.event.KeyEvent.KEY_PRESSED
-import java.awt.event.KeyEvent.KEY_RELEASED
-import java.awt.event.KeyEvent.KEY_TYPED
-import java.awt.event.KeyEvent.VK_UNDEFINED
-
-private object DummyComponent : Component()
-
-/**
- * The [KeyEvent] is usually created by the system. This function creates an instance of [KeyEvent]
- * that can be used in tests.
- */
-fun keyEvent(key: Key, keyEventType: KeyEventType, modifiers: Int = 0): KeyEvent {
-    val action =
-        when (keyEventType) {
-            KeyEventType.KeyDown -> KEY_PRESSED
-            KeyEventType.KeyUp -> KEY_RELEASED
-            else -> error("Unknown key event type")
-        }
-    return KeyEvent(
-        KeyEventAwt(
-            DummyComponent,
-            action,
-            0L,
-            modifiers,
-            key.nativeKeyCode,
-            KeyEventAwt.getKeyText(key.nativeKeyCode)[0],
-            key.nativeKeyLocation
-        )
-    )
-}
-
-/** Creates [KeyEvent] of Unknown type. It wraps KEY_TYPED AWTs KeyEvent */
-fun keyTypedEvent(key: Key): KeyEvent {
-    return KeyEvent(
-        KeyEventAwt(
-            DummyComponent,
-            KEY_TYPED,
-            0L,
-            0,
-            VK_UNDEFINED,
-            KeyEventAwt.getKeyText(key.nativeKeyCode)[0],
-            java.awt.event.KeyEvent.KEY_LOCATION_UNKNOWN
-        )
-    )
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/input/key/KeyTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/input/key/KeyTest.kt
deleted file mode 100644
index 5fabd86..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/input/key/KeyTest.kt
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.input.key
-
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.test.junit4.createComposeRule
-import com.google.common.truth.Truth.assertThat
-import java.awt.event.KeyEvent
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class KeyTest {
-    @get:Rule val rule = createComposeRule()
-
-    @Test
-    fun desktopKey_to_composeKey() {
-        // Arrange.
-        val desktopKeyCode = KeyEvent.VK_ALT
-        val desktopKeyLocation = KeyEvent.KEY_LOCATION_LEFT
-
-        // Act.
-        val desktopKey = Key(desktopKeyCode, desktopKeyLocation)
-
-        // Assert.
-        assertThat(desktopKey).isEqualTo(Key.AltLeft)
-    }
-
-    @Test
-    fun composeKey_to_desktopKeyCode() {
-        // Arrange.
-        val key = Key.A
-
-        // Act.
-        val nativeKeyCode = key.nativeKeyCode
-
-        // Arrange.
-        assertThat(nativeKeyCode).isEqualTo(KeyEvent.VK_A)
-    }
-
-    @Test
-    fun composeKey_to_standardDesktopKeyLocation() {
-        // Arrange.
-        val key = Key.A
-
-        // Act.
-        val desktopKeyLocation = key.nativeKeyLocation
-
-        // Arrange.
-        assertThat(desktopKeyLocation).isEqualTo(KeyEvent.KEY_LOCATION_STANDARD)
-    }
-
-    @Test
-    fun composeKey_to_knownDesktopKeyLocation() {
-        // Arrange.
-        val key = Key.AltLeft
-
-        // Act.
-        val desktopKeyLocation = key.nativeKeyLocation
-
-        // Arrange.
-        assertThat(desktopKeyLocation).isEqualTo(KeyEvent.KEY_LOCATION_LEFT)
-    }
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/input/mouse/MouseHoverFilterTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/input/mouse/MouseHoverFilterTest.kt
deleted file mode 100644
index 96eaa7d..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/input/mouse/MouseHoverFilterTest.kt
+++ /dev/null
@@ -1,171 +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.
- */
-
-@file:Suppress("DEPRECATION") // https://github.com/JetBrains/compose-jb/issues/1514
-
-package androidx.compose.ui.input.mouse
-
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.rememberScrollState
-import androidx.compose.foundation.verticalScroll
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.input.pointer.PointerEventType
-import androidx.compose.ui.input.pointer.pointerInput
-import androidx.compose.ui.platform.TestComposeWindow
-import androidx.compose.ui.unit.Density
-import androidx.compose.ui.unit.dp
-import com.google.common.truth.Truth.assertThat
-import org.junit.Ignore
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class MouseHoverFilterTest {
-    private val window = TestComposeWindow(width = 100, height = 100, density = Density(2f))
-
-    @Test
-    fun `inside window`() {
-        var moveCount = 0
-        var enterCount = 0
-        var exitCount = 0
-
-        window.setContent {
-            Box(
-                modifier =
-                    Modifier.pointerMove(
-                            onMove = { moveCount++ },
-                            onEnter = { enterCount++ },
-                            onExit = { exitCount++ }
-                        )
-                        .size(10.dp, 20.dp)
-            )
-        }
-        window.onMouseEntered(x = 0, y = 0)
-        window.onMouseMoved(x = 10, y = 20)
-        assertThat(enterCount).isEqualTo(1)
-        assertThat(exitCount).isEqualTo(0)
-        assertThat(moveCount).isEqualTo(1)
-
-        window.onMouseMoved(x = 10, y = 15)
-        assertThat(enterCount).isEqualTo(1)
-        assertThat(exitCount).isEqualTo(0)
-        assertThat(moveCount).isEqualTo(2)
-
-        window.onMouseMoved(x = 30, y = 30)
-        assertThat(enterCount).isEqualTo(1)
-        assertThat(exitCount).isEqualTo(1)
-        assertThat(moveCount).isEqualTo(2)
-    }
-
-    @Test
-    fun `window enter`() {
-        var moveCount = 0
-        var enterCount = 0
-        var exitCount = 0
-
-        window.setContent {
-            Box(
-                modifier =
-                    Modifier.pointerMove(
-                            onMove = { moveCount++ },
-                            onEnter = { enterCount++ },
-                            onExit = { exitCount++ }
-                        )
-                        .size(10.dp, 20.dp)
-            )
-        }
-
-        window.onMouseEntered(x = 10, y = 20)
-        assertThat(enterCount).isEqualTo(1)
-        assertThat(exitCount).isEqualTo(0)
-        assertThat(moveCount).isEqualTo(0)
-
-        window.onMouseExited()
-        assertThat(enterCount).isEqualTo(1)
-        assertThat(exitCount).isEqualTo(1)
-        assertThat(moveCount).isEqualTo(0)
-    }
-
-    @Ignore("b/271123970 Fails in AOSP. Will be fixed after upstreaming Compose for Desktop")
-    @Test
-    fun `scroll should trigger enter and exit`() {
-        val boxCount = 3
-
-        val enterCounts = Array(boxCount) { 0 }
-        val exitCounts = Array(boxCount) { 0 }
-
-        window.setContent {
-            Column(Modifier.size(10.dp, 20.dp).verticalScroll(rememberScrollState())) {
-                repeat(boxCount) { index ->
-                    Box(
-                        modifier =
-                            Modifier.pointerMove(
-                                    onMove = {},
-                                    onEnter = { enterCounts[index] = enterCounts[index] + 1 },
-                                    onExit = { exitCounts[index] = exitCounts[index] + 1 }
-                                )
-                                .size(10.dp, 20.dp)
-                    )
-                }
-            }
-        }
-
-        window.onMouseEntered(0, 0)
-        window.onMouseScroll(
-            0,
-            0,
-            MouseScrollEvent(MouseScrollUnit.Page(1f), MouseScrollOrientation.Vertical)
-        )
-        window.render() // synthetic enter/exit will trigger only on relayout
-        assertThat(enterCounts.toList()).isEqualTo(listOf(1, 1, 0))
-        assertThat(exitCounts.toList()).isEqualTo(listOf(1, 0, 0))
-
-        window.onMouseMoved(1, 1)
-        window.onMouseScroll(
-            2,
-            2,
-            MouseScrollEvent(MouseScrollUnit.Page(1f), MouseScrollOrientation.Vertical)
-        )
-        window.render()
-        assertThat(enterCounts.toList()).isEqualTo(listOf(1, 1, 1))
-        assertThat(exitCounts.toList()).isEqualTo(listOf(1, 1, 0))
-
-        window.onMouseExited()
-        assertThat(enterCounts.toList()).isEqualTo(listOf(1, 1, 1))
-        assertThat(exitCounts.toList()).isEqualTo(listOf(1, 1, 1))
-    }
-}
-
-private fun Modifier.pointerMove(
-    onMove: () -> Unit,
-    onExit: () -> Unit,
-    onEnter: () -> Unit,
-): Modifier =
-    pointerInput(onMove, onExit, onEnter) {
-        awaitPointerEventScope {
-            while (true) {
-                val event = awaitPointerEvent()
-                when (event.type) {
-                    PointerEventType.Move -> onMove()
-                    PointerEventType.Enter -> onEnter()
-                    PointerEventType.Exit -> onExit()
-                }
-            }
-        }
-    }
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/input/mouse/MouseScrollFilterTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/input/mouse/MouseScrollFilterTest.kt
deleted file mode 100644
index 296e9f6..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/input/mouse/MouseScrollFilterTest.kt
+++ /dev/null
@@ -1,284 +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.
- */
-
-@file:Suppress("DEPRECATION") // https://github.com/JetBrains/compose-jb/issues/1514
-
-package androidx.compose.ui.input.mouse
-
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.size
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.TestComposeWindow
-import androidx.compose.ui.unit.Density
-import androidx.compose.ui.unit.IntSize
-import androidx.compose.ui.unit.dp
-import com.google.common.truth.Truth.assertThat
-import org.junit.Ignore
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-@Ignore // TODO(b/217238066) remove after migration to ImageComposeScene (it will be upstreamed from
-// Compose MPP 1.0.0)
-class MouseScrollFilterTest {
-    private val window = TestComposeWindow(width = 100, height = 100, density = Density(2f))
-
-    @Test
-    fun `inside box`() {
-        var actualEvent: MouseScrollEvent? = null
-        var actualBounds: IntSize? = null
-
-        window.setContent {
-            Box(
-                Modifier.mouseScrollFilter { event, bounds ->
-                        actualEvent = event
-                        actualBounds = bounds
-                        true
-                    }
-                    .size(10.dp, 20.dp)
-            )
-        }
-
-        window.onMouseScroll(
-            x = 0,
-            y = 0,
-            event = MouseScrollEvent(MouseScrollUnit.Line(3f), MouseScrollOrientation.Vertical)
-        )
-
-        assertThat(actualEvent?.delta).isEqualTo(MouseScrollUnit.Line(3f))
-        assertThat(actualEvent?.orientation).isEqualTo(MouseScrollOrientation.Vertical)
-        assertThat(actualBounds).isEqualTo(IntSize(20, 40))
-    }
-
-    @Test
-    fun `outside box`() {
-        var actualEvent: MouseScrollEvent? = null
-        var actualBounds: IntSize? = null
-
-        window.setContent {
-            Box(
-                Modifier.mouseScrollFilter { event, bounds ->
-                        actualEvent = event
-                        actualBounds = bounds
-                        true
-                    }
-                    .size(10.dp, 20.dp)
-            )
-        }
-
-        window.onMouseScroll(
-            x = 20,
-            y = 0,
-            event = MouseScrollEvent(MouseScrollUnit.Line(3f), MouseScrollOrientation.Vertical)
-        )
-
-        assertThat(actualEvent).isEqualTo(null)
-        assertThat(actualBounds).isEqualTo(null)
-    }
-
-    @Test
-    fun `inside two overlapping boxes`() {
-        var actualEvent1: MouseScrollEvent? = null
-        var actualBounds1: IntSize? = null
-        var actualEvent2: MouseScrollEvent? = null
-        var actualBounds2: IntSize? = null
-
-        window.setContent {
-            Box(
-                Modifier.mouseScrollFilter { event, bounds ->
-                        actualEvent1 = event
-                        actualBounds1 = bounds
-                        true
-                    }
-                    .size(10.dp, 20.dp)
-            )
-            Box(
-                Modifier.mouseScrollFilter { event, bounds ->
-                        actualEvent2 = event
-                        actualBounds2 = bounds
-                        true
-                    }
-                    .size(5.dp, 10.dp)
-            )
-        }
-
-        window.onMouseScroll(
-            x = 0,
-            y = 0,
-            event = MouseScrollEvent(MouseScrollUnit.Line(3f), MouseScrollOrientation.Horizontal)
-        )
-
-        assertThat(actualEvent1).isEqualTo(null)
-        assertThat(actualBounds1).isEqualTo(null)
-        assertThat(actualEvent2?.delta).isEqualTo(MouseScrollUnit.Line(3f))
-        assertThat(actualEvent2?.orientation).isEqualTo(MouseScrollOrientation.Horizontal)
-        assertThat(actualBounds2).isEqualTo(IntSize(10, 20))
-    }
-
-    @Test
-    fun `inside two overlapping boxes, top box doesn't handle scroll`() {
-        var actualEvent: MouseScrollEvent? = null
-        var actualBounds: IntSize? = null
-
-        window.setContent {
-            Box(
-                Modifier.mouseScrollFilter { event, bounds ->
-                        actualEvent = event
-                        actualBounds = bounds
-                        true
-                    }
-                    .size(10.dp, 20.dp)
-            )
-            Box(Modifier.mouseScrollFilter { _, _ -> false }.size(5.dp, 10.dp))
-        }
-
-        window.onMouseScroll(
-            x = 0,
-            y = 0,
-            event = MouseScrollEvent(MouseScrollUnit.Line(3f), MouseScrollOrientation.Horizontal)
-        )
-
-        assertThat(actualEvent).isEqualTo(null)
-        assertThat(actualBounds).isEqualTo(null)
-    }
-
-    @Test
-    fun `inside two overlapping boxes, top box doesn't have mouseScrollFilter`() {
-        var actualEvent: MouseScrollEvent? = null
-        var actualBounds: IntSize? = null
-
-        window.setContent {
-            Box(
-                Modifier.mouseScrollFilter { event, bounds ->
-                        actualEvent = event
-                        actualBounds = bounds
-                        true
-                    }
-                    .size(10.dp, 20.dp)
-            )
-            Box(Modifier.size(5.dp, 10.dp))
-        }
-
-        window.onMouseScroll(
-            x = 0,
-            y = 0,
-            event = MouseScrollEvent(MouseScrollUnit.Line(3f), MouseScrollOrientation.Horizontal)
-        )
-
-        assertThat(actualEvent?.delta).isEqualTo(MouseScrollUnit.Line(3f))
-        assertThat(actualEvent?.orientation).isEqualTo(MouseScrollOrientation.Horizontal)
-        assertThat(actualBounds).isEqualTo(IntSize(20, 40))
-    }
-
-    @Test
-    fun `inside two nested boxes`() {
-        var actualEvent1: MouseScrollEvent? = null
-        var actualBounds1: IntSize? = null
-        var actualEvent2: MouseScrollEvent? = null
-        var actualBounds2: IntSize? = null
-
-        window.setContent {
-            Box(
-                Modifier.mouseScrollFilter { event, bounds ->
-                        actualEvent1 = event
-                        actualBounds1 = bounds
-                        true
-                    }
-                    .size(10.dp, 20.dp)
-            ) {
-                Box(
-                    Modifier.mouseScrollFilter { event, bounds ->
-                            actualEvent2 = event
-                            actualBounds2 = bounds
-                            true
-                        }
-                        .size(5.dp, 10.dp)
-                )
-            }
-        }
-
-        window.onMouseScroll(
-            x = 0,
-            y = 0,
-            event = MouseScrollEvent(MouseScrollUnit.Line(-1f), MouseScrollOrientation.Horizontal)
-        )
-
-        assertThat(actualEvent1).isEqualTo(null)
-        assertThat(actualBounds1).isEqualTo(null)
-        assertThat(actualEvent2?.delta).isEqualTo(MouseScrollUnit.Line(-1f))
-        assertThat(actualEvent2?.orientation).isEqualTo(MouseScrollOrientation.Horizontal)
-        assertThat(actualBounds2).isEqualTo(IntSize(10, 20))
-    }
-
-    @Test
-    fun `inside two nested boxes, nested box doesn't handle scroll`() {
-        var actualEvent: MouseScrollEvent? = null
-        var actualBounds: IntSize? = null
-
-        window.setContent {
-            Box(
-                Modifier.mouseScrollFilter { event, bounds ->
-                        actualEvent = event
-                        actualBounds = bounds
-                        true
-                    }
-                    .size(10.dp, 20.dp)
-            ) {
-                Box(Modifier.mouseScrollFilter { _, _ -> false }.size(5.dp, 10.dp))
-            }
-        }
-
-        window.onMouseScroll(
-            x = 0,
-            y = 0,
-            event = MouseScrollEvent(MouseScrollUnit.Page(1f), MouseScrollOrientation.Horizontal)
-        )
-
-        assertThat(actualEvent?.delta).isEqualTo(MouseScrollUnit.Page(1f))
-        assertThat(actualEvent?.orientation).isEqualTo(MouseScrollOrientation.Horizontal)
-        assertThat(actualBounds).isEqualTo(IntSize(20, 40))
-    }
-
-    @Test
-    fun `inside two nested boxes, nested box doesn't have mouseScrollFilter`() {
-        var actualEvent: MouseScrollEvent? = null
-        var actualBounds: IntSize? = null
-
-        window.setContent {
-            Box(
-                Modifier.mouseScrollFilter { event, bounds ->
-                        actualEvent = event
-                        actualBounds = bounds
-                        true
-                    }
-                    .size(10.dp, 20.dp)
-            ) {
-                Box(Modifier.size(5.dp, 10.dp))
-            }
-        }
-
-        window.onMouseScroll(
-            x = 0,
-            y = 0,
-            event = MouseScrollEvent(MouseScrollUnit.Page(1f), MouseScrollOrientation.Horizontal)
-        )
-
-        assertThat(actualEvent?.delta).isEqualTo(MouseScrollUnit.Page(1f))
-        assertThat(actualEvent?.orientation).isEqualTo(MouseScrollOrientation.Horizontal)
-        assertThat(actualBounds).isEqualTo(IntSize(20, 40))
-    }
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/input/pointer/PointerIconTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/input/pointer/PointerIconTest.kt
deleted file mode 100644
index 0390347..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/input/pointer/PointerIconTest.kt
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.input.pointer
-
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.size
-import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.LocalPointerIconService
-import androidx.compose.ui.platform.TestComposeWindow
-import androidx.compose.ui.unit.Density
-import androidx.compose.ui.unit.dp
-import com.google.common.truth.Truth.assertThat
-import java.awt.Cursor
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class PointerIconTest {
-    private val window = TestComposeWindow(width = 100, height = 100, density = Density(1f))
-
-    private val iconService =
-        object : PointerIconService {
-            private var currentIcon: PointerIcon = PointerIcon.Default
-
-            override fun getIcon(): PointerIcon {
-                return currentIcon
-            }
-
-            override fun setIcon(value: PointerIcon?) {
-                currentIcon = value ?: PointerIcon.Default
-            }
-        }
-
-    @Test
-    fun basicTest() {
-        window.setContent {
-            CompositionLocalProvider(LocalPointerIconService provides iconService) {
-                Box(modifier = Modifier.size(30.dp, 30.dp)) {
-                    Box(modifier = Modifier.pointerHoverIcon(PointerIcon.Text).size(10.dp, 10.dp))
-                }
-            }
-        }
-
-        window.onMouseMoved(x = 5, y = 5)
-        assertThat(iconService.getIcon()).isEqualTo(PointerIcon.Text)
-    }
-
-    @Test
-    fun commitsToComponent() {
-        window.setContent {
-            Box(modifier = Modifier.size(30.dp, 30.dp)) {
-                Box(modifier = Modifier.pointerHoverIcon(PointerIcon.Text).size(10.dp, 10.dp))
-            }
-        }
-
-        window.onMouseMoved(x = 5, y = 5)
-        assertThat(window.currentCursor.type).isEqualTo(Cursor.TEXT_CURSOR)
-    }
-
-    @Test
-    fun preservedIfSameEventDispatchedTwice() {
-        window.setContent {
-            Box(modifier = Modifier.size(30.dp, 30.dp)) {
-                Box(modifier = Modifier.pointerHoverIcon(PointerIcon.Text).size(10.dp, 10.dp))
-            }
-        }
-
-        window.onMouseMoved(x = 5, y = 5)
-        window.onMouseMoved(x = 5, y = 5)
-        assertThat(window.currentCursor.type).isEqualTo(Cursor.TEXT_CURSOR)
-    }
-
-    @Test
-    fun parentWins() {
-        window.setContent {
-            CompositionLocalProvider(LocalPointerIconService provides iconService) {
-                Box(
-                    modifier = Modifier.pointerHoverIcon(PointerIcon.Hand, true).size(30.dp, 30.dp)
-                ) {
-                    Box(modifier = Modifier.pointerHoverIcon(PointerIcon.Text).size(10.dp, 10.dp))
-                }
-            }
-        }
-
-        window.onMouseMoved(x = 5, y = 5)
-        assertThat(iconService.getIcon()).isEqualTo(PointerIcon.Hand)
-
-        window.onMouseMoved(x = 15, y = 15)
-        assertThat(iconService.getIcon()).isEqualTo(PointerIcon.Hand)
-    }
-
-    @Test
-    fun childWins() {
-        window.setContent {
-            CompositionLocalProvider(LocalPointerIconService provides iconService) {
-                Box(modifier = Modifier.pointerHoverIcon(PointerIcon.Hand).size(30.dp, 30.dp)) {
-                    Box(modifier = Modifier.pointerHoverIcon(PointerIcon.Text).size(10.dp, 10.dp))
-                }
-            }
-        }
-
-        window.onMouseMoved(x = 5, y = 5)
-        assertThat(iconService.getIcon()).isEqualTo(PointerIcon.Text)
-
-        window.onMouseMoved(x = 15, y = 15)
-        assertThat(iconService.getIcon()).isEqualTo(PointerIcon.Hand)
-    }
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/AccessibilityTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/AccessibilityTest.kt
deleted file mode 100644
index 655fa48..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/AccessibilityTest.kt
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.platform
-
-import androidx.compose.material.Text
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.compose.ui.test.onNodeWithTag
-import javax.accessibility.AccessibleText
-import org.junit.Assert.assertEquals
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class AccessibilityTest {
-
-    @get:Rule val rule = createComposeRule()
-
-    @Test
-    fun accessibleText() {
-        rule.setContent { Text("Hello world. Hi world.", modifier = Modifier.testTag("text")) }
-
-        val node = rule.onNodeWithTag("text").fetchSemanticsNode()
-        val accessibleNode = ComposeAccessible(node)
-        val accessibleText = accessibleNode.accessibleContext.accessibleText!!
-        assertEquals(22, accessibleText.charCount)
-
-        assertEquals("H", accessibleText.getAtIndex(AccessibleText.CHARACTER, 0))
-        assertEquals("Hello", accessibleText.getAtIndex(AccessibleText.WORD, 0))
-        assertEquals("Hello world. ", accessibleText.getAtIndex(AccessibleText.SENTENCE, 0))
-
-        assertEquals("e", accessibleText.getAfterIndex(AccessibleText.CHARACTER, 0))
-        assertEquals("world", accessibleText.getAfterIndex(AccessibleText.WORD, 0))
-        assertEquals("Hi world.", accessibleText.getAfterIndex(AccessibleText.SENTENCE, 0))
-
-        assertEquals("d", accessibleText.getBeforeIndex(AccessibleText.CHARACTER, 21))
-        assertEquals("world", accessibleText.getBeforeIndex(AccessibleText.WORD, 21))
-        assertEquals("Hi world", accessibleText.getBeforeIndex(AccessibleText.SENTENCE, 21))
-    }
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/DesktopInputComponentTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/DesktopInputComponentTest.kt
deleted file mode 100644
index f238d23..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/DesktopInputComponentTest.kt
+++ /dev/null
@@ -1,106 +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.
- */
-
-@file:Suppress("DEPRECATION")
-
-package androidx.compose.ui.platform
-
-import androidx.compose.ui.isMacOs
-import androidx.compose.ui.text.InternalTextApi
-import androidx.compose.ui.text.TextRange
-import androidx.compose.ui.text.input.EditProcessor
-import androidx.compose.ui.text.input.ImeOptions
-import androidx.compose.ui.text.input.TextFieldValue
-import androidx.compose.ui.text.input.TextInputService
-import java.awt.Component
-import java.awt.event.InputMethodEvent
-import java.text.AttributedString
-import org.junit.Assert
-import org.junit.Assume.assumeTrue
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-private object DummyComponent : Component()
-
-@RunWith(JUnit4::class)
-class DesktopInputComponentTest {
-    @OptIn(InternalTextApi::class)
-    @Test
-    fun replaceInputMethodText_basic() {
-        val processor = EditProcessor()
-
-        val input = PlatformInput(DummyPlatformComponent)
-        val inputService = TextInputService(input)
-
-        val session =
-            inputService.startInput(TextFieldValue(), ImeOptions.Default, processor::apply, {})
-
-        processor.reset(TextFieldValue("h"), session)
-
-        val familyEmoji = "\uD83D\uDC68\u200D\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66"
-
-        input.replaceInputMethodText(
-            InputMethodEvent(
-                DummyComponent,
-                InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
-                AttributedString(familyEmoji).iterator,
-                11,
-                null,
-                null
-            )
-        )
-
-        val buffer = processor.toTextFieldValue()
-
-        Assert.assertEquals("${familyEmoji}h", buffer.text)
-        Assert.assertEquals(TextRange(11), buffer.selection)
-    }
-
-    @Test
-    fun longPressWorkaroundTest() {
-        assumeTrue(isMacOs)
-        val processor = EditProcessor()
-
-        val component = DummyPlatformComponent
-        val input = PlatformInput(component)
-        val inputService = TextInputService(input)
-
-        val session =
-            inputService.startInput(TextFieldValue(), ImeOptions.Default, processor::apply, {})
-
-        input.charKeyPressed = true
-        processor.reset(TextFieldValue("a", selection = TextRange(1)), session)
-        component.enabledInput!!.getSelectedText(null)
-        input.charKeyPressed = false
-
-        input.replaceInputMethodText(
-            InputMethodEvent(
-                DummyComponent,
-                InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
-                AttributedString("ä").iterator,
-                1,
-                null,
-                null
-            )
-        )
-
-        val buffer = processor.toTextFieldValue()
-
-        Assert.assertEquals("ä", buffer.text)
-        Assert.assertEquals(TextRange(1), buffer.selection)
-    }
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/DesktopTextInputSessionTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/DesktopTextInputSessionTest.kt
deleted file mode 100644
index 9d14d77..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/DesktopTextInputSessionTest.kt
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.platform
-
-import androidx.compose.ui.unit.Density
-import com.google.common.truth.Truth.assertThat
-import java.awt.Frame
-import java.awt.Point
-import java.awt.Rectangle
-import java.awt.event.InputMethodEvent
-import java.awt.event.InputMethodListener
-import java.awt.font.TextHitInfo
-import java.awt.im.InputMethodRequests
-import java.text.AttributedCharacterIterator
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.cancelAndJoin
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.test.advanceUntilIdle
-import kotlinx.coroutines.test.runTest
-import org.junit.Ignore
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@OptIn(ExperimentalCoroutinesApi::class)
-@RunWith(JUnit4::class)
-class DesktopTextInputSessionTest {
-
-    @Ignore("b/308619798")
-    @Test
-    fun startInputMethod_setsAndClearsRequestsAndListeners() = runTest {
-        val inputComponent = TestInputComponent()
-        val component = Frame()
-        val session =
-            DesktopTextInputSession(
-                coroutineScope = this,
-                inputComponent = inputComponent,
-                component = component
-            )
-        val request = TestInputMethodRequest()
-
-        val sessionJob = launch { session.startInputMethod(request) }
-        advanceUntilIdle()
-
-        assertThat(inputComponent.inputMethodRequests).isSameInstanceAs(request)
-        assertThat(component.inputMethodListeners).asList().containsExactly(request)
-
-        sessionJob.cancelAndJoin()
-
-        assertThat(inputComponent.inputMethodRequests).isNull()
-        assertThat(component.inputMethodListeners).isEmpty()
-    }
-
-    private class TestInputComponent : PlatformInputComponent {
-        var inputMethodRequests: InputMethodRequests? = null
-
-        override fun enableInput(inputMethodRequests: InputMethodRequests) {
-            this.inputMethodRequests = inputMethodRequests
-        }
-
-        override fun disableInput(inputMethodRequests: InputMethodRequests?) {
-            this.inputMethodRequests = null
-        }
-
-        override suspend fun textInputSession(
-            session: suspend PlatformTextInputSessionScope.() -> Nothing
-        ): Nothing {
-            throw AssertionError("not supported")
-        }
-
-        override val locationOnScreen: Point
-            get() = throw AssertionError("not supported")
-
-        override val density: Density
-            get() = throw AssertionError("not supported")
-    }
-
-    private class TestInputMethodRequest :
-        PlatformTextInputMethodRequest, InputMethodListener, InputMethodRequests {
-
-        override val inputMethodListener: InputMethodListener
-            get() = this
-
-        override val inputMethodRequests: InputMethodRequests
-            get() = this
-
-        override fun inputMethodTextChanged(event: InputMethodEvent?) {
-            throw AssertionError("not supported")
-        }
-
-        override fun caretPositionChanged(event: InputMethodEvent?) {
-            throw AssertionError("not supported")
-        }
-
-        override fun getTextLocation(offset: TextHitInfo?): Rectangle {
-            throw AssertionError("not supported")
-        }
-
-        override fun getLocationOffset(x: Int, y: Int): TextHitInfo? {
-            throw AssertionError("not supported")
-        }
-
-        override fun getInsertPositionOffset(): Int {
-            throw AssertionError("not supported")
-        }
-
-        override fun getCommittedText(
-            beginIndex: Int,
-            endIndex: Int,
-            attributes: Array<out AttributedCharacterIterator.Attribute>?
-        ): AttributedCharacterIterator {
-            throw AssertionError("not supported")
-        }
-
-        override fun getCommittedTextLength(): Int {
-            throw AssertionError("not supported")
-        }
-
-        override fun cancelLatestCommittedText(
-            attributes: Array<out AttributedCharacterIterator.Attribute>?
-        ): AttributedCharacterIterator? {
-            throw AssertionError("not supported")
-        }
-
-        override fun getSelectedText(
-            attributes: Array<out AttributedCharacterIterator.Attribute>?
-        ): AttributedCharacterIterator? {
-            throw AssertionError("not supported")
-        }
-    }
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/FlushCoroutineDispatcherTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/FlushCoroutineDispatcherTest.kt
deleted file mode 100644
index abfc35a..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/FlushCoroutineDispatcherTest.kt
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.platform
-
-import kotlin.random.Random
-import kotlinx.coroutines.DelicateCoroutinesApi
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.test.runTest
-import kotlinx.coroutines.yield
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertFalse
-import org.junit.Test
-
-@OptIn(ExperimentalCoroutinesApi::class, DelicateCoroutinesApi::class)
-class FlushCoroutineDispatcherTest {
-    @Test
-    fun `all tasks should run with flush`() = runTest {
-        val dispatcher = FlushCoroutineDispatcher(this)
-
-        val actualNumbers = mutableListOf<Int>()
-        launch(dispatcher) {
-            yield()
-            actualNumbers.add(1)
-            yield()
-            yield()
-            actualNumbers.add(2)
-            yield()
-            yield()
-            yield()
-            actualNumbers.add(3)
-        }
-
-        while (dispatcher.hasTasks()) {
-            dispatcher.flush()
-        }
-
-        assertEquals(listOf(1, 2, 3), actualNumbers)
-    }
-
-    @Test
-    fun `tasks should run even without flush`() = runTest {
-        val dispatcher = FlushCoroutineDispatcher(this)
-
-        val actualNumbers = mutableListOf<Int>()
-        launch(dispatcher) {
-            yield()
-            actualNumbers.add(1)
-            yield()
-            yield()
-            actualNumbers.add(2)
-            yield()
-            yield()
-            yield()
-            actualNumbers.add(3)
-        }
-
-        testScheduler.advanceUntilIdle()
-
-        assertEquals(listOf(1, 2, 3), actualNumbers)
-        assertFalse(dispatcher.hasTasks())
-    }
-
-    @Test
-    fun `flushing in another thread`() {
-        val actualNumbers = mutableListOf<Int>()
-        lateinit var dispatcher: FlushCoroutineDispatcher
-        val random = Random(123)
-
-        runBlocking(Dispatchers.Default) {
-            dispatcher = FlushCoroutineDispatcher(this)
-
-            val addJob =
-                launch(dispatcher) {
-                    repeat(10000) {
-                        actualNumbers.add(it)
-                        repeat(random.nextInt(5)) { yield() }
-                    }
-                }
-
-            launch {
-                while (addJob.isActive) {
-                    dispatcher.flush()
-                    yield()
-                }
-            }
-        }
-
-        assertEquals((0 until 10000).toList(), actualNumbers)
-        assertFalse(dispatcher.hasTasks())
-    }
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/GraphicsLayerTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/GraphicsLayerTest.kt
deleted file mode 100644
index 874703d..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/GraphicsLayerTest.kt
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.platform
-
-import androidx.compose.foundation.background
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.requiredSize
-import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.TransformOrigin
-import androidx.compose.ui.graphics.graphicsLayer
-import androidx.compose.ui.test.InternalTestApi
-import androidx.compose.ui.test.junit4.DesktopScreenshotTestRule
-import androidx.compose.ui.unit.dp
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-@OptIn(InternalTestApi::class)
-class GraphicsLayerTest {
-    @get:Rule val screenshotRule = DesktopScreenshotTestRule("compose/ui/ui-desktop/platform")
-
-    @Test
-    fun scale() {
-        val window = TestComposeWindow(width = 40, height = 40)
-        window.setContent {
-            Box(
-                Modifier.graphicsLayer(
-                        scaleX = 2f,
-                        scaleY = 0.5f,
-                        transformOrigin = TransformOrigin(0f, 0f)
-                    )
-                    .requiredSize(10f.dp, 10f.dp)
-                    .background(Color.Red)
-            )
-            Box(
-                Modifier.graphicsLayer(
-                        translationX = 10f,
-                        translationY = 20f,
-                        scaleX = 2f,
-                        scaleY = 0.5f
-                    )
-                    .requiredSize(10f.dp, 10f.dp)
-                    .background(Color.Blue)
-            )
-        }
-        screenshotRule.snap(window.surface)
-    }
-
-    @Test
-    fun rotationZ() {
-        val window = TestComposeWindow(width = 40, height = 40)
-        window.setContent {
-            Box(
-                Modifier.graphicsLayer(
-                        translationX = 10f,
-                        rotationZ = 90f,
-                        scaleX = 2f,
-                        scaleY = 0.5f,
-                        transformOrigin = TransformOrigin(0f, 0f)
-                    )
-                    .requiredSize(10f.dp, 10f.dp)
-                    .background(Color.Red)
-            )
-            Box(
-                Modifier.graphicsLayer(translationX = 10f, translationY = 20f, rotationZ = 45f)
-                    .requiredSize(10f.dp, 10f.dp)
-                    .background(Color.Blue)
-            )
-        }
-        screenshotRule.snap(window.surface)
-    }
-
-    @Test
-    fun rotationX() {
-        val window = TestComposeWindow(width = 40, height = 40)
-
-        window.setContent {
-            Box(
-                Modifier.graphicsLayer(rotationX = 45f)
-                    .requiredSize(10f.dp, 10f.dp)
-                    .background(Color.Blue)
-            )
-            Box(
-                Modifier.graphicsLayer(
-                        translationX = 20f,
-                        transformOrigin = TransformOrigin(0f, 0f),
-                        rotationX = 45f
-                    )
-                    .requiredSize(10f.dp, 10f.dp)
-                    .background(Color.Blue)
-            )
-        }
-        screenshotRule.snap(window.surface)
-    }
-
-    @Test
-    fun rotationY() {
-        val window = TestComposeWindow(width = 40, height = 40)
-        window.setContent {
-            Box(
-                Modifier.graphicsLayer(rotationY = 45f)
-                    .requiredSize(10f.dp, 10f.dp)
-                    .background(Color.Blue)
-            )
-            Box(
-                Modifier.graphicsLayer(
-                        translationX = 20f,
-                        transformOrigin = TransformOrigin(0f, 0f),
-                        rotationY = 45f
-                    )
-                    .requiredSize(10f.dp, 10f.dp)
-                    .background(Color.Blue)
-            )
-        }
-        screenshotRule.snap(window.surface)
-    }
-
-    @Test
-    fun `nested layer transformations`() {
-        val window = TestComposeWindow(width = 40, height = 40)
-        window.setContent {
-            Box(
-                Modifier.graphicsLayer(rotationZ = 45f, translationX = 10f)
-                    .requiredSize(20f.dp, 20f.dp)
-                    .background(Color.Green)
-            ) {
-                Box(
-                    Modifier.graphicsLayer(rotationZ = 45f)
-                        .requiredSize(20f.dp, 20f.dp)
-                        .background(Color.Blue)
-                )
-            }
-        }
-        screenshotRule.snap(window.surface)
-    }
-
-    @Test
-    fun clip() {
-        val window = TestComposeWindow(width = 40, height = 40)
-        window.setContent {
-            Box(
-                Modifier.graphicsLayer(
-                        translationX = 10f,
-                        translationY = 10f,
-                        transformOrigin = TransformOrigin(0f, 0f),
-                        clip = false
-                    )
-                    .requiredSize(10f.dp, 10f.dp)
-                    .background(Color.Red)
-            ) {
-                Box(
-                    Modifier.graphicsLayer(transformOrigin = TransformOrigin(0f, 0f), clip = false)
-                        .requiredSize(20f.dp, 2f.dp)
-                        .background(Color.Blue)
-                )
-            }
-
-            Box(
-                Modifier.graphicsLayer(
-                        translationX = 10f,
-                        translationY = 30f,
-                        transformOrigin = TransformOrigin(0f, 0f),
-                        clip = true
-                    )
-                    .requiredSize(10f.dp, 10f.dp)
-                    .background(Color.Red)
-            ) {
-                Box(
-                    Modifier.graphicsLayer(transformOrigin = TransformOrigin(0f, 0f), clip = false)
-                        .requiredSize(20f.dp, 2f.dp)
-                        .background(Color.Blue)
-                )
-            }
-
-            Box(
-                Modifier.graphicsLayer(
-                        translationX = 30f,
-                        translationY = 10f,
-                        transformOrigin = TransformOrigin(0f, 0f),
-                        clip = true,
-                        shape = RoundedCornerShape(5.dp)
-                    )
-                    .requiredSize(10f.dp, 10f.dp)
-                    .background(Color.Red)
-            ) {
-                Box(
-                    Modifier.graphicsLayer(transformOrigin = TransformOrigin(0f, 0f), clip = false)
-                        .requiredSize(20f.dp, 2f.dp)
-                        .background(Color.Blue)
-                )
-            }
-        }
-        screenshotRule.snap(window.surface)
-    }
-
-    @Test
-    fun alpha() {
-        val window = TestComposeWindow(width = 40, height = 40)
-        window.setContent {
-            Box(
-                Modifier.padding(start = 5.dp)
-                    .graphicsLayer(
-                        translationX = -5f,
-                        translationY = 5f,
-                        transformOrigin = TransformOrigin(0f, 0f),
-                        alpha = 0.5f
-                    )
-                    .requiredSize(10f.dp, 10f.dp)
-                    .background(Color.Green)
-            ) {
-                // This box will be clipped (because if we use alpha, we draw into
-                // intermediate buffer)
-                Box(Modifier.requiredSize(30f.dp, 30f.dp).background(Color.Blue))
-            }
-
-            Box(
-                Modifier.padding(start = 15.dp)
-                    .graphicsLayer(alpha = 0.5f)
-                    .requiredSize(15f.dp, 15f.dp)
-                    .background(Color.Red)
-            ) {
-                Box(
-                    Modifier.graphicsLayer(alpha = 0.5f)
-                        .requiredSize(10f.dp, 10f.dp)
-                        .background(Color.Blue)
-                )
-            }
-
-            Box(
-                Modifier.graphicsLayer(alpha = 0f)
-                    .requiredSize(10f.dp, 10f.dp)
-                    .background(Color.Blue)
-            )
-        }
-        screenshotRule.snap(window.surface)
-    }
-
-    @Test
-    fun elevation() {
-        val window = TestComposeWindow(width = 40, height = 40)
-        window.setContent {
-            Box(Modifier.graphicsLayer(shadowElevation = 5f).requiredSize(20f.dp, 20f.dp))
-            Box(
-                Modifier.graphicsLayer(translationX = 20f, shadowElevation = 5f)
-                    .requiredSize(20f.dp, 20f.dp)
-            ) {
-                Box(Modifier.requiredSize(20f.dp, 20f.dp).background(Color.Blue))
-            }
-            Box(
-                Modifier.graphicsLayer(translationY = 20f, alpha = 0.8f, shadowElevation = 5f)
-                    .requiredSize(20f.dp, 20f.dp)
-            ) {
-                Box(Modifier.requiredSize(20f.dp, 20f.dp).background(Color.Red))
-            }
-            Box(
-                Modifier.graphicsLayer(
-                        translationX = 20f,
-                        translationY = 20f,
-                        shadowElevation = 5f,
-                        alpha = 0.8f
-                    )
-                    .requiredSize(20f.dp, 20f.dp)
-            )
-        }
-        screenshotRule.snap(window.surface)
-    }
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/RenderingTestScope.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/RenderingTestScope.kt
deleted file mode 100644
index b991389..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/RenderingTestScope.kt
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.platform
-
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.ComposeScene
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.toArgb
-import androidx.compose.ui.unit.Constraints
-import androidx.compose.ui.unit.Density
-import kotlin.coroutines.CoroutineContext
-import kotlinx.coroutines.CompletableDeferred
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.swing.Swing
-import kotlinx.coroutines.yield
-import org.jetbrains.skia.Canvas
-import org.jetbrains.skia.Surface
-import org.jetbrains.skiko.FrameDispatcher
-
-internal fun renderingTest(
-    width: Int,
-    height: Int,
-    context: CoroutineContext = Dispatchers.Swing,
-    block: suspend RenderingTestScope.() -> Unit
-) =
-    runBlocking(Dispatchers.Swing) {
-        val scope = RenderingTestScope(width, height, context)
-        try {
-            scope.block()
-        } finally {
-            scope.dispose()
-        }
-    }
-
-internal class RenderingTestScope(
-    val width: Int,
-    val height: Int,
-    coroutineContext: CoroutineContext
-) {
-    var currentTimeMillis = 0L
-
-    private val frameDispatcher =
-        FrameDispatcher(coroutineContext) { onRender(currentTimeMillis * 1_000_000) }
-
-    val surface: Surface = Surface.makeRasterN32Premul(width, height)
-    val canvas: Canvas = surface.canvas
-    val scene =
-        ComposeScene(
-                coroutineContext = coroutineContext,
-                invalidate = frameDispatcher::scheduleFrame
-            )
-            .apply { constraints = Constraints(maxWidth = width, maxHeight = height) }
-
-    var density: Float
-        get() = scene.density.density
-        set(value) {
-            scene.density = Density(value, scene.density.fontScale)
-        }
-
-    fun dispose() {
-        scene.close()
-        frameDispatcher.cancel()
-    }
-
-    private var onRender = CompletableDeferred<Unit>()
-
-    fun setContent(content: @Composable () -> Unit) {
-        scene.setContent { content() }
-    }
-
-    private fun onRender(timeNanos: Long) {
-        canvas.clear(Color.Transparent.toArgb())
-        scene.render(canvas, timeNanos)
-        onRender.complete(Unit)
-    }
-
-    suspend fun awaitNextRender() {
-        onRender = CompletableDeferred()
-        onRender.await()
-    }
-
-    suspend fun hasRenders(): Boolean {
-        onRender = CompletableDeferred()
-        // repeat multiple times because rendering can be dispatched on the next frames
-        repeat(10) { yield() }
-        return onRender.isCompleted
-    }
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/SkiaLayerTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/SkiaLayerTest.kt
deleted file mode 100644
index 0e6e333..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/SkiaLayerTest.kt
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.platform
-
-import androidx.compose.foundation.shape.CircleShape
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.geometry.Size
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.CompositingStrategy
-import androidx.compose.ui.graphics.DefaultShadowColor
-import androidx.compose.ui.graphics.RectangleShape
-import androidx.compose.ui.graphics.RenderEffect
-import androidx.compose.ui.graphics.ReusableGraphicsLayerScope
-import androidx.compose.ui.graphics.Shape
-import androidx.compose.ui.graphics.TransformOrigin
-import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.compose.ui.unit.Density
-import androidx.compose.ui.unit.IntOffset
-import androidx.compose.ui.unit.IntSize
-import androidx.compose.ui.unit.LayoutDirection
-import androidx.compose.ui.unit.round
-import kotlin.math.PI
-import kotlin.math.cos
-import kotlin.math.roundToInt
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertFalse
-import org.junit.Assert.assertTrue
-import org.junit.Rule
-import org.junit.Test
-
-class SkiaLayerTest {
-    @get:Rule val rule = createComposeRule()
-
-    private val layer = TestSkiaLayer()
-    private val cos45 = cos(PI / 4)
-
-    @Test
-    fun initial() {
-        val matrix = layer.matrix
-
-        assertEquals(IntOffset(0, 0), matrix.map(Offset(0f, 0f)).round())
-        assertEquals(IntOffset(100, 10), matrix.map(Offset(100f, 10f)).round())
-    }
-
-    @Test
-    fun move() {
-        layer.move(IntOffset(10, 20))
-        val matrix = layer.matrix
-
-        assertEquals(IntOffset(0, 0), matrix.map(Offset(0f, 0f)).round())
-        assertEquals(IntOffset(100, 10), matrix.map(Offset(100f, 10f)).round())
-    }
-
-    @Test
-    fun resize() {
-        layer.resize(IntSize(100, 10))
-        val matrix = layer.matrix
-
-        assertEquals(IntOffset(0, 0), matrix.map(Offset(0f, 0f)).round())
-        assertEquals(IntOffset(100, 10), matrix.map(Offset(100f, 10f)).round())
-    }
-
-    @Test
-    fun `resize and move`() {
-        layer.resize(IntSize(100, 10))
-        layer.move(IntOffset(10, 20))
-        val matrix = layer.matrix
-
-        assertEquals(IntOffset(0, 0), matrix.map(Offset(0f, 0f)).round())
-        assertEquals(IntOffset(100, 10), matrix.map(Offset(100f, 10f)).round())
-    }
-
-    @Test
-    fun `translation, left-top origin`() {
-        layer.resize(IntSize(100, 10))
-        layer.updateProperties(
-            translationX = 10f,
-            translationY = 20f,
-            transformOrigin = TransformOrigin(0f, 0f)
-        )
-        val matrix = layer.matrix
-
-        assertEquals(IntOffset(10, 20), matrix.map(Offset(0f, 0f)).round())
-        assertEquals(IntOffset(110, 30), matrix.map(Offset(100f, 10f)).round())
-    }
-
-    @Test
-    fun `translation, bottom-right origin`() {
-        layer.resize(IntSize(100, 10))
-        layer.updateProperties(
-            translationX = 10f,
-            translationY = 20f,
-            transformOrigin = TransformOrigin(1f, 1f)
-        )
-        val matrix = layer.matrix
-
-        assertEquals(IntOffset(10, 20), matrix.map(Offset(0f, 0f)).round())
-        assertEquals(IntOffset(110, 30), matrix.map(Offset(100f, 10f)).round())
-    }
-
-    @Test
-    fun `scale, left-top origin`() {
-        layer.resize(IntSize(100, 10))
-        layer.updateProperties(scaleX = 2f, scaleY = 4f, transformOrigin = TransformOrigin(0f, 0f))
-        val matrix = layer.matrix
-
-        assertEquals(IntOffset(0, 0), matrix.map(Offset(0f, 0f)).round())
-        assertEquals(IntOffset(200, 40), matrix.map(Offset(100f, 10f)).round())
-    }
-
-    @Test
-    fun `scale, bottom-right origin`() {
-        layer.resize(IntSize(100, 10))
-        layer.updateProperties(scaleX = 2f, scaleY = 4f, transformOrigin = TransformOrigin(1f, 1f))
-        val matrix = layer.matrix
-
-        assertEquals(IntOffset(-100, -30), matrix.map(Offset(0f, 0f)).round())
-        assertEquals(IntOffset(100, 10), matrix.map(Offset(100f, 10f)).round())
-    }
-
-    @Test
-    fun `rotationX, left-top origin`() {
-        layer.resize(IntSize(100, 10))
-        layer.updateProperties(rotationX = 45f, transformOrigin = TransformOrigin(0f, 0f))
-        val matrix = layer.matrix
-
-        val y = (10 * cos45).roundToInt()
-        assertEquals(IntOffset(0, 0), matrix.map(Offset(0f, 0f)).round())
-        assertEquals(IntOffset(100, y), matrix.map(Offset(100f, 10f)).round())
-    }
-
-    @Test
-    fun `rotationX, bottom-right origin`() {
-        layer.resize(IntSize(100, 10))
-        layer.updateProperties(rotationX = 45f, transformOrigin = TransformOrigin(1f, 1f))
-        val matrix = layer.matrix
-
-        val y = 10 * (1 - cos45.toFloat())
-        assertOffsetEquals(Offset(0f, y), matrix.map(Offset(0f, 0f)))
-        assertOffsetEquals(Offset(100f, 10f), matrix.map(Offset(100f, 10f)))
-    }
-
-    @Test
-    fun `rotationY, left-top origin`() {
-        layer.resize(IntSize(100, 10))
-        layer.updateProperties(rotationY = 45f, transformOrigin = TransformOrigin(0f, 0f))
-        val matrix = layer.matrix
-
-        val x = (100 * cos45).roundToInt()
-        assertEquals(IntOffset(0, 0), matrix.map(Offset(0f, 0f)).round())
-        assertEquals(IntOffset(x, 10), matrix.map(Offset(100f, 10f)).round())
-    }
-
-    @Test
-    fun `rotationY, bottom-right origin`() {
-        layer.resize(IntSize(100, 10))
-        layer.updateProperties(rotationY = 45f, transformOrigin = TransformOrigin(1f, 1f))
-        val matrix = layer.matrix
-
-        val x = (100 * (1 - cos45)).roundToInt()
-        assertEquals(IntOffset(x, 0), matrix.map(Offset(0f, 0f)).round())
-        assertEquals(IntOffset(100, 10), matrix.map(Offset(100f, 10f)).round())
-    }
-
-    @Test
-    fun `rotationZ, left-top origin`() {
-        layer.resize(IntSize(100, 10))
-        layer.updateProperties(rotationZ = 90f, transformOrigin = TransformOrigin(0f, 0f))
-        val matrix = layer.matrix
-
-        assertEquals(IntOffset(0, 0), matrix.map(Offset(0f, 0f)).round())
-        assertEquals(IntOffset(-10, 100), matrix.map(Offset(100f, 10f)).round())
-    }
-
-    @Test
-    fun `rotationZ, bottom-right origin`() {
-        layer.resize(IntSize(100, 10))
-        layer.updateProperties(rotationZ = 90f, transformOrigin = TransformOrigin(1f, 1f))
-        val matrix = layer.matrix
-
-        assertEquals(IntOffset(110, -90), matrix.map(Offset(0f, 0f)).round())
-        assertEquals(IntOffset(100, 10), matrix.map(Offset(100f, 10f)).round())
-    }
-
-    @Test
-    fun `translation, scale, left-top origin`() {
-        layer.resize(IntSize(100, 10))
-        layer.updateProperties(
-            translationX = 60f,
-            translationY = 7f,
-            scaleX = 2f,
-            scaleY = 4f,
-            transformOrigin = TransformOrigin(0f, 0f)
-        )
-        val matrix = layer.matrix
-
-        assertEquals(IntOffset(0 + 60, 0 + 7), matrix.map(Offset(0f, 0f)).round())
-        assertEquals(IntOffset(100 * 2 + 60, 10 * 4 + 7), matrix.map(Offset(100f, 10f)).round())
-    }
-
-    @Test
-    fun `translation, rotationZ, left-top origin`() {
-        layer.resize(IntSize(100, 10))
-        layer.updateProperties(
-            translationX = 60f,
-            translationY = 7f,
-            rotationZ = 90f,
-            transformOrigin = TransformOrigin(0f, 0f)
-        )
-        val matrix = layer.matrix
-
-        assertEquals(IntOffset(0 + 60, 0 + 7), matrix.map(Offset(0f, 0f)).round())
-        assertEquals(IntOffset(-10 + 60, 100 + 7), matrix.map(Offset(100f, 10f)).round())
-    }
-
-    @Test
-    fun `translation, rotationX, left-top origin`() {
-        layer.resize(IntSize(100, 10))
-        layer.updateProperties(
-            translationX = 60f,
-            translationY = 7f,
-            rotationX = 45f,
-            transformOrigin = TransformOrigin(0f, 0f)
-        )
-        val matrix = layer.matrix
-
-        val y = (10 * cos45).roundToInt()
-        val translationY = (7 * cos45).roundToInt()
-        assertEquals(IntOffset(0 + 60, 0 + translationY), matrix.map(Offset(0f, 0f)).round())
-        assertEquals(IntOffset(100 + 60, y + translationY), matrix.map(Offset(100f, 10f)).round())
-    }
-
-    @Test
-    fun `translation, rotationY, left-top origin`() {
-        layer.resize(IntSize(100, 10))
-        layer.updateProperties(
-            translationX = 60f,
-            translationY = 7f,
-            rotationY = 45f,
-            transformOrigin = TransformOrigin(0f, 0f)
-        )
-        val matrix = layer.matrix
-
-        val x = (100 * cos45).roundToInt()
-        val translationX = (60 * cos45).roundToInt()
-        assertEquals(IntOffset(0 + translationX, 0 + 7), matrix.map(Offset(0f, 0f)).round())
-        assertEquals(IntOffset(x + translationX, 10 + 7), matrix.map(Offset(100f, 10f)).round())
-    }
-
-    @Test
-    fun `scale, rotationZ, left-top origin`() {
-        layer.resize(IntSize(100, 10))
-        layer.updateProperties(
-            scaleX = 2f,
-            scaleY = 4f,
-            rotationZ = 90f,
-            transformOrigin = TransformOrigin(0f, 0f)
-        )
-        val matrix = layer.matrix
-
-        assertEquals(IntOffset(0, 0), matrix.map(Offset(0f, 0f)).round())
-        assertEquals(IntOffset(-10 * 4, 100 * 2), matrix.map(Offset(100f, 10f)).round())
-    }
-
-    @Test
-    fun `translation, scale, rotationZ, left-top origin`() {
-        layer.resize(IntSize(100, 10))
-        layer.updateProperties(
-            translationX = 60f,
-            translationY = 7f,
-            scaleX = 2f,
-            scaleY = 4f,
-            rotationZ = 90f,
-            transformOrigin = TransformOrigin(0f, 0f)
-        )
-        val matrix = layer.matrix
-
-        assertEquals(IntOffset(0 + 60, 0 + 7), matrix.map(Offset(0f, 0f)).round())
-        assertEquals(IntOffset(-10 * 4 + 60, 100 * 2 + 7), matrix.map(Offset(100f, 10f)).round())
-    }
-
-    @Test
-    fun `is in layer`() {
-        layer.resize(IntSize(0, 0))
-        layer.updateProperties(clip = false)
-
-        assertTrue(layer.isInLayer(Offset(-1f, -1f)))
-        assertTrue(layer.isInLayer(Offset(0f, 0f)))
-        assertTrue(layer.isInLayer(Offset(1f, 1f)))
-
-        layer.resize(IntSize(0, 0))
-        layer.updateProperties(clip = true)
-
-        assertFalse(layer.isInLayer(Offset(-1f, -1f)))
-        assertFalse(layer.isInLayer(Offset(0f, 0f)))
-        assertFalse(layer.isInLayer(Offset(1f, 1f)))
-
-        layer.resize(IntSize(0, 0))
-        layer.updateProperties(clip = true, shape = CircleShape)
-
-        assertFalse(layer.isInLayer(Offset(-1f, -1f)))
-        assertFalse(layer.isInLayer(Offset(0f, 0f)))
-        assertFalse(layer.isInLayer(Offset(1f, 1f)))
-
-        layer.resize(IntSize(1, 2))
-        layer.updateProperties(clip = true, size = Size(1f, 2f))
-
-        assertFalse(layer.isInLayer(Offset(-1f, -1f)))
-        assertTrue(layer.isInLayer(Offset(0f, 0f)))
-        assertTrue(layer.isInLayer(Offset(0f, 1f)))
-        assertFalse(layer.isInLayer(Offset(0f, 2f)))
-        assertFalse(layer.isInLayer(Offset(1f, 0f)))
-
-        layer.resize(IntSize(100, 200))
-        layer.updateProperties(clip = true, shape = CircleShape, size = Size(100f, 200f))
-
-        assertFalse(layer.isInLayer(Offset(5f, 5f)))
-        assertFalse(layer.isInLayer(Offset(95f, 195f)))
-        assertTrue(layer.isInLayer(Offset(50f, 100f)))
-    }
-
-    private fun TestSkiaLayer() =
-        SkiaLayer(Density(1f, 1f), invalidateParentLayer = {}, drawBlock = { _, _ -> })
-
-    private fun SkiaLayer.updateProperties(
-        scaleX: Float = 1f,
-        scaleY: Float = 1f,
-        alpha: Float = 1f,
-        translationX: Float = 0f,
-        translationY: Float = 0f,
-        shadowElevation: Float = 0f,
-        ambientShadowColor: Color = DefaultShadowColor,
-        spotShadowColor: Color = DefaultShadowColor,
-        rotationX: Float = 0f,
-        rotationY: Float = 0f,
-        rotationZ: Float = 0f,
-        cameraDistance: Float = 0f,
-        transformOrigin: TransformOrigin = TransformOrigin.Center,
-        shape: Shape = RectangleShape,
-        clip: Boolean = false,
-        renderEffect: RenderEffect? = null,
-        compositingStrategy: CompositingStrategy = CompositingStrategy.Auto,
-        size: Size = Size.Zero
-    ) {
-        val scope = ReusableGraphicsLayerScope()
-        scope.cameraDistance = cameraDistance
-        scope.scaleX = scaleX
-        scope.scaleY = scaleY
-        scope.alpha = alpha
-        scope.translationX = translationX
-        scope.translationY = translationY
-        scope.shadowElevation = shadowElevation
-        scope.ambientShadowColor = ambientShadowColor
-        scope.spotShadowColor = spotShadowColor
-        scope.rotationX = rotationX
-        scope.rotationY = rotationY
-        scope.rotationZ = rotationZ
-        scope.cameraDistance = cameraDistance
-        scope.transformOrigin = transformOrigin
-        scope.shape = shape
-        scope.clip = clip
-        scope.renderEffect = renderEffect
-        scope.compositingStrategy = compositingStrategy
-        scope.layoutDirection = LayoutDirection.Ltr
-        scope.graphicsDensity = Density(1f)
-        scope.outline = shape.createOutline(size, scope.layoutDirection, scope.graphicsDensity)
-        updateLayerProperties(scope)
-    }
-}
-
-fun assertOffsetEquals(a: Offset, b: Offset, delta: Float = 0.02f) {
-    assertEquals(a.x, b.x, delta)
-    assertEquals(a.y, b.y, delta)
-}
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
deleted file mode 100644
index 735f3a7..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/TestComposeWindowTest.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.platform
-
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.material.ExtendedFloatingActionButton
-import androidx.compose.material.Icon
-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 {
-    @Test
-    fun `run multiple TestComposeWindow`() {
-        for (i in 1..15) {
-            TestComposeWindow(800, 800).setContent {
-                Box(Modifier.fillMaxWidth()) {
-                    ExtendedFloatingActionButton(
-                        icon = { Icon(Icons.Filled.AccountBox, "") },
-                        text = {},
-                        onClick = {},
-                        modifier = Modifier.fillMaxWidth()
-                    )
-                }
-            }
-        }
-    }
-
-    @Test(timeout = 5000)
-    fun `disposing TestComposeWindow should not cancel coroutineContext's Job`() {
-        runBlocking(Dispatchers.Swing) {
-            val window = TestComposeWindow(100, 100, coroutineContext = coroutineContext)
-            window.dispose()
-        }
-    }
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/res/DesktopSvgResourcesTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/res/DesktopSvgResourcesTest.kt
deleted file mode 100644
index e5de1db..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/res/DesktopSvgResourcesTest.kt
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.res
-
-import androidx.compose.foundation.Image
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.size
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.isLinux
-import androidx.compose.ui.isWindows
-import androidx.compose.ui.layout.ContentScale
-import androidx.compose.ui.platform.TestComposeWindow
-import androidx.compose.ui.test.InternalTestApi
-import androidx.compose.ui.test.junit4.DesktopScreenshotTestRule
-import androidx.compose.ui.unit.dp
-import org.junit.Assume.assumeTrue
-import org.junit.Rule
-import org.junit.Test
-
-@OptIn(InternalTestApi::class)
-class DesktopSvgResourcesTest {
-    @get:Rule val screenshotRule = DesktopScreenshotTestRule("compose/ui/ui-desktop/res")
-
-    @Test
-    fun `load SVG with specified size`() {
-        assumeTrue(isLinux || isWindows)
-
-        val window = TestComposeWindow(width = 200, height = 200)
-        window.setContent {
-            Image(
-                painterResource("androidx/compose/ui/res/star-size-100.svg"),
-                contentDescription = "Star"
-            )
-        }
-        screenshotRule.snap(window.surface)
-    }
-
-    @Test
-    fun `load SVG with unspecified size`() {
-        assumeTrue(isLinux || isWindows)
-
-        val window = TestComposeWindow(width = 200, height = 200)
-        window.setContent {
-            Image(
-                painterResource("androidx/compose/ui/res/star-size-unspecified.svg"),
-                contentDescription = "Star"
-            )
-        }
-        screenshotRule.snap(window.surface)
-    }
-
-    @Test
-    fun `load SVG with unspecified viewbox`() {
-        assumeTrue(isLinux || isWindows)
-
-        val window = TestComposeWindow(width = 200, height = 200)
-        window.setContent {
-            Image(
-                painterResource("androidx/compose/ui/res/star-viewbox-unspecified.svg"),
-                contentDescription = "Star"
-            )
-        }
-        screenshotRule.snap(window.surface)
-    }
-
-    @Test
-    fun `load SVG with custom size`() {
-        assumeTrue(isLinux || isWindows)
-
-        val window = TestComposeWindow(width = 200, height = 200)
-        window.setContent {
-            Image(
-                painterResource("androidx/compose/ui/res/star-size-100.svg"),
-                contentDescription = "Star",
-                modifier = Modifier.size(50.dp)
-            )
-        }
-        screenshotRule.snap(window.surface)
-    }
-
-    @Test
-    fun `load SVG and fill bounds`() {
-        assumeTrue(isLinux || isWindows)
-
-        val window = TestComposeWindow(width = 200, height = 300)
-        window.setContent {
-            Image(
-                painterResource("androidx/compose/ui/res/star-size-100.svg"),
-                contentDescription = "Star",
-                contentScale = ContentScale.FillBounds,
-                modifier = Modifier.fillMaxSize()
-            )
-        }
-        screenshotRule.snap(window.surface)
-    }
-
-    @Test
-    fun `load SVG with unspecified viewbox and fill bounds`() {
-        assumeTrue(isLinux || isWindows)
-
-        val window = TestComposeWindow(width = 200, height = 300)
-        window.setContent {
-            Image(
-                painterResource("androidx/compose/ui/res/star-viewbox-unspecified.svg"),
-                contentDescription = "Star",
-                contentScale = ContentScale.FillBounds,
-                modifier = Modifier.fillMaxSize()
-            )
-        }
-        screenshotRule.snap(window.surface)
-    }
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/util/AddRemoveMutableListTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/util/AddRemoveMutableListTest.kt
deleted file mode 100644
index b3845a3..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/util/AddRemoveMutableListTest.kt
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.util
-
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-
-class AddRemoveMutableListTest {
-    @Test
-    fun `add items`() {
-        val list = TestList()
-
-        list.add(1)
-        list.add(2)
-        list.add(3)
-
-        assertThat(list).isEqualTo(listOf(1, 2, 3))
-    }
-
-    @Test
-    fun `add items to the middle`() {
-        val list = TestList(1, 2, 3)
-
-        list.add(0, -1)
-        assertThat(list).isEqualTo(listOf(-1, 1, 2, 3))
-
-        list.add(1, 0)
-        assertThat(list).isEqualTo(listOf(-1, 0, 1, 2, 3))
-
-        list.add(5, 4)
-        assertThat(list).isEqualTo(listOf(-1, 0, 1, 2, 3, 4))
-    }
-
-    @Test
-    fun `set item`() {
-        val list = TestList(1, 2, 3, 4)
-
-        list[1] = 22
-        list[0] = 11
-        list[2] = 33
-        list[3] = 44
-
-        assertThat(list).isEqualTo(listOf(11, 22, 33, 44))
-    }
-}
-
-// TODO(demin): why there is a compilation error when we use AddRemoveMutableList<Int>() ?
-
-@Suppress("UNCHECKED_CAST")
-private class TestList(vararg items: Int) : AddRemoveMutableList<Any>() {
-    private val list: MutableList<Any> = items.toMutableList() as MutableList<Any>
-
-    override val size: Int
-        get() = list.size
-
-    override fun get(index: Int): Any = list[index]
-
-    override fun performAdd(element: Any) {
-        list.add(element)
-    }
-
-    override fun performRemove(index: Int) {
-        list.removeAt(index)
-    }
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/util/UpdateEffectTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/util/UpdateEffectTest.kt
deleted file mode 100644
index b54d9eb..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/util/UpdateEffectTest.kt
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.util
-
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.test.junit4.createComposeRule
-import com.google.common.truth.Truth.assertThat
-import org.junit.Ignore
-import org.junit.Rule
-import org.junit.Test
-
-@Ignore("b/271123970 Fails in AOSP. Will be fixed after upstreaming Compose for Desktop")
-internal class UpdateEffectTest {
-    @get:Rule val rule = createComposeRule()
-
-    @Test
-    fun `call update when any mutableStateOf is changed`() {
-        var state1 by mutableStateOf(0)
-        var state2 by mutableStateOf(0)
-        var updatedState1 = -1
-        var updatedState2 = -1
-
-        rule.setContent {
-            UpdateEffect {
-                updatedState1 = state1
-                updatedState2 = state2
-            }
-        }
-
-        rule.waitForIdle()
-        assertThat(updatedState1).isEqualTo(state1)
-        assertThat(updatedState2).isEqualTo(state2)
-
-        state1 = 1
-        rule.waitForIdle()
-        assertThat(updatedState1).isEqualTo(state1)
-        assertThat(updatedState2).isEqualTo(state2)
-
-        state2 = 1
-        rule.waitForIdle()
-        assertThat(updatedState1).isEqualTo(state1)
-        assertThat(updatedState2).isEqualTo(state2)
-
-        state1 = 1
-        state2 = 1
-        rule.waitForIdle()
-        assertThat(updatedState1).isEqualTo(state1)
-        assertThat(updatedState2).isEqualTo(state2)
-    }
-
-    @Test
-    fun `don't call update if there no any changed state`() {
-        var state = 0
-        var updatedState = -1
-
-        rule.setContent { UpdateEffect { updatedState = state } }
-
-        rule.waitForIdle()
-        assertThat(updatedState).isEqualTo(state)
-
-        state = 1
-        rule.waitForIdle()
-        assertThat(updatedState).isNotEqualTo(state)
-    }
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/window/ApplicationTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/window/ApplicationTest.kt
deleted file mode 100644
index 760911a..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/window/ApplicationTest.kt
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.window
-
-import androidx.compose.foundation.background
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.size
-import androidx.compose.runtime.DisposableEffect
-import androidx.compose.runtime.ExperimentalComposeApi
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.MonotonicFrameClock
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.monotonicFrameClock
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.awt.ComposeWindow
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.unit.DpSize
-import androidx.compose.ui.unit.dp
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.CompletableDeferred
-import org.junit.Test
-
-class ApplicationTest {
-    @Test
-    fun `run application`() = runApplicationTest {
-        var isInit = false
-        var isDisposed = false
-
-        val appJob = launchApplication {
-            DisposableEffect(Unit) {
-                isInit = true
-                onDispose { isDisposed = true }
-            }
-        }
-
-        appJob.join()
-
-        assertThat(isInit).isTrue()
-        assertThat(isDisposed).isTrue()
-    }
-
-    @Test
-    fun `run application with launched effect`() = runApplicationTest {
-        val onEffectLaunch = CompletableDeferred<Unit>()
-        val shouldEnd = CompletableDeferred<Unit>()
-
-        launchApplication {
-            LaunchedEffect(Unit) {
-                onEffectLaunch.complete(Unit)
-                shouldEnd.await()
-            }
-        }
-
-        onEffectLaunch.await()
-        shouldEnd.complete(Unit)
-    }
-
-    @Test
-    fun `run two applications`() = runApplicationTest {
-        var window1: ComposeWindow? = null
-        var window2: ComposeWindow? = null
-
-        var isOpen1 by mutableStateOf(true)
-        var isOpen2 by mutableStateOf(true)
-
-        launchApplication {
-            if (isOpen1) {
-                Window(
-                    onCloseRequest = {},
-                    state =
-                        rememberWindowState(
-                            size = DpSize(600.dp, 600.dp),
-                        )
-                ) {
-                    window1 = this.window
-                    Box(Modifier.size(32.dp).background(Color.Red))
-                }
-            }
-        }
-
-        launchApplication {
-            if (isOpen2) {
-                Window(
-                    onCloseRequest = {},
-                    state =
-                        rememberWindowState(
-                            size = DpSize(300.dp, 300.dp),
-                        )
-                ) {
-                    window2 = this.window
-                    Box(Modifier.size(32.dp).background(Color.Blue))
-                }
-            }
-        }
-
-        awaitIdle()
-        assertThat(window1?.isShowing).isTrue()
-        assertThat(window2?.isShowing).isTrue()
-
-        isOpen1 = false
-        awaitIdle()
-        assertThat(window1?.isShowing).isFalse()
-        assertThat(window2?.isShowing).isTrue()
-
-        isOpen2 = false
-        awaitIdle()
-        assertThat(window1?.isShowing).isFalse()
-        assertThat(window2?.isShowing).isFalse()
-    }
-
-    @OptIn(ExperimentalComposeApi::class)
-    @Test
-    fun `window shouldn't use MonotonicFrameClock from application context`() = runApplicationTest {
-        lateinit var appClock: MonotonicFrameClock
-        lateinit var windowClock: MonotonicFrameClock
-
-        launchApplication {
-            LaunchedEffect(Unit) { appClock = coroutineContext.monotonicFrameClock }
-
-            Window(onCloseRequest = {}) {
-                LaunchedEffect(Unit) { windowClock = coroutineContext.monotonicFrameClock }
-            }
-        }
-
-        awaitIdle()
-        assertThat(windowClock).isNotEqualTo(appClock)
-
-        exitApplication()
-    }
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/window/DesktopPopupTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/window/DesktopPopupTest.kt
deleted file mode 100644
index f524624..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/window/DesktopPopupTest.kt
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.window
-
-import androidx.compose.foundation.Canvas
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.lazy.LazyColumn
-import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.runtime.DisposableEffect
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.derivedStateOf
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.runtime.snapshots.Snapshot
-import androidx.compose.runtime.staticCompositionLocalOf
-import androidx.compose.runtime.withFrameNanos
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.layout.Layout
-import androidx.compose.ui.platform.LocalDensity
-import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.compose.ui.unit.Density
-import androidx.compose.ui.unit.dp
-import com.google.common.truth.Truth
-import org.junit.Rule
-import org.junit.Test
-
-class DesktopPopupTest {
-    @get:Rule val rule = createComposeRule()
-
-    @Test
-    fun `pass composition locals to popup`() {
-        val compositionLocal = staticCompositionLocalOf<Int> { error("not set") }
-
-        var actualLocalValue = 0
-
-        rule.setContent {
-            CompositionLocalProvider(compositionLocal provides 3) {
-                Popup { actualLocalValue = compositionLocal.current }
-            }
-        }
-
-        Truth.assertThat(actualLocalValue).isEqualTo(3)
-    }
-
-    @Test
-    fun `onDispose inside popup`() {
-        var isPopupShowing by mutableStateOf(true)
-        var isDisposed = false
-
-        rule.setContent {
-            if (isPopupShowing) {
-                Popup { DisposableEffect(Unit) { onDispose { isDisposed = true } } }
-            }
-        }
-
-        isPopupShowing = false
-        rule.waitForIdle()
-
-        Truth.assertThat(isDisposed).isEqualTo(true)
-    }
-
-    @Test
-    fun `use density inside popup`() {
-        var density by mutableStateOf(Density(2f, 1f))
-        var densityInsidePopup = 0f
-
-        rule.setContent {
-            CompositionLocalProvider(LocalDensity provides density) {
-                Popup { densityInsidePopup = LocalDensity.current.density }
-            }
-        }
-
-        Truth.assertThat(densityInsidePopup).isEqualTo(2f)
-
-        density = Density(3f, 1f)
-        rule.waitForIdle()
-        Truth.assertThat(densityInsidePopup).isEqualTo(3f)
-    }
-
-    @Test(timeout = 5000) // TODO(demin): why, when an error has occurred, this test never ends?
-    fun `(Bug) after open popup use derivedStateOf inside main window draw`() {
-        var showPopup by mutableStateOf(false)
-
-        rule.setContent {
-            val isPressed = derivedStateOf { false }
-
-            Canvas(Modifier.size(100.dp)) { isPressed.value }
-
-            if (showPopup) {
-                Popup { Box(Modifier) }
-            }
-        }
-
-        rule.waitForIdle()
-
-        showPopup = true
-
-        rule.waitForIdle()
-    }
-
-    @Test(timeout = 5000)
-    fun `(Bug) after open popup use sendApplyNotifications inside main window draw`() {
-        var showPopup by mutableStateOf(false)
-
-        rule.setContent {
-            Canvas(Modifier.size(100.dp)) {
-                if (showPopup) {
-                    Snapshot.sendApplyNotifications()
-                }
-            }
-
-            if (showPopup) {
-                Popup { Box(Modifier) }
-            }
-        }
-
-        rule.waitForIdle()
-
-        showPopup = true
-
-        rule.waitForIdle()
-    }
-
-    @Test(timeout = 5000)
-    fun `(Bug) after open popup use sendApplyNotifications inside popup layout`() {
-        var showPopup by mutableStateOf(false)
-        var state by mutableStateOf(0)
-        var applyState by mutableStateOf(false)
-        var lastCompositionState = 0
-
-        rule.setContent {
-            Canvas(Modifier.size(100.dp)) { lastCompositionState = state }
-
-            if (showPopup) {
-                Popup {
-                    Layout(
-                        content = {},
-                        measurePolicy = { _, _ ->
-                            layout(10, 10) {
-                                if (applyState && state == 0) {
-                                    state++
-                                    Snapshot.sendApplyNotifications()
-                                }
-                            }
-                        }
-                    )
-                }
-            }
-        }
-
-        rule.waitForIdle()
-
-        showPopup = true
-
-        rule.waitForIdle()
-
-        applyState = true
-
-        rule.waitForIdle()
-
-        Truth.assertThat(lastCompositionState).isEqualTo(1)
-    }
-
-    @Test(timeout = 5000)
-    fun `(Bug) use Popup inside LazyColumn`() {
-        rule.setContent {
-            var count by remember { mutableStateOf(0) }
-            LazyColumn { items(count) { Popup {} } }
-            LaunchedEffect(Unit) {
-                withFrameNanos { count++ }
-                withFrameNanos { count++ }
-            }
-        }
-
-        rule.waitForIdle()
-    }
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/window/MenuBarTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/window/MenuBarTest.kt
deleted file mode 100644
index 99b9ba2..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/window/MenuBarTest.kt
+++ /dev/null
@@ -1,465 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.window
-
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.awt.ComposeWindow
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.painter.Painter
-import androidx.compose.ui.readFirstPixel
-import androidx.compose.ui.testImage
-import com.google.common.truth.Truth.assertThat
-import javax.swing.JCheckBoxMenuItem
-import javax.swing.JRadioButtonMenuItem
-import javax.swing.JSeparator
-import org.junit.Test
-
-class MenuBarTest {
-    @Test(timeout = 20000)
-    fun `show and hide menu bar`() = runApplicationTest {
-        var isOpen by mutableStateOf(true)
-        var isMenubarShowing by mutableStateOf(true)
-        var window: ComposeWindow? = null
-
-        launchApplication {
-            if (isOpen) {
-                Window(onCloseRequest = {}) {
-                    window = this.window
-
-                    if (isMenubarShowing) {
-                        MenuBar {
-                            Menu("Menu0") {
-                                Item("Item0", onClick = {})
-                                Separator()
-                            }
-                            Menu("Menu1") {}
-                        }
-                    }
-                }
-            }
-        }
-
-        awaitIdle()
-        assertThat(window?.jMenuBar).isNotNull()
-        window?.jMenuBar!!.apply {
-            assertThat(menuCount).isEqualTo(2)
-            assertThat(getMenu(0).text).isEqualTo("Menu0")
-            assertThat(getMenu(1).text).isEqualTo("Menu1")
-
-            getMenu(0).apply {
-                assertThat(itemCount).isEqualTo(2)
-                assertThat(getItem(0).text).isEqualTo("Item0")
-                assertThat(getMenuComponent(1)).isInstanceOf(JSeparator::class.java)
-            }
-
-            getMenu(1).apply { assertThat(itemCount).isEqualTo(0) }
-        }
-
-        isMenubarShowing = false
-        awaitIdle()
-        assertThat(window!!.jMenuBar).isNull()
-
-        isOpen = false
-    }
-
-    @Test(timeout = 20000)
-    fun `show and hide menu`() = runApplicationTest {
-        var isOpen by mutableStateOf(true)
-        var isMenuShowing by mutableStateOf(true)
-        var window: ComposeWindow? = null
-
-        launchApplication {
-            if (isOpen) {
-                Window(onCloseRequest = {}) {
-                    window = this.window
-
-                    MenuBar {
-                        if (isMenuShowing) {
-                            Menu("Menu0") {
-                                Item("Item0", onClick = {})
-                                Separator()
-                            }
-                        }
-                        Menu("Menu1") {}
-                    }
-                }
-            }
-        }
-
-        awaitIdle()
-
-        isMenuShowing = false
-        awaitIdle()
-        assertThat(window!!.jMenuBar.menuCount).isEqualTo(1)
-        window?.jMenuBar!!.apply {
-            assertThat(menuCount).isEqualTo(1)
-            assertThat(getMenu(0).text).isEqualTo("Menu1")
-        }
-
-        isMenuShowing = true
-        awaitIdle()
-        assertThat(window!!.jMenuBar.menuCount).isEqualTo(2)
-        window?.jMenuBar!!.apply {
-            assertThat(menuCount).isEqualTo(2)
-            assertThat(getMenu(0).text).isEqualTo("Menu0")
-            assertThat(getMenu(1).text).isEqualTo("Menu1")
-        }
-
-        isOpen = false
-    }
-
-    @Test(timeout = 20000)
-    fun `show and hide submenu`() = runApplicationTest {
-        var isOpen by mutableStateOf(true)
-        var isSubmenuShowing by mutableStateOf(true)
-        var window: ComposeWindow? = null
-
-        launchApplication {
-            if (isOpen) {
-                Window(onCloseRequest = {}) {
-                    window = this.window
-
-                    MenuBar {
-                        Menu("Menu0") {
-                            if (isSubmenuShowing) {
-                                Menu("Submenu0") {}
-                            }
-                            Item("Item0", onClick = {})
-                            Separator()
-                        }
-                        Menu("Menu1") {}
-                    }
-                }
-            }
-        }
-
-        awaitIdle()
-
-        isSubmenuShowing = false
-        awaitIdle()
-        assertThat(window!!.jMenuBar.getMenu(0).itemCount).isEqualTo(2)
-        window?.jMenuBar!!.getMenu(0).apply {
-            assertThat(itemCount).isEqualTo(2)
-            assertThat(getItem(0).text).isEqualTo("Item0")
-            assertThat(getMenuComponent(1)).isInstanceOf(JSeparator::class.java)
-        }
-
-        isSubmenuShowing = true
-        awaitIdle()
-        assertThat(window!!.jMenuBar.getMenu(0).itemCount).isEqualTo(3)
-        window?.jMenuBar!!.getMenu(0).apply {
-            assertThat(itemCount).isEqualTo(3)
-            assertThat(getItem(0).text).isEqualTo("Submenu0")
-            assertThat(getItem(1).text).isEqualTo("Item0")
-            assertThat(getMenuComponent(2)).isInstanceOf(JSeparator::class.java)
-        }
-
-        isOpen = false
-    }
-
-    @Test(timeout = 20000)
-    fun `change label`() = runApplicationTest {
-        var window: ComposeWindow? = null
-
-        var menuLabel by mutableStateOf("Menu")
-        var submenuLabel by mutableStateOf("Submenu")
-        var itemLabel by mutableStateOf("Item")
-
-        launchApplication {
-            Window(onCloseRequest = {}) {
-                window = this.window
-
-                MenuBar {
-                    Menu(menuLabel) {
-                        Menu(submenuLabel) {}
-                        Item(itemLabel, onClick = {})
-                    }
-                }
-            }
-        }
-
-        awaitIdle()
-        with(window!!.jMenuBar) {
-            assertThat(getMenu(0).text).isEqualTo("Menu")
-            assertThat(getMenu(0).getItem(0).text).isEqualTo("Submenu")
-            assertThat(getMenu(0).getItem(1).text).isEqualTo("Item")
-
-            menuLabel = "Menu2"
-            submenuLabel = "Submenu2"
-            itemLabel = "Item2"
-            awaitIdle()
-            assertThat(getMenu(0).text).isEqualTo("Menu2")
-            assertThat(getMenu(0).getItem(0).text).isEqualTo("Submenu2")
-            assertThat(getMenu(0).getItem(1).text).isEqualTo("Item2")
-        }
-
-        exitApplication()
-    }
-
-    @Test(timeout = 20000)
-    fun `change enabled`() = runApplicationTest {
-        var window: ComposeWindow? = null
-
-        var menuEnabled by mutableStateOf(true)
-        var submenuEnabled by mutableStateOf(true)
-        var itemEnabled by mutableStateOf(true)
-
-        launchApplication {
-            Window(onCloseRequest = {}) {
-                window = this.window
-
-                MenuBar {
-                    Menu("Menu", enabled = menuEnabled) {
-                        Menu("Menu", enabled = submenuEnabled) {}
-                        Item("Item", enabled = itemEnabled, onClick = {})
-                    }
-                }
-            }
-        }
-
-        awaitIdle()
-        with(window!!.jMenuBar) {
-            assertThat(getMenu(0).isEnabled).isTrue()
-            assertThat(getMenu(0).getItem(0).isEnabled).isTrue()
-            assertThat(getMenu(0).getItem(1).isEnabled).isTrue()
-
-            menuEnabled = false
-            submenuEnabled = false
-            itemEnabled = false
-            awaitIdle()
-            assertThat(getMenu(0).isEnabled).isFalse()
-            assertThat(getMenu(0).getItem(0).isEnabled).isFalse()
-            assertThat(getMenu(0).getItem(1).isEnabled).isFalse()
-        }
-
-        exitApplication()
-    }
-
-    @Test(timeout = 20000)
-    fun `change icon`() = runApplicationTest {
-        var window: ComposeWindow? = null
-
-        val redIcon = testImage(Color.Red)
-        val blueIcon = testImage(Color.Blue)
-
-        var icon: Painter? by mutableStateOf(redIcon)
-
-        launchApplication {
-            Window(onCloseRequest = {}) {
-                window = this.window
-
-                MenuBar { Menu("Menu") { Item("Item", icon = icon, onClick = {}) } }
-            }
-        }
-
-        val item by lazy { window!!.jMenuBar.getMenu(0).getItem(0) }
-
-        awaitIdle()
-        assertThat(item.icon?.readFirstPixel()).isEqualTo(Color.Red)
-
-        icon = blueIcon
-        awaitIdle()
-        assertThat(item.icon?.readFirstPixel()).isEqualTo(Color.Blue)
-
-        icon = null
-        awaitIdle()
-        assertThat(item.icon?.readFirstPixel()).isEqualTo(null)
-
-        exitApplication()
-    }
-
-    // bug https://github.com/JetBrains/compose-jb/issues/1097#issuecomment-921108560
-    @Test(timeout = 20000)
-    fun `set icon and disable item`() = runApplicationTest {
-        var window: ComposeWindow? = null
-        val redIcon = testImage(Color.Red)
-
-        launchApplication {
-            Window(onCloseRequest = {}) {
-                window = this.window
-
-                MenuBar {
-                    Menu("Menu") { Item("Item", icon = redIcon, enabled = false, onClick = {}) }
-                }
-            }
-        }
-
-        awaitIdle()
-        window!!.jMenuBar.getMenu(0).doClick()
-        window!!.paint(window!!.graphics)
-
-        exitApplication()
-    }
-
-    @Test(timeout = 20000)
-    fun `change checked of CheckboxItem`() = runApplicationTest {
-        var window: ComposeWindow? = null
-
-        var checked by mutableStateOf(true)
-
-        launchApplication {
-            Window(onCloseRequest = {}) {
-                window = this.window
-
-                MenuBar {
-                    Menu("Menu") {
-                        CheckboxItem("Item", checked = checked, onCheckedChange = { checked = it })
-                    }
-                }
-            }
-        }
-
-        val item by lazy { window!!.jMenuBar.getMenu(0).getItem(0) as JCheckBoxMenuItem }
-
-        awaitIdle()
-        assertThat(item.state).isEqualTo(true)
-
-        checked = false
-        awaitIdle()
-        assertThat(item.state).isEqualTo(false)
-
-        item.doClick()
-        awaitIdle()
-        assertThat(checked).isEqualTo(true)
-        assertThat(item.state).isEqualTo(true)
-
-        exitApplication()
-    }
-
-    @Test(timeout = 20000)
-    fun `don't change checked of CheckboxItem`() = runApplicationTest {
-        var window: ComposeWindow? = null
-
-        var checked by mutableStateOf(true)
-
-        launchApplication {
-            Window(onCloseRequest = {}) {
-                window = this.window
-
-                MenuBar {
-                    Menu("Menu") { CheckboxItem("Item", checked = checked, onCheckedChange = {}) }
-                }
-            }
-        }
-
-        val item by lazy { window!!.jMenuBar.getMenu(0).getItem(0) as JCheckBoxMenuItem }
-
-        awaitIdle()
-        assertThat(item.state).isEqualTo(true)
-
-        checked = false
-        awaitIdle()
-        assertThat(item.state).isEqualTo(false)
-
-        item.doClick()
-        awaitIdle()
-        assertThat(checked).isEqualTo(false)
-        assertThat(item.state).isEqualTo(false)
-
-        exitApplication()
-    }
-
-    @Test(timeout = 20000)
-    fun `change status of RadioButtonItem`() = runApplicationTest {
-        var window: ComposeWindow? = null
-
-        var selected by mutableStateOf(1)
-
-        launchApplication {
-            Window(onCloseRequest = {}) {
-                window = this.window
-
-                MenuBar {
-                    Menu("Menu") {
-                        RadioButtonItem(
-                            "Item0",
-                            selected = selected == 0,
-                            onClick = { selected = 0 }
-                        )
-                        RadioButtonItem(
-                            "Item1",
-                            selected = selected == 1,
-                            onClick = { selected = 1 }
-                        )
-                    }
-                }
-            }
-        }
-
-        val item0 by lazy { window!!.jMenuBar.getMenu(0).getItem(0) as JRadioButtonMenuItem }
-        val item1 by lazy { window!!.jMenuBar.getMenu(0).getItem(1) as JRadioButtonMenuItem }
-
-        awaitIdle()
-        assertThat(item0.isSelected).isEqualTo(false)
-        assertThat(item1.isSelected).isEqualTo(true)
-
-        selected = 0
-        awaitIdle()
-        assertThat(item0.isSelected).isEqualTo(true)
-        assertThat(item1.isSelected).isEqualTo(false)
-
-        item1.doClick()
-        awaitIdle()
-        assertThat(selected).isEqualTo(1)
-        assertThat(item0.isSelected).isEqualTo(false)
-        assertThat(item1.isSelected).isEqualTo(true)
-
-        exitApplication()
-    }
-
-    @Test(timeout = 20000)
-    fun `don't change checked of RadioButtonItem`() = runApplicationTest {
-        var window: ComposeWindow? = null
-
-        var selected by mutableStateOf(1)
-
-        launchApplication {
-            Window(onCloseRequest = {}) {
-                window = this.window
-
-                MenuBar {
-                    Menu("Menu") {
-                        RadioButtonItem("Item0", selected = selected == 0, onClick = {})
-                        RadioButtonItem("Item1", selected = selected == 1, onClick = {})
-                    }
-                }
-            }
-        }
-
-        val item0 by lazy { window!!.jMenuBar.getMenu(0).getItem(0) as JRadioButtonMenuItem }
-        val item1 by lazy { window!!.jMenuBar.getMenu(0).getItem(1) as JRadioButtonMenuItem }
-
-        awaitIdle()
-        assertThat(item0.isSelected).isEqualTo(false)
-        assertThat(item1.isSelected).isEqualTo(true)
-
-        selected = 0
-        awaitIdle()
-        assertThat(item0.isSelected).isEqualTo(true)
-        assertThat(item1.isSelected).isEqualTo(false)
-
-        item1.doClick()
-        awaitIdle()
-        assertThat(selected).isEqualTo(0)
-        assertThat(item0.isSelected).isEqualTo(true)
-        assertThat(item1.isSelected).isEqualTo(false)
-
-        exitApplication()
-    }
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/window/TestUtils.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/window/TestUtils.kt
deleted file mode 100644
index f4316c4..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/window/TestUtils.kt
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.window
-
-import androidx.compose.runtime.Recomposer
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.setValue
-import androidx.compose.runtime.snapshots.Snapshot
-import java.awt.GraphicsEnvironment
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.flow.collect
-import kotlinx.coroutines.flow.takeWhile
-import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.swing.Swing
-import kotlinx.coroutines.withTimeout
-import kotlinx.coroutines.yield
-import org.junit.Assume.assumeFalse
-import org.junit.Assume.assumeTrue
-
-@OptIn(ExperimentalCoroutinesApi::class)
-internal fun runApplicationTest(
-    /**
-     * Use delay(500) additionally to `yield` in `await*` functions
-     *
-     * Set this property only if you sure that you can't easily make the test deterministic
-     * (non-flaky).
-     *
-     * We have to use `useDelay` in some Linux Tests, because Linux can behave in non-deterministic
-     * way when we change position/size very fast (see the snippet below)
-     */
-    useDelay: Boolean = false,
-    body: suspend WindowTestScope.() -> Unit
-) {
-    // b/271123970 These tests are flaky or fail.
-    // We reconsider enable them after upstreaming desktop changes
-    val composeForDesktopUpstreamed = false
-    assumeTrue(composeForDesktopUpstreamed)
-    assumeFalse(GraphicsEnvironment.getLocalGraphicsEnvironment().isHeadlessInstance)
-
-    runBlocking(Dispatchers.Swing) {
-        withTimeout(30000) {
-            val testScope = WindowTestScope(this, useDelay)
-            if (testScope.isOpen) {
-                testScope.body()
-            }
-        }
-    }
-}
-
-/* Snippet that demonstrated the issue with window state listening on Linux
-
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.swing.Swing
-import kotlinx.coroutines.yield
-import java.awt.Point
-import java.awt.event.ComponentAdapter
-import java.awt.event.ComponentEvent
-import javax.swing.JFrame
-
-fun main()  {
-    runBlocking(Dispatchers.Swing) {
-        repeat(10) {
-            val actions = mutableListOf<String>()
-            val frame = JFrame()
-            frame.addComponentListener(object : ComponentAdapter() {
-                override fun componentMoved(e: ComponentEvent?) {
-                    actions.add(frame.x.toString())
-                }
-            })
-            frame.location = Point(200, 200)
-            frame.isVisible = true
-            yield()
-//                delay(200)
-            actions.add("set300")
-            frame.location = Point(300, 300)
-            delay(200)
-            /**
-             * output is [200, set300, 300, 200, 300] on Linux
-             * (see 200, 300 at the end, they are unexpected events that make impossible to write
-             * robust tests without delays)
-             */
-            println(actions)
-            frame.dispose()
-        }
-    }
-}
-*/
-
-internal class WindowTestScope(private val scope: CoroutineScope, private val useDelay: Boolean) :
-    CoroutineScope by CoroutineScope(scope.coroutineContext + Job()) {
-    var isOpen by mutableStateOf(true)
-    private val initialRecomposers = Recomposer.runningRecomposers.value
-
-    fun exitApplication() {
-        isOpen = false
-    }
-
-    suspend fun awaitIdle() {
-        if (useDelay) {
-            delay(500)
-        }
-        // TODO(demin): It seems this not-so-good synchronization
-        //  doesn't cause flakiness in our window tests.
-        //  But more robust solution will be to use something like
-        //  TestCoroutineDispatcher/FlushCoroutineDispatcher (but we can't use it in a pure form,
-        //  because there are Swing/system events that we don't control).
-        // Most of the work usually is done after the first yield(), almost all of the work -
-        // after fourth yield()
-        repeat(100) { yield() }
-
-        Snapshot.sendApplyNotifications()
-        for (recomposerInfo in Recomposer.runningRecomposers.value - initialRecomposers) {
-            recomposerInfo.state.takeWhile { it > Recomposer.State.Idle }.collect()
-        }
-    }
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/window/dialog/DialogTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/window/dialog/DialogTest.kt
deleted file mode 100644
index 8a64acb..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/window/dialog/DialogTest.kt
+++ /dev/null
@@ -1,551 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.window.dialog
-
-import androidx.compose.foundation.Canvas
-import androidx.compose.foundation.background
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.size
-import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.runtime.DisposableEffect
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.compositionLocalOf
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.awt.ComposeDialog
-import androidx.compose.ui.focus.FocusRequester
-import androidx.compose.ui.focus.focusRequester
-import androidx.compose.ui.focus.focusTarget
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.input.key.Key
-import androidx.compose.ui.input.key.key
-import androidx.compose.ui.input.key.onKeyEvent
-import androidx.compose.ui.input.key.onPreviewKeyEvent
-import androidx.compose.ui.sendKeyEvent
-import androidx.compose.ui.unit.DpSize
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.window.DialogWindow
-import androidx.compose.ui.window.launchApplication
-import androidx.compose.ui.window.rememberDialogState
-import androidx.compose.ui.window.runApplicationTest
-import com.google.common.truth.Truth.assertThat
-import java.awt.Dimension
-import java.awt.event.KeyEvent
-import java.awt.event.WindowAdapter
-import java.awt.event.WindowEvent
-import org.junit.Test
-
-class DialogTest {
-    @Test
-    fun `open and close custom dialog`() = runApplicationTest {
-        var window: ComposeDialog? = null
-
-        launchApplication {
-            var isOpen by remember { mutableStateOf(true) }
-
-            fun createWindow() =
-                ComposeDialog().apply {
-                    size = Dimension(300, 200)
-
-                    addWindowListener(
-                        object : WindowAdapter() {
-                            override fun windowClosing(e: WindowEvent) {
-                                isOpen = false
-                            }
-                        }
-                    )
-                }
-
-            if (isOpen) {
-                DialogWindow(create = ::createWindow, dispose = ComposeDialog::dispose) {
-                    window = this.window
-                    Box(Modifier.size(32.dp).background(Color.Red))
-                }
-            }
-        }
-
-        awaitIdle()
-        assertThat(window?.isShowing).isTrue()
-
-        window?.dispatchEvent(WindowEvent(window, WindowEvent.WINDOW_CLOSING))
-    }
-
-    @Test
-    fun `update custom dialog`() = runApplicationTest {
-        var window: ComposeDialog? = null
-
-        var isOpen by mutableStateOf(true)
-        var title by mutableStateOf("Title1")
-
-        launchApplication {
-            fun createWindow() =
-                ComposeDialog().apply {
-                    size = Dimension(300, 200)
-
-                    addWindowListener(
-                        object : WindowAdapter() {
-                            override fun windowClosing(e: WindowEvent) {
-                                isOpen = false
-                            }
-                        }
-                    )
-                }
-
-            if (isOpen) {
-                DialogWindow(
-                    create = ::createWindow,
-                    dispose = ComposeDialog::dispose,
-                    update = { it.title = title }
-                ) {
-                    window = this.window
-                    Box(Modifier.size(32.dp).background(Color.Red))
-                }
-            }
-        }
-
-        awaitIdle()
-        assertThat(window?.isShowing).isTrue()
-        assertThat(window?.title).isEqualTo(title)
-
-        title = "Title2"
-        awaitIdle()
-        assertThat(window?.title).isEqualTo(title)
-
-        isOpen = false
-    }
-
-    @Test
-    fun `open and close dialog`() = runApplicationTest {
-        var window: ComposeDialog? = null
-
-        launchApplication {
-            DialogWindow(onCloseRequest = ::exitApplication) {
-                window = this.window
-                Box(Modifier.size(32.dp).background(Color.Red))
-            }
-        }
-
-        awaitIdle()
-        assertThat(window?.isShowing).isTrue()
-
-        window?.dispatchEvent(WindowEvent(window, WindowEvent.WINDOW_CLOSING))
-    }
-
-    @Test
-    fun `disable closing dialog`() = runApplicationTest {
-        var isOpen by mutableStateOf(true)
-        var isCloseCalled by mutableStateOf(false)
-        var window: ComposeDialog? = null
-
-        launchApplication {
-            if (isOpen) {
-                DialogWindow(onCloseRequest = { isCloseCalled = true }) {
-                    window = this.window
-                    Box(Modifier.size(32.dp).background(Color.Red))
-                }
-            }
-        }
-
-        awaitIdle()
-
-        window?.dispatchEvent(WindowEvent(window, WindowEvent.WINDOW_CLOSING))
-        awaitIdle()
-        assertThat(isCloseCalled).isTrue()
-        assertThat(window?.isShowing).isTrue()
-
-        isOpen = false
-        awaitIdle()
-        assertThat(window?.isShowing).isFalse()
-    }
-
-    @Test
-    fun `show splash screen`() = runApplicationTest {
-        var window1: ComposeDialog? = null
-        var window2: ComposeDialog? = null
-
-        var isOpen by mutableStateOf(true)
-        var isLoading by mutableStateOf(true)
-
-        launchApplication {
-            if (isOpen) {
-                if (isLoading) {
-                    DialogWindow(onCloseRequest = {}) {
-                        window1 = this.window
-                        Box(Modifier.size(32.dp).background(Color.Red))
-                    }
-                } else {
-                    DialogWindow(onCloseRequest = {}) {
-                        window2 = this.window
-                        Box(Modifier.size(32.dp).background(Color.Blue))
-                    }
-                }
-            }
-        }
-
-        awaitIdle()
-        assertThat(window1?.isShowing).isTrue()
-        assertThat(window2).isNull()
-
-        isLoading = false
-        awaitIdle()
-        assertThat(window1?.isShowing).isFalse()
-        assertThat(window2?.isShowing).isTrue()
-
-        isOpen = false
-        awaitIdle()
-        assertThat(window1?.isShowing).isFalse()
-        assertThat(window2?.isShowing).isFalse()
-    }
-
-    @Test
-    fun `open two dialogs`() = runApplicationTest {
-        var window1: ComposeDialog? = null
-        var window2: ComposeDialog? = null
-
-        var isOpen by mutableStateOf(true)
-
-        launchApplication {
-            if (isOpen) {
-                DialogWindow(onCloseRequest = {}) {
-                    window1 = this.window
-                    Box(Modifier.size(32.dp).background(Color.Red))
-                }
-
-                DialogWindow(onCloseRequest = {}) {
-                    window2 = this.window
-                    Box(Modifier.size(32.dp).background(Color.Blue))
-                }
-            }
-        }
-
-        awaitIdle()
-        assertThat(window1?.isShowing).isTrue()
-        assertThat(window2?.isShowing).isTrue()
-
-        isOpen = false
-        awaitIdle()
-        assertThat(window1?.isShowing).isFalse()
-        assertThat(window2?.isShowing).isFalse()
-    }
-
-    @Test
-    fun `open nested dialog`() = runApplicationTest {
-        var window1: ComposeDialog? = null
-        var window2: ComposeDialog? = null
-
-        var isOpen by mutableStateOf(true)
-        var isNestedOpen by mutableStateOf(true)
-
-        launchApplication {
-            if (isOpen) {
-                DialogWindow(
-                    onCloseRequest = {},
-                    state =
-                        rememberDialogState(
-                            size = DpSize(600.dp, 600.dp),
-                        )
-                ) {
-                    window1 = this.window
-                    Box(Modifier.size(32.dp).background(Color.Red))
-
-                    if (isNestedOpen) {
-                        DialogWindow(
-                            onCloseRequest = {},
-                            state =
-                                rememberDialogState(
-                                    size = DpSize(300.dp, 300.dp),
-                                )
-                        ) {
-                            window2 = this.window
-                            Box(Modifier.size(32.dp).background(Color.Blue))
-                        }
-                    }
-                }
-            }
-        }
-
-        awaitIdle()
-        assertThat(window1?.isShowing).isTrue()
-        assertThat(window2?.isShowing).isTrue()
-
-        isNestedOpen = false
-        awaitIdle()
-        assertThat(window1?.isShowing).isTrue()
-        assertThat(window2?.isShowing).isFalse()
-
-        isNestedOpen = true
-        awaitIdle()
-        assertThat(window1?.isShowing).isTrue()
-        assertThat(window2?.isShowing).isTrue()
-
-        isOpen = false
-        awaitIdle()
-        assertThat(window1?.isShowing).isFalse()
-        assertThat(window2?.isShowing).isFalse()
-    }
-
-    @Test
-    fun `pass composition local to dialogs`() = runApplicationTest {
-        var actualValue1: Int? = null
-        var actualValue2: Int? = null
-
-        var isOpen by mutableStateOf(true)
-        var testValue by mutableStateOf(0)
-        val localTestValue = compositionLocalOf { testValue }
-
-        launchApplication {
-            if (isOpen) {
-                CompositionLocalProvider(localTestValue provides testValue) {
-                    DialogWindow(
-                        onCloseRequest = {},
-                        state =
-                            rememberDialogState(
-                                size = DpSize(600.dp, 600.dp),
-                            )
-                    ) {
-                        actualValue1 = localTestValue.current
-                        Box(Modifier.size(32.dp).background(Color.Red))
-
-                        DialogWindow(
-                            onCloseRequest = {},
-                            state =
-                                rememberDialogState(
-                                    size = DpSize(300.dp, 300.dp),
-                                )
-                        ) {
-                            actualValue2 = localTestValue.current
-                            Box(Modifier.size(32.dp).background(Color.Blue))
-                        }
-                    }
-                }
-            }
-        }
-
-        awaitIdle()
-        assertThat(actualValue1).isEqualTo(0)
-        assertThat(actualValue2).isEqualTo(0)
-
-        testValue = 42
-        awaitIdle()
-        assertThat(actualValue1).isEqualTo(42)
-        assertThat(actualValue2).isEqualTo(42)
-
-        isOpen = false
-    }
-
-    @Test
-    fun `DisposableEffect call order`() = runApplicationTest {
-        var initCount = 0
-        var disposeCount = 0
-
-        var isOpen by mutableStateOf(true)
-
-        launchApplication {
-            if (isOpen) {
-                DialogWindow(onCloseRequest = {}) {
-                    DisposableEffect(Unit) {
-                        initCount++
-                        onDispose { disposeCount++ }
-                    }
-                }
-            }
-        }
-
-        awaitIdle()
-        assertThat(initCount).isEqualTo(1)
-        assertThat(disposeCount).isEqualTo(0)
-
-        isOpen = false
-        awaitIdle()
-        assertThat(initCount).isEqualTo(1)
-        assertThat(disposeCount).isEqualTo(1)
-    }
-
-    @Test
-    fun `catch key handlers`() = runApplicationTest {
-        var window: ComposeDialog? = null
-        val onKeyEventKeys = mutableSetOf<Key>()
-        val onPreviewKeyEventKeys = mutableSetOf<Key>()
-
-        fun clear() {
-            onKeyEventKeys.clear()
-            onPreviewKeyEventKeys.clear()
-        }
-
-        launchApplication {
-            DialogWindow(
-                onCloseRequest = ::exitApplication,
-                onPreviewKeyEvent = {
-                    onPreviewKeyEventKeys.add(it.key)
-                    it.key == Key.Q
-                },
-                onKeyEvent = {
-                    onKeyEventKeys.add(it.key)
-                    it.key == Key.W
-                }
-            ) {
-                window = this.window
-            }
-        }
-
-        awaitIdle()
-
-        window?.sendKeyEvent(KeyEvent.VK_Q)
-        awaitIdle()
-        assertThat(onPreviewKeyEventKeys).isEqualTo(setOf(Key.Q))
-        assertThat(onKeyEventKeys).isEqualTo(emptySet<Key>())
-
-        clear()
-        window?.sendKeyEvent(KeyEvent.VK_W)
-        awaitIdle()
-        assertThat(onPreviewKeyEventKeys).isEqualTo(setOf(Key.W))
-        assertThat(onKeyEventKeys).isEqualTo(setOf(Key.W))
-
-        clear()
-        window?.sendKeyEvent(KeyEvent.VK_E)
-        awaitIdle()
-        assertThat(onPreviewKeyEventKeys).isEqualTo(setOf(Key.E))
-        assertThat(onKeyEventKeys).isEqualTo(setOf(Key.E))
-
-        exitApplication()
-    }
-
-    @Test
-    fun `catch key handlers with focused node`() = runApplicationTest {
-        var window: ComposeDialog? = null
-        val onWindowKeyEventKeys = mutableSetOf<Key>()
-        val onWindowPreviewKeyEventKeys = mutableSetOf<Key>()
-        val onNodeKeyEventKeys = mutableSetOf<Key>()
-        val onNodePreviewKeyEventKeys = mutableSetOf<Key>()
-
-        fun clear() {
-            onWindowKeyEventKeys.clear()
-            onWindowPreviewKeyEventKeys.clear()
-            onNodeKeyEventKeys.clear()
-            onNodePreviewKeyEventKeys.clear()
-        }
-
-        launchApplication {
-            DialogWindow(
-                onCloseRequest = ::exitApplication,
-                onPreviewKeyEvent = {
-                    onWindowPreviewKeyEventKeys.add(it.key)
-                    it.key == Key.Q
-                },
-                onKeyEvent = {
-                    onWindowKeyEventKeys.add(it.key)
-                    it.key == Key.W
-                },
-            ) {
-                window = this.window
-
-                val focusRequester = remember(::FocusRequester)
-                LaunchedEffect(Unit) { focusRequester.requestFocus() }
-
-                Box(
-                    Modifier.focusRequester(focusRequester)
-                        .focusTarget()
-                        .onPreviewKeyEvent {
-                            onNodePreviewKeyEventKeys.add(it.key)
-                            it.key == Key.E
-                        }
-                        .onKeyEvent {
-                            onNodeKeyEventKeys.add(it.key)
-                            it.key == Key.R
-                        }
-                )
-            }
-        }
-
-        awaitIdle()
-
-        window?.sendKeyEvent(KeyEvent.VK_Q)
-        awaitIdle()
-        assertThat(onWindowPreviewKeyEventKeys).isEqualTo(setOf(Key.Q))
-        assertThat(onNodePreviewKeyEventKeys).isEqualTo(emptySet<Key>())
-        assertThat(onNodeKeyEventKeys).isEqualTo(emptySet<Key>())
-        assertThat(onWindowKeyEventKeys).isEqualTo(emptySet<Key>())
-
-        clear()
-        window?.sendKeyEvent(KeyEvent.VK_W)
-        awaitIdle()
-        assertThat(onWindowPreviewKeyEventKeys).isEqualTo(setOf(Key.W))
-        assertThat(onNodePreviewKeyEventKeys).isEqualTo(setOf(Key.W))
-        assertThat(onNodeKeyEventKeys).isEqualTo(setOf(Key.W))
-        assertThat(onWindowKeyEventKeys).isEqualTo(setOf(Key.W))
-
-        clear()
-        window?.sendKeyEvent(KeyEvent.VK_E)
-        awaitIdle()
-        assertThat(onWindowPreviewKeyEventKeys).isEqualTo(setOf(Key.E))
-        assertThat(onNodePreviewKeyEventKeys).isEqualTo(setOf(Key.E))
-        assertThat(onNodeKeyEventKeys).isEqualTo(emptySet<Key>())
-        assertThat(onWindowKeyEventKeys).isEqualTo(emptySet<Key>())
-
-        clear()
-        window?.sendKeyEvent(KeyEvent.VK_R)
-        awaitIdle()
-        assertThat(onWindowPreviewKeyEventKeys).isEqualTo(setOf(Key.R))
-        assertThat(onNodePreviewKeyEventKeys).isEqualTo(setOf(Key.R))
-        assertThat(onNodeKeyEventKeys).isEqualTo(setOf(Key.R))
-        assertThat(onWindowKeyEventKeys).isEqualTo(emptySet<Key>())
-
-        clear()
-        window?.sendKeyEvent(KeyEvent.VK_T)
-        awaitIdle()
-        assertThat(onWindowPreviewKeyEventKeys).isEqualTo(setOf(Key.T))
-        assertThat(onNodePreviewKeyEventKeys).isEqualTo(setOf(Key.T))
-        assertThat(onNodeKeyEventKeys).isEqualTo(setOf(Key.T))
-        assertThat(onWindowKeyEventKeys).isEqualTo(setOf(Key.T))
-
-        exitApplication()
-    }
-
-    @Test(timeout = 30000)
-    fun `should draw before dialog is visible`() = runApplicationTest {
-        var isComposed = false
-        var isDrawn = false
-        var isVisibleOnFirstComposition = false
-        var isVisibleOnFirstDraw = false
-
-        launchApplication {
-            DialogWindow(onCloseRequest = ::exitApplication) {
-                if (!isComposed) {
-                    isVisibleOnFirstComposition = window.isVisible
-                    isComposed = true
-                }
-
-                Canvas(Modifier.fillMaxSize()) {
-                    if (!isDrawn) {
-                        isVisibleOnFirstDraw = window.isVisible
-                        isDrawn = true
-                    }
-                }
-            }
-        }
-
-        awaitIdle()
-        assertThat(isVisibleOnFirstComposition).isFalse()
-        assertThat(isVisibleOnFirstDraw).isFalse()
-
-        exitApplication()
-    }
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/window/window/WindowInputEventTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/window/window/WindowInputEventTest.kt
deleted file mode 100644
index ed79346..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/window/window/WindowInputEventTest.kt
+++ /dev/null
@@ -1,596 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-@file:Suppress("DEPRECATION") // https://github.com/JetBrains/compose-jb/issues/1514
-
-package androidx.compose.ui.window.window
-
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.remember
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.awt.ComposeWindow
-import androidx.compose.ui.focus.FocusRequester
-import androidx.compose.ui.focus.focusRequester
-import androidx.compose.ui.focus.focusTarget
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.input.key.Key
-import androidx.compose.ui.input.key.key
-import androidx.compose.ui.input.key.onKeyEvent
-import androidx.compose.ui.input.key.onPreviewKeyEvent
-import androidx.compose.ui.input.pointer.AwaitPointerEventScope
-import androidx.compose.ui.input.pointer.PointerButtons
-import androidx.compose.ui.input.pointer.PointerEvent
-import androidx.compose.ui.input.pointer.PointerEventType
-import androidx.compose.ui.input.pointer.PointerKeyboardModifiers
-import androidx.compose.ui.input.pointer.pointerInput
-import androidx.compose.ui.sendKeyEvent
-import androidx.compose.ui.sendMouseEvent
-import androidx.compose.ui.sendMouseWheelEvent
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.window.Window
-import androidx.compose.ui.window.density
-import androidx.compose.ui.window.launchApplication
-import androidx.compose.ui.window.rememberWindowState
-import androidx.compose.ui.window.runApplicationTest
-import com.google.common.truth.Truth.assertThat
-import java.awt.Toolkit
-import java.awt.event.KeyEvent
-import java.awt.event.MouseEvent
-import java.awt.event.MouseWheelEvent
-import org.junit.Test
-
-class WindowInputEventTest {
-    @Test
-    fun `catch key handlers`() = runApplicationTest {
-        var window: ComposeWindow? = null
-        val onKeyEventKeys = mutableSetOf<Key>()
-        val onPreviewKeyEventKeys = mutableSetOf<Key>()
-
-        fun clear() {
-            onKeyEventKeys.clear()
-            onPreviewKeyEventKeys.clear()
-        }
-
-        launchApplication {
-            Window(
-                onCloseRequest = ::exitApplication,
-                onPreviewKeyEvent = {
-                    onPreviewKeyEventKeys.add(it.key)
-                    it.key == Key.Q
-                },
-                onKeyEvent = {
-                    onKeyEventKeys.add(it.key)
-                    it.key == Key.W
-                }
-            ) {
-                window = this.window
-            }
-        }
-
-        awaitIdle()
-
-        window?.sendKeyEvent(KeyEvent.VK_Q)
-        awaitIdle()
-        assertThat(onPreviewKeyEventKeys).isEqualTo(setOf(Key.Q))
-        assertThat(onKeyEventKeys).isEqualTo(emptySet<Key>())
-
-        clear()
-        window?.sendKeyEvent(KeyEvent.VK_W)
-        awaitIdle()
-        assertThat(onPreviewKeyEventKeys).isEqualTo(setOf(Key.W))
-        assertThat(onKeyEventKeys).isEqualTo(setOf(Key.W))
-
-        clear()
-        window?.sendKeyEvent(KeyEvent.VK_E)
-        awaitIdle()
-        assertThat(onPreviewKeyEventKeys).isEqualTo(setOf(Key.E))
-        assertThat(onKeyEventKeys).isEqualTo(setOf(Key.E))
-
-        exitApplication()
-    }
-
-    @Test
-    fun `catch key handlers with focused node`() = runApplicationTest {
-        var window: ComposeWindow? = null
-        val onWindowKeyEventKeys = mutableSetOf<Key>()
-        val onWindowPreviewKeyEventKeys = mutableSetOf<Key>()
-        val onNodeKeyEventKeys = mutableSetOf<Key>()
-        val onNodePreviewKeyEventKeys = mutableSetOf<Key>()
-
-        fun clear() {
-            onWindowKeyEventKeys.clear()
-            onWindowPreviewKeyEventKeys.clear()
-            onNodeKeyEventKeys.clear()
-            onNodePreviewKeyEventKeys.clear()
-        }
-
-        launchApplication {
-            Window(
-                onCloseRequest = ::exitApplication,
-                onPreviewKeyEvent = {
-                    onWindowPreviewKeyEventKeys.add(it.key)
-                    it.key == Key.Q
-                },
-                onKeyEvent = {
-                    onWindowKeyEventKeys.add(it.key)
-                    it.key == Key.W
-                },
-            ) {
-                window = this.window
-
-                val focusRequester = remember(::FocusRequester)
-                LaunchedEffect(Unit) { focusRequester.requestFocus() }
-
-                Box(
-                    Modifier.focusRequester(focusRequester)
-                        .focusTarget()
-                        .onPreviewKeyEvent {
-                            onNodePreviewKeyEventKeys.add(it.key)
-                            it.key == Key.E
-                        }
-                        .onKeyEvent {
-                            onNodeKeyEventKeys.add(it.key)
-                            it.key == Key.R
-                        }
-                )
-            }
-        }
-
-        awaitIdle()
-
-        window?.sendKeyEvent(KeyEvent.VK_Q)
-        awaitIdle()
-        assertThat(onWindowPreviewKeyEventKeys).isEqualTo(setOf(Key.Q))
-        assertThat(onNodePreviewKeyEventKeys).isEqualTo(emptySet<Key>())
-        assertThat(onNodeKeyEventKeys).isEqualTo(emptySet<Key>())
-        assertThat(onWindowKeyEventKeys).isEqualTo(emptySet<Key>())
-
-        clear()
-        window?.sendKeyEvent(KeyEvent.VK_W)
-        awaitIdle()
-        assertThat(onWindowPreviewKeyEventKeys).isEqualTo(setOf(Key.W))
-        assertThat(onNodePreviewKeyEventKeys).isEqualTo(setOf(Key.W))
-        assertThat(onNodeKeyEventKeys).isEqualTo(setOf(Key.W))
-        assertThat(onWindowKeyEventKeys).isEqualTo(setOf(Key.W))
-
-        clear()
-        window?.sendKeyEvent(KeyEvent.VK_E)
-        awaitIdle()
-        assertThat(onWindowPreviewKeyEventKeys).isEqualTo(setOf(Key.E))
-        assertThat(onNodePreviewKeyEventKeys).isEqualTo(setOf(Key.E))
-        assertThat(onNodeKeyEventKeys).isEqualTo(emptySet<Key>())
-        assertThat(onWindowKeyEventKeys).isEqualTo(emptySet<Key>())
-
-        clear()
-        window?.sendKeyEvent(KeyEvent.VK_R)
-        awaitIdle()
-        assertThat(onWindowPreviewKeyEventKeys).isEqualTo(setOf(Key.R))
-        assertThat(onNodePreviewKeyEventKeys).isEqualTo(setOf(Key.R))
-        assertThat(onNodeKeyEventKeys).isEqualTo(setOf(Key.R))
-        assertThat(onWindowKeyEventKeys).isEqualTo(emptySet<Key>())
-
-        clear()
-        window?.sendKeyEvent(KeyEvent.VK_T)
-        awaitIdle()
-        assertThat(onWindowPreviewKeyEventKeys).isEqualTo(setOf(Key.T))
-        assertThat(onNodePreviewKeyEventKeys).isEqualTo(setOf(Key.T))
-        assertThat(onNodeKeyEventKeys).isEqualTo(setOf(Key.T))
-        assertThat(onWindowKeyEventKeys).isEqualTo(setOf(Key.T))
-
-        exitApplication()
-    }
-
-    @Test
-    fun `catch mouse press + move + release`() = runApplicationTest {
-        lateinit var window: ComposeWindow
-
-        val events = mutableListOf<PointerEvent>()
-
-        launchApplication {
-            Window(
-                onCloseRequest = ::exitApplication,
-                state = rememberWindowState(width = 200.dp, height = 100.dp)
-            ) {
-                window = this.window
-
-                Box(
-                    Modifier.fillMaxSize().pointerInput(events) {
-                        while (true) {
-                            awaitPointerEventScope { events += awaitPointerEvent() }
-                        }
-                    }
-                )
-            }
-        }
-        val density by lazy { window.density.density }
-
-        awaitIdle()
-        assertThat(events.size).isEqualTo(0)
-
-        window.sendMouseEvent(MouseEvent.MOUSE_PRESSED, x = 100, y = 50)
-        awaitIdle()
-        assertThat(events.size).isEqualTo(1)
-        assertThat(events.last().pressed).isEqualTo(true)
-        assertThat(events.last().position).isEqualTo(Offset(100 * density, 50 * density))
-
-        window.sendMouseEvent(MouseEvent.MOUSE_DRAGGED, x = 90, y = 40)
-        awaitIdle()
-        assertThat(events.size).isEqualTo(2)
-        assertThat(events.last().pressed).isEqualTo(true)
-        assertThat(events.last().position).isEqualTo(Offset(90 * density, 40 * density))
-
-        window.sendMouseEvent(MouseEvent.MOUSE_RELEASED, x = 80, y = 30)
-        awaitIdle()
-        assertThat(events.size).isEqualTo(3)
-        assertThat(events.last().pressed).isEqualTo(false)
-        assertThat(events.last().position).isEqualTo(Offset(80 * density, 30 * density))
-
-        exitApplication()
-    }
-
-    @Test
-    fun `catch mouse move`() = runApplicationTest {
-        lateinit var window: ComposeWindow
-
-        val onMoves = mutableListOf<Offset>()
-        var onEnters = 0
-        var onExits = 0
-
-        launchApplication {
-            Window(
-                onCloseRequest = ::exitApplication,
-                state = rememberWindowState(width = 200.dp, height = 100.dp)
-            ) {
-                window = this.window
-
-                Box(
-                    Modifier.fillMaxSize()
-                        .onPointerEvent(PointerEventType.Move) {
-                            onMoves.add(it.changes.first().position)
-                        }
-                        .onPointerEvent(PointerEventType.Enter) { onEnters++ }
-                        .onPointerEvent(PointerEventType.Exit) { onExits++ }
-                )
-            }
-        }
-        val density by lazy { window.density.density }
-
-        awaitIdle()
-        assertThat(onMoves.size).isEqualTo(0)
-        assertThat(onEnters).isEqualTo(0)
-        assertThat(onExits).isEqualTo(0)
-
-        window.sendMouseEvent(MouseEvent.MOUSE_ENTERED, x = 100, y = 50)
-        awaitIdle()
-        assertThat(onMoves.size).isEqualTo(0)
-        assertThat(onEnters).isEqualTo(1)
-        assertThat(onExits).isEqualTo(0)
-
-        window.sendMouseEvent(MouseEvent.MOUSE_MOVED, x = 90, y = 50)
-        awaitIdle()
-        assertThat(onMoves.size).isEqualTo(1)
-        assertThat(onMoves.last()).isEqualTo(Offset(90 * density, 50 * density))
-        assertThat(onEnters).isEqualTo(1)
-        assertThat(onExits).isEqualTo(0)
-
-        window.sendMouseEvent(MouseEvent.MOUSE_PRESSED, x = 90, y = 50)
-        window.sendMouseEvent(MouseEvent.MOUSE_DRAGGED, x = 80, y = 50)
-        window.sendMouseEvent(MouseEvent.MOUSE_RELEASED, x = 80, y = 50)
-        awaitIdle()
-        assertThat(onMoves.size).isEqualTo(2)
-        assertThat(onMoves.last()).isEqualTo(Offset(80 * density, 50 * density))
-        assertThat(onEnters).isEqualTo(1)
-        assertThat(onExits).isEqualTo(0)
-
-        // TODO(https://github.com/JetBrains/compose-jb/issues/1176) fix catching exit event
-        //        window.sendMouseEvent(MouseEvent.MOUSE_EXITED, x = 900, y = 500)
-        //        awaitIdle()
-        //        assertThat(onMoves.size).isEqualTo(2)
-        //        assertThat(onEnters).isEqualTo(1)
-        //        assertThat(onExits).isEqualTo(1)
-
-        exitApplication()
-    }
-
-    @Test
-    fun `catch mouse scroll`() = runApplicationTest {
-        lateinit var window: ComposeWindow
-
-        val deltas = mutableListOf<Offset>()
-
-        launchApplication {
-            Window(
-                onCloseRequest = ::exitApplication,
-                state = rememberWindowState(width = 200.dp, height = 100.dp)
-            ) {
-                window = this.window
-
-                Box(
-                    Modifier.fillMaxSize().onPointerEvent(PointerEventType.Scroll) {
-                        deltas.add(it.changes.first().scrollDelta)
-                    }
-                )
-            }
-        }
-
-        awaitIdle()
-        assertThat(deltas.size).isEqualTo(0)
-
-        window.sendMouseWheelEvent(
-            MouseEvent.MOUSE_WHEEL,
-            x = 100,
-            y = 50,
-            scrollType = MouseWheelEvent.WHEEL_UNIT_SCROLL,
-            wheelRotation = 1
-        )
-        awaitIdle()
-        assertThat(deltas.size).isEqualTo(1)
-        assertThat(deltas.last()).isEqualTo(Offset(0f, 1f))
-
-        window.sendMouseWheelEvent(
-            MouseEvent.MOUSE_WHEEL,
-            x = 100,
-            y = 50,
-            scrollType = MouseWheelEvent.WHEEL_UNIT_SCROLL,
-            wheelRotation = -1
-        )
-        awaitIdle()
-        assertThat(deltas.size).isEqualTo(2)
-        assertThat(deltas.last()).isEqualTo(Offset(0f, -1f))
-
-        exitApplication()
-    }
-
-    @Test
-    fun `catch multiple scroll events in one frame`() = runApplicationTest {
-        lateinit var window: ComposeWindow
-
-        val deltas = mutableListOf<Offset>()
-
-        launchApplication {
-            Window(
-                onCloseRequest = ::exitApplication,
-                state = rememberWindowState(width = 200.dp, height = 100.dp)
-            ) {
-                window = this.window
-
-                Box(
-                    Modifier.fillMaxSize().onPointerEvent(PointerEventType.Scroll) {
-                        deltas.add(it.changes.first().scrollDelta)
-                    }
-                )
-            }
-        }
-
-        awaitIdle()
-        assertThat(deltas.size).isEqualTo(0)
-
-        val eventCount = 500
-
-        repeat(eventCount) {
-            window.sendMouseWheelEvent(
-                MouseEvent.MOUSE_WHEEL,
-                x = 100,
-                y = 50,
-                scrollType = MouseWheelEvent.WHEEL_UNIT_SCROLL,
-                wheelRotation = 1
-            )
-        }
-        awaitIdle()
-        assertThat(deltas.size).isEqualTo(eventCount)
-        assertThat(deltas.all { it == Offset(0f, 1f) }).isTrue()
-
-        exitApplication()
-    }
-
-    @Test
-    fun `catch only the first scroll event in one frame`() = runApplicationTest {
-        lateinit var window: ComposeWindow
-
-        val deltas = mutableListOf<Offset>()
-
-        launchApplication {
-            Window(
-                onCloseRequest = ::exitApplication,
-                state = rememberWindowState(width = 200.dp, height = 100.dp)
-            ) {
-                window = this.window
-
-                Box(
-                    Modifier.fillMaxSize().onFirstPointerEvent(PointerEventType.Scroll) {
-                        deltas.add(it.changes.first().scrollDelta)
-                    }
-                )
-            }
-        }
-
-        awaitIdle()
-        assertThat(deltas.size).isEqualTo(0)
-
-        val eventCount = 500
-
-        repeat(eventCount) {
-            window.sendMouseWheelEvent(
-                MouseEvent.MOUSE_WHEEL,
-                x = 100,
-                y = 50,
-                scrollType = MouseWheelEvent.WHEEL_UNIT_SCROLL,
-                wheelRotation = 1
-            )
-        }
-        awaitIdle()
-        assertThat(deltas.size).isEqualTo(1)
-        assertThat(deltas.first()).isEqualTo(Offset(0f, 1f))
-
-        exitApplication()
-    }
-
-    @Test(timeout = 5000)
-    fun `receive buttons and modifiers`() = runApplicationTest {
-        lateinit var window: ComposeWindow
-
-        val receivedButtons = mutableListOf<PointerButtons>()
-        val receivedKeyboardModifiers = mutableListOf<PointerKeyboardModifiers>()
-
-        launchApplication {
-            Window(
-                onCloseRequest = ::exitApplication,
-                state = rememberWindowState(width = 200.dp, height = 100.dp)
-            ) {
-                window = this.window
-
-                Box(
-                    Modifier.fillMaxSize()
-                        .onPointerEvent(PointerEventType.Press) {
-                            receivedButtons.add(it.buttons)
-                            receivedKeyboardModifiers.add(it.keyboardModifiers)
-                        }
-                        .onPointerEvent(PointerEventType.Scroll) {
-                            receivedButtons.add(it.buttons)
-                            receivedKeyboardModifiers.add(it.keyboardModifiers)
-                        }
-                )
-            }
-        }
-
-        awaitIdle()
-
-        window.sendMouseEvent(
-            MouseEvent.MOUSE_PRESSED,
-            x = 100,
-            y = 50,
-            modifiers =
-                MouseEvent.SHIFT_DOWN_MASK or
-                    MouseEvent.CTRL_DOWN_MASK or
-                    MouseEvent.BUTTON1_DOWN_MASK or
-                    MouseEvent.BUTTON3_DOWN_MASK
-        )
-
-        awaitIdle()
-        assertThat(receivedButtons.size).isEqualTo(1)
-        assertThat(receivedButtons.last())
-            .isEqualTo(
-                PointerButtons(
-                    isPrimaryPressed = true,
-                    isSecondaryPressed = true,
-                )
-            )
-        assertThat(receivedKeyboardModifiers.size).isEqualTo(1)
-        assertThat(receivedKeyboardModifiers.last())
-            .isEqualTo(
-                PointerKeyboardModifiers(
-                    isCtrlPressed = true,
-                    isShiftPressed = true,
-                    isCapsLockOn = getLockingKeyStateSafe(KeyEvent.VK_CAPS_LOCK),
-                    isScrollLockOn = getLockingKeyStateSafe(KeyEvent.VK_SCROLL_LOCK),
-                    isNumLockOn = getLockingKeyStateSafe(KeyEvent.VK_NUM_LOCK),
-                )
-            )
-
-        window.sendMouseWheelEvent(
-            MouseEvent.MOUSE_WHEEL,
-            x = 100,
-            y = 50,
-            scrollType = MouseWheelEvent.WHEEL_UNIT_SCROLL,
-            wheelRotation = 1,
-            modifiers =
-                MouseEvent.SHIFT_DOWN_MASK or
-                    MouseEvent.CTRL_DOWN_MASK or
-                    MouseEvent.BUTTON1_DOWN_MASK or
-                    MouseEvent.BUTTON3_DOWN_MASK
-        )
-
-        awaitIdle()
-        assertThat(receivedButtons.size).isEqualTo(2)
-        assertThat(receivedButtons.last())
-            .isEqualTo(
-                PointerButtons(
-                    isPrimaryPressed = true,
-                    isSecondaryPressed = true,
-                )
-            )
-        assertThat(receivedKeyboardModifiers.size).isEqualTo(2)
-        assertThat(receivedKeyboardModifiers.last())
-            .isEqualTo(
-                PointerKeyboardModifiers(
-                    isCtrlPressed = true,
-                    isShiftPressed = true,
-                    isCapsLockOn = getLockingKeyStateSafe(KeyEvent.VK_CAPS_LOCK),
-                    isScrollLockOn = getLockingKeyStateSafe(KeyEvent.VK_SCROLL_LOCK),
-                    isNumLockOn = getLockingKeyStateSafe(KeyEvent.VK_NUM_LOCK),
-                )
-            )
-
-        exitApplication()
-    }
-
-    private fun getLockingKeyStateSafe(mask: Int): Boolean =
-        try {
-            Toolkit.getDefaultToolkit().getLockingKeyState(mask)
-        } catch (_: Exception) {
-            false
-        }
-
-    private fun Modifier.onPointerEvent(
-        eventType: PointerEventType,
-        onEvent: AwaitPointerEventScope.(event: PointerEvent) -> Unit
-    ) =
-        pointerInput(eventType, onEvent) {
-            awaitPointerEventScope {
-                while (true) {
-                    val event = awaitPointerEvent()
-                    if (event.type == eventType) {
-                        onEvent(event)
-                    }
-                }
-            }
-        }
-
-    /**
-     * Handle only the first received event and drop all the others that are received in a single
-     * frame
-     */
-    private fun Modifier.onFirstPointerEvent(
-        eventType: PointerEventType,
-        onEvent: AwaitPointerEventScope.(event: PointerEvent) -> Unit
-    ) =
-        pointerInput(eventType, onEvent) {
-            while (true) {
-                awaitPointerEventScope {
-                    val event = awaitEvent(eventType)
-                    onEvent(event)
-                }
-            }
-        }
-
-    private suspend fun AwaitPointerEventScope.awaitEvent(
-        eventType: PointerEventType
-    ): PointerEvent {
-        var event: PointerEvent
-        do {
-            event = awaitPointerEvent()
-        } while (event.type != eventType)
-        return event
-    }
-
-    private val PointerEvent.pressed
-        get() = changes.first().pressed
-
-    private val PointerEvent.position
-        get() = changes.first().position
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/window/window/WindowParameterTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/window/window/WindowParameterTest.kt
deleted file mode 100644
index 7b72c62..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/window/window/WindowParameterTest.kt
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.window.window
-
-import androidx.compose.foundation.background
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.size
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.awt.ComposeWindow
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.painter.Painter
-import androidx.compose.ui.readFirstPixel
-import androidx.compose.ui.testImage
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.window.Window
-import androidx.compose.ui.window.launchApplication
-import androidx.compose.ui.window.runApplicationTest
-import com.google.common.truth.Truth.assertThat
-import java.awt.event.WindowEvent
-import org.junit.Test
-
-class WindowParameterTest {
-    @Test
-    fun `change title`() = runApplicationTest {
-        var window: ComposeWindow? = null
-
-        var title by mutableStateOf("Title1")
-
-        launchApplication {
-            Window(onCloseRequest = ::exitApplication, title = title) {
-                window = this.window
-                Box(Modifier.size(32.dp).background(Color.Red))
-            }
-        }
-
-        awaitIdle()
-        assertThat(window?.title).isEqualTo("Title1")
-
-        title = "Title2"
-        awaitIdle()
-        assertThat(window?.title).isEqualTo("Title2")
-
-        window?.dispatchEvent(WindowEvent(window, WindowEvent.WINDOW_CLOSING))
-    }
-
-    @Test
-    fun `change icon`() = runApplicationTest {
-        var window: ComposeWindow? = null
-
-        val redIcon = testImage(Color.Red)
-        val blueIcon = testImage(Color.Blue)
-
-        var icon: Painter? by mutableStateOf(redIcon)
-
-        launchApplication {
-            Window(onCloseRequest = ::exitApplication, icon = icon) {
-                window = this.window
-                Box(Modifier.size(32.dp).background(Color.Red))
-            }
-        }
-
-        awaitIdle()
-        assertThat(window?.iconImage?.readFirstPixel()).isEqualTo(Color.Red)
-
-        icon = blueIcon
-        awaitIdle()
-        assertThat(window?.iconImage?.readFirstPixel()).isEqualTo(Color.Blue)
-
-        icon = null
-        awaitIdle()
-        assertThat(window?.iconImage?.readFirstPixel()).isEqualTo(null)
-
-        window?.dispatchEvent(WindowEvent(window, WindowEvent.WINDOW_CLOSING))
-    }
-
-    // Swing doesn't support changing isUndecorated
-    @Test
-    fun `set undecorated`() = runApplicationTest {
-        var window: ComposeWindow? = null
-
-        launchApplication {
-            Window(onCloseRequest = ::exitApplication, undecorated = false) {
-                window = this.window
-                Box(Modifier.size(32.dp).background(Color.Red))
-            }
-        }
-
-        awaitIdle()
-        assertThat(window?.isUndecorated).isFalse()
-
-        window?.dispatchEvent(WindowEvent(window, WindowEvent.WINDOW_CLOSING))
-    }
-
-    @Test
-    fun `change undecorated`() = runApplicationTest {
-        var window: ComposeWindow? = null
-
-        var resizable by mutableStateOf(false)
-
-        launchApplication {
-            Window(onCloseRequest = ::exitApplication, resizable = resizable) {
-                window = this.window
-                Box(Modifier.size(32.dp).background(Color.Red))
-            }
-        }
-
-        awaitIdle()
-        assertThat(window?.isResizable).isFalse()
-
-        resizable = true
-        awaitIdle()
-        assertThat(window?.isResizable).isTrue()
-
-        window?.dispatchEvent(WindowEvent(window, WindowEvent.WINDOW_CLOSING))
-    }
-
-    @Test
-    fun `change enabled`() = runApplicationTest {
-        var window: ComposeWindow? = null
-
-        var enabled by mutableStateOf(false)
-
-        launchApplication {
-            Window(onCloseRequest = ::exitApplication, enabled = enabled) {
-                window = this.window
-                Box(Modifier.size(32.dp).background(Color.Red))
-            }
-        }
-
-        awaitIdle()
-        assertThat(window?.isEnabled).isFalse()
-
-        enabled = true
-        awaitIdle()
-        assertThat(window?.isEnabled).isTrue()
-
-        window?.dispatchEvent(WindowEvent(window, WindowEvent.WINDOW_CLOSING))
-    }
-
-    @Test
-    fun `change focusable`() = runApplicationTest {
-        var window: ComposeWindow? = null
-
-        var focusable by mutableStateOf(false)
-
-        launchApplication {
-            Window(onCloseRequest = ::exitApplication, focusable = focusable) {
-                window = this.window
-                Box(Modifier.size(32.dp).background(Color.Red))
-            }
-        }
-
-        awaitIdle()
-        assertThat(window?.isFocusable).isFalse()
-
-        focusable = true
-        awaitIdle()
-        assertThat(window?.isFocusable).isTrue()
-
-        window?.dispatchEvent(WindowEvent(window, WindowEvent.WINDOW_CLOSING))
-    }
-
-    @Test
-    fun `change alwaysOnTop`() = runApplicationTest {
-        var window: ComposeWindow? = null
-
-        var alwaysOnTop by mutableStateOf(false)
-
-        launchApplication {
-            Window(onCloseRequest = ::exitApplication, alwaysOnTop = alwaysOnTop) {
-                window = this.window
-                Box(Modifier.size(32.dp).background(Color.Red))
-            }
-        }
-
-        awaitIdle()
-        assertThat(window?.isAlwaysOnTop).isFalse()
-
-        alwaysOnTop = true
-        awaitIdle()
-        assertThat(window?.isAlwaysOnTop).isTrue()
-
-        window?.dispatchEvent(WindowEvent(window, WindowEvent.WINDOW_CLOSING))
-    }
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/window/window/WindowStateTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/window/window/WindowStateTest.kt
deleted file mode 100644
index c141a9c..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/window/window/WindowStateTest.kt
+++ /dev/null
@@ -1,712 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.window.window
-
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.width
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.saveable.rememberSaveableStateHolder
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.awt.ComposeWindow
-import androidx.compose.ui.isLinux
-import androidx.compose.ui.isWindows
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.DpSize
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.window.Window
-import androidx.compose.ui.window.WindowPlacement
-import androidx.compose.ui.window.WindowPosition
-import androidx.compose.ui.window.WindowState
-import androidx.compose.ui.window.launchApplication
-import androidx.compose.ui.window.rememberWindowState
-import androidx.compose.ui.window.runApplicationTest
-import com.google.common.truth.Truth.assertThat
-import java.awt.Dimension
-import java.awt.Point
-import java.awt.Rectangle
-import java.awt.Window
-import java.awt.event.WindowEvent
-import javax.swing.JFrame
-import kotlin.math.abs
-import kotlin.math.max
-import kotlinx.coroutines.channels.Channel
-import kotlinx.coroutines.channels.consumeEach
-import org.junit.Assume.assumeTrue
-import org.junit.Test
-
-// Note that on Linux some tests are flaky. Swing event listener's on Linux has non-deterministic
-// nature. To avoid flaky'ness we use delays
-// (see description of `delay` parameter in TestUtils.runApplicationTest).
-// It is not a good solution, but it works.
-
-// TODO(demin): figure out how can we fix flaky tests on Linux
-// TODO(demin): fix fullscreen tests on macOs
-
-class WindowStateTest {
-    @Test
-    fun `manually close window`() = runApplicationTest {
-        var window: ComposeWindow? = null
-        var isOpen by mutableStateOf(true)
-
-        launchApplication {
-            if (isOpen) {
-                Window(onCloseRequest = { isOpen = false }) { window = this.window }
-            }
-        }
-
-        awaitIdle()
-        assertThat(window?.isShowing).isTrue()
-
-        window?.dispatchEvent(WindowEvent(window, WindowEvent.WINDOW_CLOSING))
-        awaitIdle()
-        assertThat(window?.isShowing).isFalse()
-    }
-
-    @Test
-    fun `programmatically close window`() = runApplicationTest {
-        var window: ComposeWindow? = null
-        var isOpen by mutableStateOf(true)
-
-        launchApplication {
-            if (isOpen) {
-                Window(onCloseRequest = { isOpen = false }) { window = this.window }
-            }
-        }
-
-        awaitIdle()
-        assertThat(window?.isShowing).isTrue()
-
-        isOpen = false
-        awaitIdle()
-        assertThat(window?.isShowing).isFalse()
-    }
-
-    @Test
-    fun `programmatically open and close nested window`() = runApplicationTest {
-        var parentWindow: ComposeWindow? = null
-        var childWindow: ComposeWindow? = null
-        var isParentOpen by mutableStateOf(true)
-        var isChildOpen by mutableStateOf(false)
-
-        launchApplication {
-            if (isParentOpen) {
-                Window(onCloseRequest = {}) {
-                    parentWindow = this.window
-
-                    if (isChildOpen) {
-                        Window(onCloseRequest = {}) { childWindow = this.window }
-                    }
-                }
-            }
-        }
-
-        awaitIdle()
-        assertThat(parentWindow?.isShowing).isTrue()
-
-        isChildOpen = true
-        awaitIdle()
-        assertThat(parentWindow?.isShowing).isTrue()
-        assertThat(childWindow?.isShowing).isTrue()
-
-        isChildOpen = false
-        awaitIdle()
-        assertThat(parentWindow?.isShowing).isTrue()
-        assertThat(childWindow?.isShowing).isFalse()
-
-        isParentOpen = false
-        awaitIdle()
-        assertThat(parentWindow?.isShowing).isFalse()
-    }
-
-    @Test
-    fun `set size and position before show`() =
-        runApplicationTest(useDelay = isLinux) {
-            val state =
-                WindowState(
-                    size = DpSize(200.dp, 200.dp),
-                    position = WindowPosition(242.dp, 242.dp)
-                )
-
-            var window: ComposeWindow? = null
-
-            launchApplication { Window(onCloseRequest = {}, state) { window = this.window } }
-
-            awaitIdle()
-            assertThat(window?.size).isEqualTo(Dimension(200, 200))
-            assertThat(window?.location).isEqualTo(Point(242, 242))
-
-            exitApplication()
-        }
-
-    @Test
-    fun `change position after show`() =
-        runApplicationTest(useDelay = isLinux) {
-            val state =
-                WindowState(
-                    size = DpSize(200.dp, 200.dp),
-                    position = WindowPosition(200.dp, 200.dp)
-                )
-            var window: ComposeWindow? = null
-
-            launchApplication { Window(onCloseRequest = {}, state) { window = this.window } }
-
-            awaitIdle()
-
-            state.position = WindowPosition(242.dp, (242).dp)
-            awaitIdle()
-            assertThat(window?.location).isEqualTo(Point(242, 242))
-
-            exitApplication()
-        }
-
-    @Test
-    fun `change size after show`() =
-        runApplicationTest(useDelay = isLinux) {
-            val state =
-                WindowState(
-                    size = DpSize(200.dp, 200.dp),
-                    position = WindowPosition(200.dp, 200.dp)
-                )
-            var window: ComposeWindow? = null
-
-            launchApplication { Window(onCloseRequest = {}, state) { window = this.window } }
-
-            awaitIdle()
-
-            state.size = DpSize(250.dp, 200.dp)
-            awaitIdle()
-            assertThat(window?.size).isEqualTo(Dimension(250, 200))
-
-            exitApplication()
-        }
-
-    @Test
-    fun `center window`() = runApplicationTest {
-        fun Rectangle.center() = Point(x + width / 2, y + height / 2)
-        fun JFrame.center() = bounds.center()
-        fun JFrame.screenCenter() = graphicsConfiguration.bounds.center()
-        infix fun Point.maxDistance(other: Point) = max(abs(x - other.x), abs(y - other.y))
-
-        val state =
-            WindowState(size = DpSize(200.dp, 200.dp), position = WindowPosition(Alignment.Center))
-        var window: ComposeWindow? = null
-
-        launchApplication { Window(onCloseRequest = {}, state) { window = this.window } }
-
-        awaitIdle()
-        assertThat(window!!.center() maxDistance window!!.screenCenter() < 250)
-
-        exitApplication()
-    }
-
-    @Test
-    fun `remember position after reattach`() =
-        runApplicationTest(useDelay = isLinux) {
-            val state = WindowState(size = DpSize(200.dp, 200.dp))
-            var window1: ComposeWindow? = null
-            var window2: ComposeWindow? = null
-            var isWindow1 by mutableStateOf(true)
-
-            launchApplication {
-                if (isWindow1) {
-                    Window(onCloseRequest = {}, state) { window1 = this.window }
-                } else {
-                    Window(onCloseRequest = {}, state) { window2 = this.window }
-                }
-            }
-
-            awaitIdle()
-
-            state.position = WindowPosition(242.dp, 242.dp)
-            awaitIdle()
-            assertThat(window1?.location == Point(242, 242))
-
-            isWindow1 = false
-            awaitIdle()
-            assertThat(window2?.location == Point(242, 242))
-
-            exitApplication()
-        }
-
-    @Test
-    fun `state position should be specified after attach`() = runApplicationTest {
-        val state = WindowState(size = DpSize(200.dp, 200.dp))
-
-        launchApplication { Window(onCloseRequest = {}, state) {} }
-
-        assertThat(state.position.isSpecified).isFalse()
-
-        awaitIdle()
-        assertThat(state.position.isSpecified).isTrue()
-
-        exitApplication()
-    }
-
-    @Test
-    fun `enter fullscreen`() =
-        runApplicationTest(useDelay = isLinux) {
-            // TODO(demin): fix macOs. We disabled it because it is not deterministic.
-            //  If we set in skiko SkiaLayer.setFullscreen(true) then isFullscreen still returns
-            // false
-            assumeTrue(isWindows || isLinux)
-
-            val state = WindowState(size = DpSize(200.dp, 200.dp))
-            var window: ComposeWindow? = null
-
-            launchApplication { Window(onCloseRequest = {}, state) { window = this.window } }
-
-            awaitIdle()
-
-            state.placement = WindowPlacement.Fullscreen
-            awaitIdle()
-            assertThat(window?.placement).isEqualTo(WindowPlacement.Fullscreen)
-
-            state.placement = WindowPlacement.Floating
-            awaitIdle()
-            assertThat(window?.placement).isEqualTo(WindowPlacement.Floating)
-
-            exitApplication()
-        }
-
-    @Test
-    fun maximize() =
-        runApplicationTest(useDelay = isLinux) {
-            val state = WindowState(size = DpSize(200.dp, 200.dp))
-            var window: ComposeWindow? = null
-
-            launchApplication { Window(onCloseRequest = {}, state) { window = this.window } }
-
-            awaitIdle()
-
-            state.placement = WindowPlacement.Maximized
-            awaitIdle()
-            assertThat(window?.placement).isEqualTo(WindowPlacement.Maximized)
-
-            state.placement = WindowPlacement.Floating
-            awaitIdle()
-            assertThat(window?.placement).isEqualTo(WindowPlacement.Floating)
-
-            exitApplication()
-        }
-
-    @Test
-    fun minimize() = runApplicationTest {
-        val state = WindowState(size = DpSize(200.dp, 200.dp))
-        var window: ComposeWindow? = null
-
-        launchApplication { Window(onCloseRequest = {}, state) { window = this.window } }
-
-        awaitIdle()
-
-        state.isMinimized = true
-        awaitIdle()
-        assertThat(window?.isMinimized).isTrue()
-
-        state.isMinimized = false
-        awaitIdle()
-        assertThat(window?.isMinimized).isFalse()
-
-        exitApplication()
-    }
-
-    @Test
-    fun `maximize and minimize `() = runApplicationTest {
-        // macOs can't be maximized and minimized at the same time
-        assumeTrue(isWindows || isLinux)
-
-        val state = WindowState(size = DpSize(200.dp, 200.dp))
-        var window: ComposeWindow? = null
-
-        launchApplication { Window(onCloseRequest = {}, state) { window = this.window } }
-
-        awaitIdle()
-
-        state.isMinimized = true
-        state.placement = WindowPlacement.Maximized
-        awaitIdle()
-        assertThat(window?.isMinimized).isTrue()
-        assertThat(window?.placement).isEqualTo(WindowPlacement.Maximized)
-
-        exitApplication()
-    }
-
-    @Test
-    fun `restore size and position after maximize`() = runApplicationTest {
-        // Swing/macOs can't re-change isMaximized in a deterministic way:
-        //        fun main() = runBlocking(Dispatchers.Swing) {
-        //            val window = ComposeWindow()
-        //            window.size = Dimension(200, 200)
-        //            window.isVisible = true
-        //            window.isMaximized = true
-        //            delay(100)
-        //            window.isMaximized = false  // we cannot do that on macOs (window is still
-        // animating)
-        //            delay(1000)
-        //            println(window.isMaximized) // prints true
-        //        }
-        //        Swing/Linux has animations and sometimes adds an offset to the size/position
-        assumeTrue(isWindows)
-
-        val state =
-            WindowState(size = DpSize(201.dp, 203.dp), position = WindowPosition(196.dp, 257.dp))
-        var window: ComposeWindow? = null
-
-        launchApplication { Window(onCloseRequest = {}, state) { window = this.window } }
-
-        awaitIdle()
-        assertThat(window?.size).isEqualTo(Dimension(201, 203))
-        assertThat(window?.location).isEqualTo(Point(196, 257))
-
-        state.placement = WindowPlacement.Maximized
-        awaitIdle()
-        assertThat(window?.placement).isEqualTo(WindowPlacement.Maximized)
-        assertThat(window?.size).isNotEqualTo(Dimension(201, 203))
-        assertThat(window?.location).isNotEqualTo(Point(196, 257))
-
-        state.placement = WindowPlacement.Floating
-        awaitIdle()
-        assertThat(window?.placement).isEqualTo(WindowPlacement.Floating)
-        assertThat(window?.size).isEqualTo(Dimension(201, 203))
-        assertThat(window?.location).isEqualTo(Point(196, 257))
-
-        exitApplication()
-    }
-
-    @Test
-    fun `restore size and position after fullscreen`() = runApplicationTest {
-        //        Swing/Linux has animations and sometimes adds an offset to the size/position
-        assumeTrue(isWindows)
-
-        val state =
-            WindowState(size = DpSize(201.dp, 203.dp), position = WindowPosition(196.dp, 257.dp))
-        var window: ComposeWindow? = null
-
-        launchApplication { Window(onCloseRequest = {}, state) { window = this.window } }
-
-        awaitIdle()
-        assertThat(window?.size).isEqualTo(Dimension(201, 203))
-        assertThat(window?.location).isEqualTo(Point(196, 257))
-
-        state.placement = WindowPlacement.Fullscreen
-        awaitIdle()
-        assertThat(window?.placement).isEqualTo(WindowPlacement.Fullscreen)
-        assertThat(window?.size).isNotEqualTo(Dimension(201, 203))
-        assertThat(window?.location).isNotEqualTo(Point(196, 257))
-
-        state.placement = WindowPlacement.Floating
-        awaitIdle()
-        assertThat(window?.placement).isEqualTo(WindowPlacement.Floating)
-        assertThat(window?.size).isEqualTo(Dimension(201, 203))
-        assertThat(window?.location).isEqualTo(Point(196, 257))
-
-        exitApplication()
-    }
-
-    @Test
-    fun `maximize window before show`() =
-        runApplicationTest(useDelay = isLinux) {
-            val state =
-                WindowState(
-                    size = DpSize(200.dp, 200.dp),
-                    position = WindowPosition(Alignment.Center),
-                    placement = WindowPlacement.Maximized,
-                )
-            var window: ComposeWindow? = null
-
-            launchApplication { Window(onCloseRequest = {}, state) { window = this.window } }
-
-            awaitIdle()
-            assertThat(window?.placement).isEqualTo(WindowPlacement.Maximized)
-
-            exitApplication()
-        }
-
-    @Test
-    fun `minimize window before show`() = runApplicationTest {
-        // Linux/macos doesn't support this:
-        //        fun main() = runBlocking(Dispatchers.Swing) {
-        //            val window = ComposeWindow()
-        //            window.size = Dimension(200, 200)
-        //            window.isMinimized = true
-        //            window.isVisible = true
-        //            delay(2000)
-        //            println(window.isMinimized) // prints false
-        //        }
-        // TODO(demin): can we minimize after window.isVisible?
-        assumeTrue(isWindows)
-
-        val state =
-            WindowState(
-                size = DpSize(200.dp, 200.dp),
-                position = WindowPosition(Alignment.Center),
-                isMinimized = true
-            )
-        var window: ComposeWindow? = null
-
-        launchApplication { Window(onCloseRequest = {}, state) { window = this.window } }
-
-        awaitIdle()
-        assertThat(window?.isMinimized).isTrue()
-
-        exitApplication()
-    }
-
-    @Test
-    fun `enter fullscreen before show`() = runApplicationTest {
-        // TODO(demin): probably we have a bug in skiko (we can't change fullscreen on macOs before
-        //  showing the window)
-        assumeTrue(isLinux || isWindows)
-
-        val state =
-            WindowState(
-                size = DpSize(200.dp, 200.dp),
-                position = WindowPosition(Alignment.Center),
-                placement = WindowPlacement.Fullscreen,
-            )
-        var window: ComposeWindow? = null
-
-        launchApplication { Window(onCloseRequest = {}, state) { window = this.window } }
-
-        awaitIdle()
-        assertThat(window?.placement).isEqualTo(WindowPlacement.Fullscreen)
-
-        exitApplication()
-    }
-
-    @Test
-    fun `save state`() = runApplicationTest {
-        val initialState = WindowState()
-        val newState =
-            WindowState(
-                placement = WindowPlacement.Maximized,
-                size = DpSize(42.dp, 42.dp),
-                position = WindowPosition(3.dp, 3.dp),
-                isMinimized = true,
-            )
-
-        var isOpen by mutableStateOf(true)
-        var index by mutableStateOf(0)
-        val states = mutableListOf<WindowState>()
-
-        launchApplication {
-            val saveableStateHolder = rememberSaveableStateHolder()
-            saveableStateHolder.SaveableStateProvider(index) {
-                val state = rememberWindowState()
-
-                LaunchedEffect(Unit) {
-                    state.placement = newState.placement
-                    state.isMinimized = newState.isMinimized
-                    state.size = newState.size
-                    state.position = newState.position
-                    states.add(state)
-                }
-            }
-
-            if (isOpen) {
-                Window(onCloseRequest = {}) {}
-            }
-        }
-
-        awaitIdle()
-        assertThat(states.size == 1)
-
-        index = 1
-        awaitIdle()
-        assertThat(states.size == 2)
-
-        index = 0
-        awaitIdle()
-        assertThat(states.size == 3)
-
-        assertThat(states[0].placement == initialState.placement)
-        assertThat(states[0].isMinimized == initialState.isMinimized)
-        assertThat(states[0].size == initialState.size)
-        assertThat(states[0].position == initialState.position)
-        assertThat(states[2].placement == newState.placement)
-        assertThat(states[2].isMinimized == newState.isMinimized)
-        assertThat(states[2].size == newState.size)
-        assertThat(states[2].position == newState.position)
-
-        isOpen = false
-    }
-
-    @Test
-    fun `set window height by its content`() =
-        runApplicationTest(useDelay = isLinux) {
-            lateinit var window: ComposeWindow
-            val state = WindowState(size = DpSize(300.dp, Dp.Unspecified))
-
-            launchApplication {
-                Window(onCloseRequest = ::exitApplication, state = state) {
-                    window = this.window
-
-                    Box(Modifier.width(400.dp).height(200.dp))
-                }
-            }
-
-            awaitIdle()
-            assertThat(window.width).isEqualTo(300)
-            assertThat(window.contentSize.height).isEqualTo(200)
-            assertThat(state.size).isEqualTo(DpSize(window.size.width.dp, window.size.height.dp))
-
-            exitApplication()
-        }
-
-    @Test
-    fun `set window width by its content`() =
-        runApplicationTest(useDelay = isLinux) {
-            lateinit var window: ComposeWindow
-            val state = WindowState(size = DpSize(Dp.Unspecified, 300.dp))
-
-            launchApplication {
-                Window(onCloseRequest = ::exitApplication, state = state) {
-                    window = this.window
-
-                    Box(Modifier.width(400.dp).height(200.dp))
-                }
-            }
-
-            awaitIdle()
-            assertThat(window.height).isEqualTo(300)
-            assertThat(window.contentSize.width).isEqualTo(400)
-            assertThat(state.size).isEqualTo(DpSize(window.size.width.dp, window.size.height.dp))
-
-            exitApplication()
-        }
-
-    @Test
-    fun `set window size by its content`() =
-        runApplicationTest(useDelay = isLinux) {
-            lateinit var window: ComposeWindow
-            val state = WindowState(size = DpSize(Dp.Unspecified, Dp.Unspecified))
-
-            launchApplication {
-                Window(onCloseRequest = ::exitApplication, state = state) {
-                    window = this.window
-
-                    Box(Modifier.width(400.dp).height(200.dp))
-                }
-            }
-
-            awaitIdle()
-            assertThat(window.contentSize).isEqualTo(Dimension(400, 200))
-            assertThat(state.size).isEqualTo(DpSize(window.size.width.dp, window.size.height.dp))
-
-            exitApplication()
-        }
-
-    @Test
-    fun `set window size by its content when window is on the screen`() =
-        runApplicationTest(useDelay = isLinux) {
-            lateinit var window: ComposeWindow
-            val state = WindowState(size = DpSize(100.dp, 100.dp))
-
-            launchApplication {
-                Window(onCloseRequest = ::exitApplication, state = state) {
-                    window = this.window
-
-                    Box(Modifier.width(400.dp).height(200.dp))
-                }
-            }
-
-            awaitIdle()
-
-            state.size = DpSize(Dp.Unspecified, Dp.Unspecified)
-            awaitIdle()
-            assertThat(window.contentSize).isEqualTo(Dimension(400, 200))
-            assertThat(state.size).isEqualTo(DpSize(window.size.width.dp, window.size.height.dp))
-
-            exitApplication()
-        }
-
-    @Test
-    fun `change visible`() = runApplicationTest {
-        lateinit var window: ComposeWindow
-
-        var visible by mutableStateOf(false)
-
-        launchApplication {
-            Window(onCloseRequest = ::exitApplication, visible = visible) { window = this.window }
-        }
-
-        awaitIdle()
-        assertThat(window.isVisible).isEqualTo(false)
-
-        visible = true
-        awaitIdle()
-        assertThat(window.isVisible).isEqualTo(true)
-
-        exitApplication()
-    }
-
-    @Test
-    fun `invisible window should be active`() = runApplicationTest {
-        val receivedNumbers = mutableListOf<Int>()
-
-        val sendChannel = Channel<Int>(Channel.UNLIMITED)
-
-        launchApplication {
-            Window(onCloseRequest = ::exitApplication, visible = false) {
-                LaunchedEffect(Unit) { sendChannel.consumeEach { receivedNumbers.add(it) } }
-            }
-        }
-
-        sendChannel.send(1)
-        awaitIdle()
-        assertThat(receivedNumbers).isEqualTo(listOf(1))
-
-        sendChannel.send(2)
-        awaitIdle()
-        assertThat(receivedNumbers).isEqualTo(listOf(1, 2))
-
-        exitApplication()
-    }
-
-    @Test
-    fun `start invisible undecorated window`() = runApplicationTest {
-        val receivedNumbers = mutableListOf<Int>()
-
-        val sendChannel = Channel<Int>(Channel.UNLIMITED)
-
-        launchApplication {
-            Window(onCloseRequest = ::exitApplication, visible = false, undecorated = true) {
-                LaunchedEffect(Unit) { sendChannel.consumeEach { receivedNumbers.add(it) } }
-            }
-        }
-
-        sendChannel.send(1)
-        awaitIdle()
-        assertThat(receivedNumbers).isEqualTo(listOf(1))
-
-        sendChannel.send(2)
-        awaitIdle()
-        assertThat(receivedNumbers).isEqualTo(listOf(1, 2))
-
-        exitApplication()
-    }
-
-    private val Window.contentSize
-        get() =
-            Dimension(
-                size.width - insets.left - insets.right,
-                size.height - insets.top - insets.bottom,
-            )
-}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/window/window/WindowTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/window/window/WindowTest.kt
deleted file mode 100644
index 9470feb8..0000000
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/window/window/WindowTest.kt
+++ /dev/null
@@ -1,463 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.window.window
-
-import androidx.compose.foundation.Canvas
-import androidx.compose.foundation.background
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.size
-import androidx.compose.material.Button
-import androidx.compose.material.Slider
-import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.runtime.DisposableEffect
-import androidx.compose.runtime.Recomposer
-import androidx.compose.runtime.compositionLocalOf
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.LeakDetector
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.awt.ComposeWindow
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.unit.DpSize
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.window.Window
-import androidx.compose.ui.window.launchApplication
-import androidx.compose.ui.window.rememberWindowState
-import androidx.compose.ui.window.runApplicationTest
-import com.google.common.truth.Truth.assertThat
-import java.awt.Dimension
-import java.awt.GraphicsEnvironment
-import java.awt.event.WindowAdapter
-import java.awt.event.WindowEvent
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.swing.Swing
-import org.junit.Assume.assumeFalse
-import org.junit.Test
-
-class WindowTest {
-    @Test
-    fun `open and close custom window`() = runApplicationTest {
-        var window: ComposeWindow? = null
-
-        launchApplication {
-            var isOpen by remember { mutableStateOf(true) }
-
-            fun createWindow() =
-                ComposeWindow().apply {
-                    size = Dimension(300, 200)
-
-                    addWindowListener(
-                        object : WindowAdapter() {
-                            override fun windowClosing(e: WindowEvent) {
-                                isOpen = false
-                            }
-                        }
-                    )
-                }
-
-            if (isOpen) {
-                Window(create = ::createWindow, dispose = ComposeWindow::dispose) {
-                    window = this.window
-                    Box(Modifier.size(32.dp).background(Color.Red))
-                }
-            }
-        }
-
-        awaitIdle()
-        assertThat(window?.isShowing).isTrue()
-
-        window?.dispatchEvent(WindowEvent(window, WindowEvent.WINDOW_CLOSING))
-    }
-
-    @Test
-    fun `update custom window`() = runApplicationTest {
-        var window: ComposeWindow? = null
-
-        var isOpen by mutableStateOf(true)
-        var title by mutableStateOf("Title1")
-
-        launchApplication {
-            fun createWindow() =
-                ComposeWindow().apply {
-                    size = Dimension(300, 200)
-
-                    addWindowListener(
-                        object : WindowAdapter() {
-                            override fun windowClosing(e: WindowEvent) {
-                                isOpen = false
-                            }
-                        }
-                    )
-                }
-
-            if (isOpen) {
-                Window(
-                    create = ::createWindow,
-                    dispose = ComposeWindow::dispose,
-                    update = { it.title = title }
-                ) {
-                    window = this.window
-                    Box(Modifier.size(32.dp).background(Color.Red))
-                }
-            }
-        }
-
-        awaitIdle()
-        assertThat(window?.isShowing).isTrue()
-        assertThat(window?.title).isEqualTo(title)
-
-        title = "Title2"
-        awaitIdle()
-        assertThat(window?.title).isEqualTo(title)
-
-        isOpen = false
-    }
-
-    @Test
-    fun `open and close window`() = runApplicationTest {
-        var window: ComposeWindow? = null
-
-        launchApplication {
-            Window(onCloseRequest = ::exitApplication) {
-                window = this.window
-                Box(Modifier.size(32.dp).background(Color.Red))
-            }
-        }
-
-        awaitIdle()
-        assertThat(window?.isShowing).isTrue()
-
-        window?.dispatchEvent(WindowEvent(window, WindowEvent.WINDOW_CLOSING))
-    }
-
-    @Test
-    fun `disable closing window`() = runApplicationTest {
-        var isOpen by mutableStateOf(true)
-        var isCloseCalled by mutableStateOf(false)
-        var window: ComposeWindow? = null
-
-        launchApplication {
-            if (isOpen) {
-                Window(onCloseRequest = { isCloseCalled = true }) {
-                    window = this.window
-                    Box(Modifier.size(32.dp).background(Color.Red))
-                }
-            }
-        }
-
-        awaitIdle()
-
-        window?.dispatchEvent(WindowEvent(window, WindowEvent.WINDOW_CLOSING))
-        awaitIdle()
-        assertThat(isCloseCalled).isTrue()
-        assertThat(window?.isShowing).isTrue()
-
-        isOpen = false
-        awaitIdle()
-        assertThat(window?.isShowing).isFalse()
-    }
-
-    @Test
-    fun `show splash screen`() = runApplicationTest {
-        var window1: ComposeWindow? = null
-        var window2: ComposeWindow? = null
-
-        var isOpen by mutableStateOf(true)
-        var isLoading by mutableStateOf(true)
-
-        launchApplication {
-            if (isOpen) {
-                if (isLoading) {
-                    Window(onCloseRequest = {}) {
-                        window1 = this.window
-                        Box(Modifier.size(32.dp).background(Color.Red))
-                    }
-                } else {
-                    Window(onCloseRequest = {}) {
-                        window2 = this.window
-                        Box(Modifier.size(32.dp).background(Color.Blue))
-                    }
-                }
-            }
-        }
-
-        awaitIdle()
-        assertThat(window1?.isShowing).isTrue()
-        assertThat(window2).isNull()
-
-        isLoading = false
-        awaitIdle()
-        assertThat(window1?.isShowing).isFalse()
-        assertThat(window2?.isShowing).isTrue()
-
-        isOpen = false
-        awaitIdle()
-        assertThat(window1?.isShowing).isFalse()
-        assertThat(window2?.isShowing).isFalse()
-    }
-
-    @Test
-    fun `open two windows`() = runApplicationTest {
-        var window1: ComposeWindow? = null
-        var window2: ComposeWindow? = null
-
-        var isOpen by mutableStateOf(true)
-
-        launchApplication {
-            if (isOpen) {
-                Window(onCloseRequest = {}) {
-                    window1 = this.window
-                    Box(Modifier.size(32.dp).background(Color.Red))
-                }
-
-                Window(onCloseRequest = {}) {
-                    window2 = this.window
-                    Box(Modifier.size(32.dp).background(Color.Blue))
-                }
-            }
-        }
-
-        awaitIdle()
-        assertThat(window1?.isShowing).isTrue()
-        assertThat(window2?.isShowing).isTrue()
-
-        isOpen = false
-        awaitIdle()
-        assertThat(window1?.isShowing).isFalse()
-        assertThat(window2?.isShowing).isFalse()
-    }
-
-    @Test
-    fun `open nested window`() = runApplicationTest {
-        var window1: ComposeWindow? = null
-        var window2: ComposeWindow? = null
-
-        var isOpen by mutableStateOf(true)
-        var isNestedOpen by mutableStateOf(true)
-
-        launchApplication {
-            if (isOpen) {
-                Window(
-                    onCloseRequest = {},
-                    state =
-                        rememberWindowState(
-                            size = DpSize(600.dp, 600.dp),
-                        )
-                ) {
-                    window1 = this.window
-                    Box(Modifier.size(32.dp).background(Color.Red))
-
-                    if (isNestedOpen) {
-                        Window(
-                            onCloseRequest = {},
-                            state =
-                                rememberWindowState(
-                                    size = DpSize(300.dp, 300.dp),
-                                )
-                        ) {
-                            window2 = this.window
-                            Box(Modifier.size(32.dp).background(Color.Blue))
-                        }
-                    }
-                }
-            }
-        }
-
-        awaitIdle()
-        assertThat(window1?.isShowing).isTrue()
-        assertThat(window2?.isShowing).isTrue()
-
-        isNestedOpen = false
-        awaitIdle()
-        assertThat(window1?.isShowing).isTrue()
-        assertThat(window2?.isShowing).isFalse()
-
-        isNestedOpen = true
-        awaitIdle()
-        assertThat(window1?.isShowing).isTrue()
-        assertThat(window2?.isShowing).isTrue()
-
-        isOpen = false
-        awaitIdle()
-        assertThat(window1?.isShowing).isFalse()
-        assertThat(window2?.isShowing).isFalse()
-    }
-
-    @Test
-    fun `pass composition local to windows`() = runApplicationTest {
-        var actualValue1: Int? = null
-        var actualValue2: Int? = null
-        var actualValue3: Int? = null
-
-        var isOpen by mutableStateOf(true)
-        val local1TestValue = compositionLocalOf { 0 }
-        val local2TestValue = compositionLocalOf { 0 }
-        var locals by mutableStateOf(arrayOf(local1TestValue provides 1))
-
-        launchApplication {
-            if (isOpen) {
-                CompositionLocalProvider(*locals) {
-                    Window(
-                        onCloseRequest = {},
-                        state =
-                            rememberWindowState(
-                                size = DpSize(600.dp, 600.dp),
-                            )
-                    ) {
-                        actualValue1 = local1TestValue.current
-                        actualValue2 = local2TestValue.current
-                        Box(Modifier.size(32.dp).background(Color.Red))
-
-                        Window(
-                            onCloseRequest = {},
-                            state =
-                                rememberWindowState(
-                                    size = DpSize(300.dp, 300.dp),
-                                )
-                        ) {
-                            actualValue3 = local1TestValue.current
-                            Box(Modifier.size(32.dp).background(Color.Blue))
-                        }
-                    }
-                }
-            }
-        }
-
-        awaitIdle()
-        assertThat(actualValue1).isEqualTo(1)
-        assertThat(actualValue2).isEqualTo(0)
-        assertThat(actualValue3).isEqualTo(1)
-
-        locals = arrayOf(local1TestValue provides 42)
-        awaitIdle()
-        assertThat(actualValue1).isEqualTo(42)
-        assertThat(actualValue2).isEqualTo(0)
-        assertThat(actualValue3).isEqualTo(42)
-
-        locals = arrayOf(local1TestValue provides 43)
-        awaitIdle()
-        assertThat(actualValue1).isEqualTo(43)
-        assertThat(actualValue2).isEqualTo(0)
-        assertThat(actualValue3).isEqualTo(43)
-
-        locals = arrayOf(local1TestValue provides 43, local2TestValue provides 12)
-        awaitIdle()
-        assertThat(actualValue1).isEqualTo(43)
-        assertThat(actualValue2).isEqualTo(12)
-        assertThat(actualValue3).isEqualTo(43)
-
-        locals = emptyArray()
-        awaitIdle()
-        assertThat(actualValue1).isEqualTo(0)
-        assertThat(actualValue2).isEqualTo(0)
-        assertThat(actualValue3).isEqualTo(0)
-
-        isOpen = false
-    }
-
-    @Test
-    fun `DisposableEffect call order`() = runApplicationTest {
-        var initCount = 0
-        var disposeCount = 0
-
-        var isOpen by mutableStateOf(true)
-
-        launchApplication {
-            if (isOpen) {
-                Window(onCloseRequest = {}) {
-                    DisposableEffect(Unit) {
-                        initCount++
-                        onDispose { disposeCount++ }
-                    }
-                }
-            }
-        }
-
-        awaitIdle()
-        assertThat(initCount).isEqualTo(1)
-        assertThat(disposeCount).isEqualTo(0)
-
-        isOpen = false
-        awaitIdle()
-        assertThat(initCount).isEqualTo(1)
-        assertThat(disposeCount).isEqualTo(1)
-    }
-
-    @Test(timeout = 30000)
-    fun `window dispose should not cause a memory leak`() {
-        assumeFalse(GraphicsEnvironment.getLocalGraphicsEnvironment().isHeadlessInstance)
-
-        val leakDetector = LeakDetector()
-
-        val oldRecomposers = Recomposer.runningRecomposers.value
-
-        runBlocking(Dispatchers.Swing) {
-            repeat(10) {
-                val window = ComposeWindow()
-                window.size = Dimension(200, 200)
-                window.isVisible = true
-                window.setContent {
-                    Button({}) {}
-                    Slider(0f, {})
-                }
-                window.dispose()
-                leakDetector.observeObject(window)
-            }
-
-            while (Recomposer.runningRecomposers.value != oldRecomposers) {
-                delay(100)
-            }
-
-            assertThat(leakDetector.noLeak()).isTrue()
-        }
-    }
-
-    @Test(timeout = 30000)
-    fun `should draw before window is visible`() = runApplicationTest {
-        var isComposed = false
-        var isDrawn = false
-        var isVisibleOnFirstComposition = false
-        var isVisibleOnFirstDraw = false
-
-        launchApplication {
-            Window(onCloseRequest = ::exitApplication) {
-                if (!isComposed) {
-                    isVisibleOnFirstComposition = window.isVisible
-                    isComposed = true
-                }
-
-                Canvas(Modifier.fillMaxSize()) {
-                    if (!isDrawn) {
-                        isVisibleOnFirstDraw = window.isVisible
-                        isDrawn = true
-                    }
-                }
-            }
-        }
-
-        awaitIdle()
-        assertThat(isVisibleOnFirstComposition).isFalse()
-        assertThat(isVisibleOnFirstDraw).isFalse()
-
-        exitApplication()
-    }
-}
diff --git a/compose/ui/ui/src/desktopTest/resources/androidx/compose/ui/res/star-size-100.svg b/compose/ui/ui/src/desktopTest/resources/androidx/compose/ui/res/star-size-100.svg
deleted file mode 100644
index 62505f1..0000000
--- a/compose/ui/ui/src/desktopTest/resources/androidx/compose/ui/res/star-size-100.svg
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-    xmlns="http://www.w3.org/2000/svg" width="100" height="100"  viewBox="0 0 100 100" version="1.1"
-    id="svg8">
-  <defs
-     id="defs2" />
-  <metadata
-     id="metadata5">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     transform="translate(0,-197)"
-     id="layer1">
-    <path
-       id="path3703"
-       d="M 50.000001,197 59.567086,223.90301 85.35534,211.64466 73.096987,237.43292 100,247 73.096986,256.56709 85.355338,282.35534 59.567084,270.09699 49.999999,297 40.432914,270.09699 14.64466,282.35534 26.903013,256.56708 0,247 26.903014,237.43291 14.644662,211.64466 40.432916,223.90301 Z"
-       style="fill:#ff5555;stroke-width:0.21590135" />
-  </g>
-</svg>
diff --git a/compose/ui/ui/src/desktopTest/resources/androidx/compose/ui/res/star-size-unspecified.svg b/compose/ui/ui/src/desktopTest/resources/androidx/compose/ui/res/star-size-unspecified.svg
deleted file mode 100644
index 5e6f47d..0000000
--- a/compose/ui/ui/src/desktopTest/resources/androidx/compose/ui/res/star-size-unspecified.svg
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" version="1.1"
-    id="svg8">
-  <defs
-     id="defs2" />
-  <metadata
-     id="metadata5">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     transform="translate(0,-197)"
-     id="layer1">
-    <path
-       id="path3703"
-       d="M 50.000001,197 59.567086,223.90301 85.35534,211.64466 73.096987,237.43292 100,247 73.096986,256.56709 85.355338,282.35534 59.567084,270.09699 49.999999,297 40.432914,270.09699 14.64466,282.35534 26.903013,256.56708 0,247 26.903014,237.43291 14.644662,211.64466 40.432916,223.90301 Z"
-       style="fill:#ff5555;stroke-width:0.21590135" />
-  </g>
-</svg>
diff --git a/compose/ui/ui/src/desktopTest/resources/androidx/compose/ui/res/star-viewbox-unspecified.svg b/compose/ui/ui/src/desktopTest/resources/androidx/compose/ui/res/star-viewbox-unspecified.svg
deleted file mode 100644
index 946a744..0000000
--- a/compose/ui/ui/src/desktopTest/resources/androidx/compose/ui/res/star-viewbox-unspecified.svg
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-    xmlns="http://www.w3.org/2000/svg" width="100" height="100" version="1.1"
-    id="svg8">
-  <defs
-     id="defs2" />
-  <metadata
-     id="metadata5">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     transform="translate(0,-197)"
-     id="layer1">
-    <path
-       id="path3703"
-       d="M 50.000001,197 59.567086,223.90301 85.35534,211.64466 73.096987,237.43292 100,247 73.096986,256.56709 85.355338,282.35534 59.567084,270.09699 49.999999,297 40.432914,270.09699 14.64466,282.35534 26.903013,256.56708 0,247 26.903014,237.43291 14.644662,211.64466 40.432916,223.90301 Z"
-       style="fill:#ff5555;stroke-width:0.21590135" />
-  </g>
-</svg>
diff --git a/compose/ui/ui/src/desktopTest/resources/mockito-extensions/org.mockito.plugins.MockMaker b/compose/ui/ui/src/desktopTest/resources/mockito-extensions/org.mockito.plugins.MockMaker
deleted file mode 100644
index ca6ee9c..0000000
--- a/compose/ui/ui/src/desktopTest/resources/mockito-extensions/org.mockito.plugins.MockMaker
+++ /dev/null
@@ -1 +0,0 @@
-mock-maker-inline
\ No newline at end of file
diff --git a/compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/platform/SkiaBasedOwner.skiko.kt b/compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/platform/SkiaBasedOwner.skiko.kt
index c054e44..e3c979b 100644
--- a/compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/platform/SkiaBasedOwner.skiko.kt
+++ b/compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/platform/SkiaBasedOwner.skiko.kt
@@ -387,7 +387,8 @@
     override fun createLayer(
         drawBlock: (Canvas, GraphicsLayer?) -> Unit,
         invalidateParentLayer: () -> Unit,
-        explicitLayer: GraphicsLayer?
+        explicitLayer: GraphicsLayer?,
+        forceUseOldLayers: Boolean
     ) =
         SkiaLayer(
             density,
diff --git a/constraintlayout/constraintlayout-compose/api/1.1.0-beta01.txt b/constraintlayout/constraintlayout-compose/api/1.1.0-beta01.txt
new file mode 100644
index 0000000..0375873
--- /dev/null
+++ b/constraintlayout/constraintlayout-compose/api/1.1.0-beta01.txt
@@ -0,0 +1,1013 @@
+// Signature format: 4.0
+package androidx.constraintlayout.compose {
+
+  @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public final class Arc {
+    method public String getName();
+    property public final String name;
+    field public static final androidx.constraintlayout.compose.Arc.Companion Companion;
+  }
+
+  public static final class Arc.Companion {
+    method public androidx.constraintlayout.compose.Arc getAbove();
+    method public androidx.constraintlayout.compose.Arc getBelow();
+    method public androidx.constraintlayout.compose.Arc getFlip();
+    method public androidx.constraintlayout.compose.Arc getNone();
+    method public androidx.constraintlayout.compose.Arc getStartHorizontal();
+    method public androidx.constraintlayout.compose.Arc getStartVertical();
+    property public final androidx.constraintlayout.compose.Arc Above;
+    property public final androidx.constraintlayout.compose.Arc Below;
+    property public final androidx.constraintlayout.compose.Arc Flip;
+    property public final androidx.constraintlayout.compose.Arc None;
+    property public final androidx.constraintlayout.compose.Arc StartHorizontal;
+    property public final androidx.constraintlayout.compose.Arc StartVertical;
+  }
+
+  @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public abstract sealed class BaseKeyFrameScope {
+    method protected final <E extends androidx.constraintlayout.compose.NamedPropertyOrValue> kotlin.properties.ObservableProperty<E> addNameOnPropertyChange(E initialValue, optional String? nameOverride);
+    method protected final <T> kotlin.properties.ObservableProperty<T> addOnPropertyChange(T initialValue, optional String? nameOverride);
+  }
+
+  @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public abstract sealed class BaseKeyFramesScope {
+    method public final androidx.constraintlayout.compose.Easing getEasing();
+    method public final void setEasing(androidx.constraintlayout.compose.Easing);
+    property public final androidx.constraintlayout.compose.Easing easing;
+  }
+
+  @kotlin.jvm.JvmDefaultWithCompatibility public interface BaselineAnchorable {
+    method public void linkTo(androidx.constraintlayout.compose.ConstraintLayoutBaseScope.BaselineAnchor anchor, optional float margin, optional float goneMargin);
+    method public void linkTo(androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor anchor, optional float margin, optional float goneMargin);
+  }
+
+  @androidx.compose.runtime.Immutable public final class ChainStyle {
+    field public static final androidx.constraintlayout.compose.ChainStyle.Companion Companion;
+  }
+
+  public static final class ChainStyle.Companion {
+    method @androidx.compose.runtime.Stable public androidx.constraintlayout.compose.ChainStyle Packed(float bias);
+    method public androidx.constraintlayout.compose.ChainStyle getPacked();
+    method public androidx.constraintlayout.compose.ChainStyle getSpread();
+    method public androidx.constraintlayout.compose.ChainStyle getSpreadInside();
+    property public final androidx.constraintlayout.compose.ChainStyle Packed;
+    property public final androidx.constraintlayout.compose.ChainStyle Spread;
+    property public final androidx.constraintlayout.compose.ChainStyle SpreadInside;
+  }
+
+  @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Stable public final class ConstrainScope {
+    method public androidx.constraintlayout.compose.Dimension asDimension(float);
+    method public void centerAround(androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor anchor);
+    method public void centerAround(androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor anchor);
+    method public void centerHorizontallyTo(androidx.constraintlayout.compose.ConstrainedLayoutReference other, optional @FloatRange(from=0.0, to=1.0) float bias);
+    method public void centerTo(androidx.constraintlayout.compose.ConstrainedLayoutReference other);
+    method public void centerVerticallyTo(androidx.constraintlayout.compose.ConstrainedLayoutReference other, optional @FloatRange(from=0.0, to=1.0) float bias);
+    method public void circular(androidx.constraintlayout.compose.ConstrainedLayoutReference other, float angle, float distance);
+    method public void clearConstraints();
+    method public void clearHorizontal();
+    method public void clearVertical();
+    method public androidx.constraintlayout.compose.VerticalAnchorable getAbsoluteLeft();
+    method public androidx.constraintlayout.compose.VerticalAnchorable getAbsoluteRight();
+    method public float getAlpha();
+    method public androidx.constraintlayout.compose.BaselineAnchorable getBaseline();
+    method public androidx.constraintlayout.compose.HorizontalAnchorable getBottom();
+    method public androidx.constraintlayout.compose.VerticalAnchorable getEnd();
+    method public androidx.constraintlayout.compose.Dimension getHeight();
+    method public float getHorizontalBias();
+    method public float getHorizontalChainWeight();
+    method public androidx.constraintlayout.compose.ConstrainedLayoutReference getParent();
+    method public float getPivotX();
+    method public float getPivotY();
+    method public float getRotationX();
+    method public float getRotationY();
+    method public float getRotationZ();
+    method public float getScaleX();
+    method public float getScaleY();
+    method public androidx.constraintlayout.compose.VerticalAnchorable getStart();
+    method public androidx.constraintlayout.compose.HorizontalAnchorable getTop();
+    method public float getTranslationX();
+    method public float getTranslationY();
+    method public float getTranslationZ();
+    method public float getVerticalBias();
+    method public float getVerticalChainWeight();
+    method public androidx.constraintlayout.compose.Visibility getVisibility();
+    method public androidx.constraintlayout.compose.Dimension getWidth();
+    method public void linkTo(androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor top, androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor bottom, optional float topMargin, optional float bottomMargin, optional float topGoneMargin, optional float bottomGoneMargin, optional @FloatRange(from=0.0, to=1.0) float bias);
+    method public void linkTo(androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor start, androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor top, androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor end, androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor bottom, optional float startMargin, optional float topMargin, optional float endMargin, optional float bottomMargin, optional float startGoneMargin, optional float topGoneMargin, optional float endGoneMargin, optional float bottomGoneMargin, optional @FloatRange(from=0.0, to=1.0) float horizontalBias, optional @FloatRange(from=0.0, to=1.0) float verticalBias);
+    method public void linkTo(androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor start, androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor end, optional float startMargin, optional float endMargin, optional float startGoneMargin, optional float endGoneMargin, optional @FloatRange(from=0.0, to=1.0) float bias);
+    method public void resetDimensions();
+    method public void resetTransforms();
+    method public void setAlpha(float);
+    method public void setHeight(androidx.constraintlayout.compose.Dimension);
+    method public void setHorizontalBias(float);
+    method public void setHorizontalChainWeight(float);
+    method public void setPivotX(float);
+    method public void setPivotY(float);
+    method public void setRotationX(float);
+    method public void setRotationY(float);
+    method public void setRotationZ(float);
+    method public void setScaleX(float);
+    method public void setScaleY(float);
+    method public void setTranslationX(float);
+    method public void setTranslationY(float);
+    method public void setTranslationZ(float);
+    method public void setVerticalBias(float);
+    method public void setVerticalChainWeight(float);
+    method public void setVisibility(androidx.constraintlayout.compose.Visibility);
+    method public void setWidth(androidx.constraintlayout.compose.Dimension);
+    property public final androidx.constraintlayout.compose.VerticalAnchorable absoluteLeft;
+    property public final androidx.constraintlayout.compose.VerticalAnchorable absoluteRight;
+    property public final float alpha;
+    property public final androidx.constraintlayout.compose.BaselineAnchorable baseline;
+    property public final androidx.constraintlayout.compose.HorizontalAnchorable bottom;
+    property public final androidx.constraintlayout.compose.VerticalAnchorable end;
+    property public final androidx.constraintlayout.compose.Dimension height;
+    property public final float horizontalBias;
+    property public final float horizontalChainWeight;
+    property public final androidx.constraintlayout.compose.ConstrainedLayoutReference parent;
+    property public final float pivotX;
+    property public final float pivotY;
+    property public final float rotationX;
+    property public final float rotationY;
+    property public final float rotationZ;
+    property public final float scaleX;
+    property public final float scaleY;
+    property public final androidx.constraintlayout.compose.VerticalAnchorable start;
+    property public final androidx.constraintlayout.compose.HorizontalAnchorable top;
+    property public final float translationX;
+    property public final float translationY;
+    property public final float translationZ;
+    property public final float verticalBias;
+    property public final float verticalChainWeight;
+    property public final androidx.constraintlayout.compose.Visibility visibility;
+    property public final androidx.constraintlayout.compose.Dimension width;
+  }
+
+  @androidx.compose.runtime.Stable public final class ConstrainedLayoutReference extends androidx.constraintlayout.compose.LayoutReference {
+    ctor public ConstrainedLayoutReference(Object id);
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor getAbsoluteLeft();
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor getAbsoluteRight();
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.BaselineAnchor getBaseline();
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor getBottom();
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor getEnd();
+    method public Object getId();
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor getStart();
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor getTop();
+    property public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor absoluteLeft;
+    property public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor absoluteRight;
+    property public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.BaselineAnchor baseline;
+    property public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor bottom;
+    property public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor end;
+    property public Object id;
+    property public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor start;
+    property public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor top;
+  }
+
+  public abstract class ConstraintLayoutBaseScope {
+    ctor public ConstraintLayoutBaseScope();
+    method public final void applyTo(androidx.constraintlayout.compose.State state);
+    method public final androidx.constraintlayout.compose.ConstrainScope constrain(androidx.constraintlayout.compose.ConstrainedLayoutReference ref, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.ConstrainScope,kotlin.Unit> constrainBlock);
+    method public final void constrain(androidx.constraintlayout.compose.ConstrainedLayoutReference[] refs, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.ConstrainScope,kotlin.Unit> constrainBlock);
+    method public final androidx.constraintlayout.compose.HorizontalChainScope constrain(androidx.constraintlayout.compose.HorizontalChainReference ref, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.HorizontalChainScope,kotlin.Unit> constrainBlock);
+    method public final androidx.constraintlayout.compose.VerticalChainScope constrain(androidx.constraintlayout.compose.VerticalChainReference ref, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.VerticalChainScope,kotlin.Unit> constrainBlock);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createAbsoluteLeftBarrier(androidx.constraintlayout.compose.LayoutReference[] elements, optional float margin);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createAbsoluteRightBarrier(androidx.constraintlayout.compose.LayoutReference[] elements, optional float margin);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor createBottomBarrier(androidx.constraintlayout.compose.LayoutReference[] elements, optional float margin);
+    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createColumn(androidx.constraintlayout.compose.LayoutReference[] elements, optional float spacing, optional float[] weights);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createEndBarrier(androidx.constraintlayout.compose.LayoutReference[] elements, optional float margin);
+    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createFlow(androidx.constraintlayout.compose.LayoutReference?[] elements, optional boolean flowVertically, optional float verticalGap, optional float horizontalGap, optional int maxElement, optional float padding, optional androidx.constraintlayout.compose.Wrap wrapMode, optional androidx.constraintlayout.compose.VerticalAlign verticalAlign, optional androidx.constraintlayout.compose.HorizontalAlign horizontalAlign, optional float horizontalFlowBias, optional float verticalFlowBias, optional androidx.constraintlayout.compose.FlowStyle verticalStyle, optional androidx.constraintlayout.compose.FlowStyle horizontalStyle);
+    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createFlow(androidx.constraintlayout.compose.LayoutReference?[] elements, optional boolean flowVertically, optional float verticalGap, optional float horizontalGap, optional int maxElement, optional float paddingHorizontal, optional float paddingVertical, optional androidx.constraintlayout.compose.Wrap wrapMode, optional androidx.constraintlayout.compose.VerticalAlign verticalAlign, optional androidx.constraintlayout.compose.HorizontalAlign horizontalAlign, optional float horizontalFlowBias, optional float verticalFlowBias, optional androidx.constraintlayout.compose.FlowStyle verticalStyle, optional androidx.constraintlayout.compose.FlowStyle horizontalStyle);
+    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createFlow(androidx.constraintlayout.compose.LayoutReference?[] elements, optional boolean flowVertically, optional float verticalGap, optional float horizontalGap, optional int maxElement, optional float paddingLeft, optional float paddingTop, optional float paddingRight, optional float paddingBottom, optional androidx.constraintlayout.compose.Wrap wrapMode, optional androidx.constraintlayout.compose.VerticalAlign verticalAlign, optional androidx.constraintlayout.compose.HorizontalAlign horizontalAlign, optional float horizontalFlowBias, optional float verticalFlowBias, optional androidx.constraintlayout.compose.FlowStyle verticalStyle, optional androidx.constraintlayout.compose.FlowStyle horizontalStyle);
+    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createGrid(androidx.constraintlayout.compose.LayoutReference[] elements, @IntRange(from=1L) int rows, @IntRange(from=1L) int columns, optional boolean isHorizontalArrangement, optional float verticalSpacing, optional float horizontalSpacing, optional float[] rowWeights, optional float[] columnWeights, optional androidx.constraintlayout.compose.Skip[] skips, optional androidx.constraintlayout.compose.Span[] spans, optional int flags);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteLeft(float offset);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteLeft(float fraction);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteRight(float offset);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteRight(float fraction);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromBottom(float offset);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromBottom(float fraction);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromEnd(float offset);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromEnd(float fraction);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromStart(float offset);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromStart(float fraction);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromTop(float offset);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromTop(float fraction);
+    method public final androidx.constraintlayout.compose.HorizontalChainReference createHorizontalChain(androidx.constraintlayout.compose.LayoutReference[] elements, optional androidx.constraintlayout.compose.ChainStyle chainStyle);
+    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createRow(androidx.constraintlayout.compose.LayoutReference[] elements, optional float spacing, optional float[] weights);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createStartBarrier(androidx.constraintlayout.compose.LayoutReference[] elements, optional float margin);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor createTopBarrier(androidx.constraintlayout.compose.LayoutReference[] elements, optional float margin);
+    method public final androidx.constraintlayout.compose.VerticalChainReference createVerticalChain(androidx.constraintlayout.compose.LayoutReference[] elements, optional androidx.constraintlayout.compose.ChainStyle chainStyle);
+    method @Deprecated protected final java.util.List<kotlin.jvm.functions.Function1<androidx.constraintlayout.compose.State,kotlin.Unit>> getTasks();
+    method public void reset();
+    method public final androidx.constraintlayout.compose.LayoutReference withChainParams(androidx.constraintlayout.compose.LayoutReference, optional float startMargin, optional float topMargin, optional float endMargin, optional float bottomMargin, optional float startGoneMargin, optional float topGoneMargin, optional float endGoneMargin, optional float bottomGoneMargin, optional float weight);
+    method public final androidx.constraintlayout.compose.LayoutReference withHorizontalChainParams(androidx.constraintlayout.compose.LayoutReference, optional float startMargin, optional float endMargin, optional float startGoneMargin, optional float endGoneMargin, optional float weight);
+    method public final androidx.constraintlayout.compose.LayoutReference withVerticalChainParams(androidx.constraintlayout.compose.LayoutReference, optional float topMargin, optional float bottomMargin, optional float topGoneMargin, optional float bottomGoneMargin, optional float weight);
+    property @Deprecated protected final java.util.List<kotlin.jvm.functions.Function1<androidx.constraintlayout.compose.State,kotlin.Unit>> tasks;
+  }
+
+  @androidx.compose.runtime.Stable public static final class ConstraintLayoutBaseScope.BaselineAnchor {
+    method public androidx.constraintlayout.compose.LayoutReference component2();
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.BaselineAnchor copy(Object id, androidx.constraintlayout.compose.LayoutReference reference);
+    method public androidx.constraintlayout.compose.LayoutReference getReference();
+    property public final androidx.constraintlayout.compose.LayoutReference reference;
+  }
+
+  @androidx.compose.runtime.Stable public static final class ConstraintLayoutBaseScope.HorizontalAnchor {
+    method public androidx.constraintlayout.compose.LayoutReference component3();
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor copy(Object id, int index, androidx.constraintlayout.compose.LayoutReference reference);
+    method public androidx.constraintlayout.compose.LayoutReference getReference();
+    property public final androidx.constraintlayout.compose.LayoutReference reference;
+  }
+
+  @androidx.compose.runtime.Stable public static final class ConstraintLayoutBaseScope.VerticalAnchor {
+    method public androidx.constraintlayout.compose.LayoutReference component3();
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor copy(Object id, int index, androidx.constraintlayout.compose.LayoutReference reference);
+    method public androidx.constraintlayout.compose.LayoutReference getReference();
+    property public final androidx.constraintlayout.compose.LayoutReference reference;
+  }
+
+  public final class ConstraintLayoutKt {
+    method @androidx.compose.runtime.Composable public static inline void ConstraintLayout(optional androidx.compose.ui.Modifier modifier, optional int optimizationLevel, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float>? animateChangesSpec, optional kotlin.jvm.functions.Function0<kotlin.Unit>? finishedAnimationListener, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.ConstraintLayoutScope,kotlin.Unit> content);
+    method @Deprecated @androidx.compose.runtime.Composable public static inline void ConstraintLayout(optional androidx.compose.ui.Modifier modifier, optional int optimizationLevel, optional boolean animateChanges, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> animationSpec, optional kotlin.jvm.functions.Function0<kotlin.Unit>? finishedAnimationListener, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.ConstraintLayoutScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static inline void ConstraintLayout(androidx.constraintlayout.compose.ConstraintSet constraintSet, optional androidx.compose.ui.Modifier modifier, optional int optimizationLevel, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float>? animateChangesSpec, optional kotlin.jvm.functions.Function0<kotlin.Unit>? finishedAnimationListener, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @Deprecated @androidx.compose.runtime.Composable public static inline void ConstraintLayout(androidx.constraintlayout.compose.ConstraintSet constraintSet, optional androidx.compose.ui.Modifier modifier, optional int optimizationLevel, optional boolean animateChanges, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> animationSpec, optional kotlin.jvm.functions.Function0<kotlin.Unit>? finishedAnimationListener, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method public static androidx.constraintlayout.compose.ConstraintSet ConstraintSet(androidx.constraintlayout.compose.ConstraintSet extendConstraintSet, @org.intellij.lang.annotations.Language("json5") String jsonContent);
+    method public static androidx.constraintlayout.compose.ConstraintSet ConstraintSet(androidx.constraintlayout.compose.ConstraintSet extendConstraintSet, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.ConstraintSetScope,kotlin.Unit> description);
+    method public static androidx.constraintlayout.compose.ConstraintSet ConstraintSet(@org.intellij.lang.annotations.Language("json5") String jsonContent);
+    method @androidx.compose.runtime.Composable public static androidx.constraintlayout.compose.ConstraintSet ConstraintSet(@org.intellij.lang.annotations.Language("json5") String content, optional @org.intellij.lang.annotations.Language("json5") String? overrideVariables);
+    method public static androidx.constraintlayout.compose.ConstraintSet ConstraintSet(kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.ConstraintSetScope,kotlin.Unit> description);
+    method public static androidx.constraintlayout.compose.Dimension.MaxCoercible atLeast(androidx.constraintlayout.compose.Dimension.Coercible, float dp);
+    method public static androidx.constraintlayout.compose.Dimension atLeast(androidx.constraintlayout.compose.Dimension.MinCoercible, float dp);
+    method @Deprecated public static androidx.constraintlayout.compose.Dimension atLeastWrapContent(androidx.constraintlayout.compose.Dimension.MinCoercible, float dp);
+    method public static androidx.constraintlayout.compose.Dimension.MinCoercible atMost(androidx.constraintlayout.compose.Dimension.Coercible, float dp);
+    method public static androidx.constraintlayout.compose.Dimension atMost(androidx.constraintlayout.compose.Dimension.MaxCoercible, float dp);
+    method public static androidx.constraintlayout.compose.Dimension.MaxCoercible getAtLeastWrapContent(androidx.constraintlayout.compose.Dimension.Coercible);
+    method public static androidx.constraintlayout.compose.Dimension getAtLeastWrapContent(androidx.constraintlayout.compose.Dimension.MinCoercible);
+    method public static androidx.constraintlayout.compose.Dimension.MinCoercible getAtMostWrapContent(androidx.constraintlayout.compose.Dimension.Coercible);
+    method public static androidx.constraintlayout.compose.Dimension getAtMostWrapContent(androidx.constraintlayout.compose.Dimension.MaxCoercible);
+  }
+
+  @androidx.compose.foundation.layout.LayoutScopeMarker public final class ConstraintLayoutScope extends androidx.constraintlayout.compose.ConstraintLayoutBaseScope {
+    method @androidx.compose.runtime.Stable public androidx.compose.ui.Modifier constrainAs(androidx.compose.ui.Modifier, androidx.constraintlayout.compose.ConstrainedLayoutReference ref, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.ConstrainScope,kotlin.Unit> constrainBlock);
+    method public androidx.constraintlayout.compose.ConstrainedLayoutReference createRef();
+    method @androidx.compose.runtime.Stable public androidx.constraintlayout.compose.ConstraintLayoutScope.ConstrainedLayoutReferences createRefs();
+  }
+
+  public final class ConstraintLayoutScope.ConstrainedLayoutReferences {
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component1();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component10();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component11();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component12();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component13();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component14();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component15();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component16();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component2();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component3();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component4();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component5();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component6();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component7();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component8();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component9();
+  }
+
+  public final class ConstraintLayoutTagKt {
+    method public static Object? getConstraintLayoutId(androidx.compose.ui.layout.Measurable);
+    method public static Object? getConstraintLayoutTag(androidx.compose.ui.layout.Measurable);
+    method public static androidx.compose.ui.Modifier layoutId(androidx.compose.ui.Modifier, String layoutId, optional String? tag);
+  }
+
+  public interface ConstraintLayoutTagParentData {
+    method public String getConstraintLayoutId();
+    method public String getConstraintLayoutTag();
+    property public abstract String constraintLayoutId;
+    property public abstract String constraintLayoutTag;
+  }
+
+  @androidx.compose.runtime.Immutable @kotlin.jvm.JvmDefaultWithCompatibility public interface ConstraintSet {
+    method public void applyTo(androidx.constraintlayout.compose.State state, java.util.List<? extends androidx.compose.ui.layout.Measurable> measurables);
+    method public default void applyTo(androidx.constraintlayout.core.state.Transition transition, int type);
+    method public default boolean isDirty(java.util.List<? extends androidx.compose.ui.layout.Measurable> measurables);
+    method public default androidx.constraintlayout.compose.ConstraintSet override(String name, float value);
+  }
+
+  public final class ConstraintSetRef {
+    method public androidx.constraintlayout.compose.ConstraintSetRef copy(String name);
+  }
+
+  @androidx.compose.foundation.layout.LayoutScopeMarker public final class ConstraintSetScope extends androidx.constraintlayout.compose.ConstraintLayoutBaseScope {
+    method public androidx.constraintlayout.compose.ConstrainedLayoutReference createRefFor(Object id);
+    method public androidx.constraintlayout.compose.ConstraintSetScope.ConstrainedLayoutReferences createRefsFor(java.lang.Object... ids);
+  }
+
+  public final class ConstraintSetScope.ConstrainedLayoutReferences {
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component1();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component10();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component11();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component12();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component13();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component14();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component15();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component16();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component2();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component3();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component4();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component5();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component6();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component7();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component8();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component9();
+  }
+
+  @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public final class CurveFit {
+    method public String getName();
+    property public String name;
+    field public static final androidx.constraintlayout.compose.CurveFit.Companion Companion;
+  }
+
+  public static final class CurveFit.Companion {
+    method public androidx.constraintlayout.compose.CurveFit getLinear();
+    method public androidx.constraintlayout.compose.CurveFit getSpline();
+    property public final androidx.constraintlayout.compose.CurveFit Linear;
+    property public final androidx.constraintlayout.compose.CurveFit Spline;
+  }
+
+  @kotlin.jvm.JvmInline public final value class DebugFlags {
+    ctor public DebugFlags(optional boolean showBounds, optional boolean showPaths, optional boolean showKeyPositions);
+    method public boolean getShowBounds();
+    method public boolean getShowKeyPositions();
+    method public boolean getShowPaths();
+    property public final boolean showBounds;
+    property public final boolean showKeyPositions;
+    property public final boolean showPaths;
+    field public static final androidx.constraintlayout.compose.DebugFlags.Companion Companion;
+  }
+
+  public static final class DebugFlags.Companion {
+    method public int getAll();
+    method public int getNone();
+    property public final int All;
+    property public final int None;
+  }
+
+  public final class DesignElements {
+    method public void define(String name, kotlin.jvm.functions.Function2<? super java.lang.String,? super java.util.HashMap<java.lang.String,java.lang.String>,kotlin.Unit> function);
+    method public java.util.HashMap<java.lang.String,kotlin.jvm.functions.Function2<java.lang.String,java.util.HashMap<java.lang.String,java.lang.String>,kotlin.Unit>> getMap();
+    method public void setMap(java.util.HashMap<java.lang.String,kotlin.jvm.functions.Function2<java.lang.String,java.util.HashMap<java.lang.String,java.lang.String>,kotlin.Unit>>);
+    property public final java.util.HashMap<java.lang.String,kotlin.jvm.functions.Function2<java.lang.String,java.util.HashMap<java.lang.String,java.lang.String>,kotlin.Unit>> map;
+    field public static final androidx.constraintlayout.compose.DesignElements INSTANCE;
+  }
+
+  public interface DesignInfoProvider {
+    method public String getDesignInfo(int startX, int startY, String args);
+  }
+
+  public interface Dimension {
+    field public static final androidx.constraintlayout.compose.Dimension.Companion Companion;
+  }
+
+  public static interface Dimension.Coercible extends androidx.constraintlayout.compose.Dimension {
+  }
+
+  public static final class Dimension.Companion {
+    method public androidx.constraintlayout.compose.Dimension.Coercible getFillToConstraints();
+    method public androidx.constraintlayout.compose.Dimension getMatchParent();
+    method public androidx.constraintlayout.compose.Dimension.Coercible getPreferredWrapContent();
+    method public androidx.constraintlayout.compose.Dimension getWrapContent();
+    method public androidx.constraintlayout.compose.Dimension percent(float percent);
+    method public androidx.constraintlayout.compose.Dimension.MinCoercible preferredValue(float dp);
+    method public androidx.constraintlayout.compose.Dimension ratio(String ratio);
+    method public androidx.constraintlayout.compose.Dimension value(float dp);
+    property public final androidx.constraintlayout.compose.Dimension.Coercible fillToConstraints;
+    property public final androidx.constraintlayout.compose.Dimension matchParent;
+    property public final androidx.constraintlayout.compose.Dimension.Coercible preferredWrapContent;
+    property public final androidx.constraintlayout.compose.Dimension wrapContent;
+  }
+
+  public static interface Dimension.MaxCoercible extends androidx.constraintlayout.compose.Dimension {
+  }
+
+  public static interface Dimension.MinCoercible extends androidx.constraintlayout.compose.Dimension {
+  }
+
+  @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public final class Easing {
+    method public String getName();
+    property public String name;
+    field public static final androidx.constraintlayout.compose.Easing.Companion Companion;
+  }
+
+  public static final class Easing.Companion {
+    method public androidx.constraintlayout.compose.Easing cubic(float x1, float y1, float x2, float y2);
+    method public androidx.constraintlayout.compose.Easing getAccelerate();
+    method public androidx.constraintlayout.compose.Easing getAnticipate();
+    method public androidx.constraintlayout.compose.Easing getDecelerate();
+    method public androidx.constraintlayout.compose.Easing getLinear();
+    method public androidx.constraintlayout.compose.Easing getOvershoot();
+    method public androidx.constraintlayout.compose.Easing getStandard();
+    property public final androidx.constraintlayout.compose.Easing Accelerate;
+    property public final androidx.constraintlayout.compose.Easing Anticipate;
+    property public final androidx.constraintlayout.compose.Easing Decelerate;
+    property public final androidx.constraintlayout.compose.Easing Linear;
+    property public final androidx.constraintlayout.compose.Easing Overshoot;
+    property public final androidx.constraintlayout.compose.Easing Standard;
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn(message="MotionLayout API is experimental and it is likely to change.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalMotionApi {
+  }
+
+  @androidx.compose.runtime.Immutable public final class FlowStyle {
+    field public static final androidx.constraintlayout.compose.FlowStyle.Companion Companion;
+  }
+
+  public static final class FlowStyle.Companion {
+    method public androidx.constraintlayout.compose.FlowStyle getPacked();
+    method public androidx.constraintlayout.compose.FlowStyle getSpread();
+    method public androidx.constraintlayout.compose.FlowStyle getSpreadInside();
+    property public final androidx.constraintlayout.compose.FlowStyle Packed;
+    property public final androidx.constraintlayout.compose.FlowStyle Spread;
+    property public final androidx.constraintlayout.compose.FlowStyle SpreadInside;
+  }
+
+  @kotlin.jvm.JvmInline public final value class GridFlags {
+    ctor public GridFlags(optional boolean isPlaceLayoutsOnSpansFirst);
+    method public boolean isPlaceLayoutsOnSpansFirst();
+    property public final boolean isPlaceLayoutsOnSpansFirst;
+    field public static final androidx.constraintlayout.compose.GridFlags.Companion Companion;
+  }
+
+  public static final class GridFlags.Companion {
+    method public int getNone();
+    method public int getPlaceLayoutsOnSpansFirst();
+    property public final int None;
+    property public final int PlaceLayoutsOnSpansFirst;
+  }
+
+  @androidx.compose.runtime.Immutable public final class HorizontalAlign {
+    field public static final androidx.constraintlayout.compose.HorizontalAlign.Companion Companion;
+  }
+
+  public static final class HorizontalAlign.Companion {
+    method public androidx.constraintlayout.compose.HorizontalAlign getCenter();
+    method public androidx.constraintlayout.compose.HorizontalAlign getEnd();
+    method public androidx.constraintlayout.compose.HorizontalAlign getStart();
+    property public final androidx.constraintlayout.compose.HorizontalAlign Center;
+    property public final androidx.constraintlayout.compose.HorizontalAlign End;
+    property public final androidx.constraintlayout.compose.HorizontalAlign Start;
+  }
+
+  @kotlin.jvm.JvmDefaultWithCompatibility public interface HorizontalAnchorable {
+    method public void linkTo(androidx.constraintlayout.compose.ConstraintLayoutBaseScope.BaselineAnchor anchor, optional float margin, optional float goneMargin);
+    method public void linkTo(androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor anchor, optional float margin, optional float goneMargin);
+  }
+
+  @androidx.compose.runtime.Stable public final class HorizontalChainReference extends androidx.constraintlayout.compose.LayoutReference {
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor getAbsoluteLeft();
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor getAbsoluteRight();
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor getEnd();
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor getStart();
+    property public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor absoluteLeft;
+    property public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor absoluteRight;
+    property public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor end;
+    property public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor start;
+  }
+
+  @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Stable public final class HorizontalChainScope {
+    method public androidx.constraintlayout.compose.VerticalAnchorable getAbsoluteLeft();
+    method public androidx.constraintlayout.compose.VerticalAnchorable getAbsoluteRight();
+    method public androidx.constraintlayout.compose.VerticalAnchorable getEnd();
+    method public androidx.constraintlayout.compose.ConstrainedLayoutReference getParent();
+    method public androidx.constraintlayout.compose.VerticalAnchorable getStart();
+    property public final androidx.constraintlayout.compose.VerticalAnchorable absoluteLeft;
+    property public final androidx.constraintlayout.compose.VerticalAnchorable absoluteRight;
+    property public final androidx.constraintlayout.compose.VerticalAnchorable end;
+    property public final androidx.constraintlayout.compose.ConstrainedLayoutReference parent;
+    property public final androidx.constraintlayout.compose.VerticalAnchorable start;
+  }
+
+  public final class InvalidationStrategy {
+    ctor public InvalidationStrategy(optional kotlin.jvm.functions.Function3<? super androidx.constraintlayout.compose.InvalidationStrategySpecification,? super androidx.compose.ui.unit.Constraints,? super androidx.compose.ui.unit.Constraints,java.lang.Boolean>? onIncomingConstraints, kotlin.jvm.functions.Function0<kotlin.Unit>? onObservedStateChange);
+    method public kotlin.jvm.functions.Function3<androidx.constraintlayout.compose.InvalidationStrategySpecification,androidx.compose.ui.unit.Constraints,androidx.compose.ui.unit.Constraints,java.lang.Boolean>? getOnIncomingConstraints();
+    method public kotlin.jvm.functions.Function0<kotlin.Unit>? getOnObservedStateChange();
+    property public final kotlin.jvm.functions.Function3<androidx.constraintlayout.compose.InvalidationStrategySpecification,androidx.compose.ui.unit.Constraints,androidx.compose.ui.unit.Constraints,java.lang.Boolean>? onIncomingConstraints;
+    property public final kotlin.jvm.functions.Function0<kotlin.Unit>? onObservedStateChange;
+    field public static final androidx.constraintlayout.compose.InvalidationStrategy.Companion Companion;
+  }
+
+  public static final class InvalidationStrategy.Companion {
+    method public androidx.constraintlayout.compose.InvalidationStrategy getDefaultInvalidationStrategy();
+    property public final androidx.constraintlayout.compose.InvalidationStrategy DefaultInvalidationStrategy;
+  }
+
+  public final class InvalidationStrategySpecification {
+    method public boolean shouldInvalidateOnFixedHeight(long oldConstraints, long newConstraints, int skipCount, int threshold);
+    method public boolean shouldInvalidateOnFixedWidth(long oldConstraints, long newConstraints, int skipCount, int threshold);
+  }
+
+  @SuppressCompatibility @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.constraintlayout.compose.ExperimentalMotionApi public final class KeyAttributeScope extends androidx.constraintlayout.compose.BaseKeyFrameScope {
+    method public float getAlpha();
+    method public float getRotationX();
+    method public float getRotationY();
+    method public float getRotationZ();
+    method public float getScaleX();
+    method public float getScaleY();
+    method public float getTranslationX();
+    method public float getTranslationY();
+    method public float getTranslationZ();
+    method public void setAlpha(float);
+    method public void setRotationX(float);
+    method public void setRotationY(float);
+    method public void setRotationZ(float);
+    method public void setScaleX(float);
+    method public void setScaleY(float);
+    method public void setTranslationX(float);
+    method public void setTranslationY(float);
+    method public void setTranslationZ(float);
+    property public final float alpha;
+    property public final float rotationX;
+    property public final float rotationY;
+    property public final float rotationZ;
+    property public final float scaleX;
+    property public final float scaleY;
+    property public final float translationX;
+    property public final float translationY;
+    property public final float translationZ;
+  }
+
+  @SuppressCompatibility @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.constraintlayout.compose.ExperimentalMotionApi public final class KeyAttributesScope extends androidx.constraintlayout.compose.BaseKeyFramesScope {
+    method public void frame(@IntRange(from=0L, to=100L) int frame, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.KeyAttributeScope,kotlin.Unit> keyFrameContent);
+  }
+
+  @SuppressCompatibility @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.constraintlayout.compose.ExperimentalMotionApi public final class KeyCycleScope extends androidx.constraintlayout.compose.BaseKeyFrameScope {
+    method public float getAlpha();
+    method public float getOffset();
+    method public float getPeriod();
+    method public float getPhase();
+    method public float getRotationX();
+    method public float getRotationY();
+    method public float getRotationZ();
+    method public float getScaleX();
+    method public float getScaleY();
+    method public float getTranslationX();
+    method public float getTranslationY();
+    method public float getTranslationZ();
+    method public void setAlpha(float);
+    method public void setOffset(float);
+    method public void setPeriod(float);
+    method public void setPhase(float);
+    method public void setRotationX(float);
+    method public void setRotationY(float);
+    method public void setRotationZ(float);
+    method public void setScaleX(float);
+    method public void setScaleY(float);
+    method public void setTranslationX(float);
+    method public void setTranslationY(float);
+    method public void setTranslationZ(float);
+    property public final float alpha;
+    property public final float offset;
+    property public final float period;
+    property public final float phase;
+    property public final float rotationX;
+    property public final float rotationY;
+    property public final float rotationZ;
+    property public final float scaleX;
+    property public final float scaleY;
+    property public final float translationX;
+    property public final float translationY;
+    property public final float translationZ;
+  }
+
+  @SuppressCompatibility @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.constraintlayout.compose.ExperimentalMotionApi public final class KeyCyclesScope extends androidx.constraintlayout.compose.BaseKeyFramesScope {
+    method public void frame(@IntRange(from=0L, to=100L) int frame, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.KeyCycleScope,kotlin.Unit> keyFrameContent);
+  }
+
+  @SuppressCompatibility @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.constraintlayout.compose.ExperimentalMotionApi public final class KeyPositionScope extends androidx.constraintlayout.compose.BaseKeyFrameScope {
+    method public androidx.constraintlayout.compose.CurveFit? getCurveFit();
+    method public float getPercentHeight();
+    method public float getPercentWidth();
+    method public float getPercentX();
+    method public float getPercentY();
+    method public void setCurveFit(androidx.constraintlayout.compose.CurveFit?);
+    method public void setPercentHeight(float);
+    method public void setPercentWidth(float);
+    method public void setPercentX(float);
+    method public void setPercentY(float);
+    property public final androidx.constraintlayout.compose.CurveFit? curveFit;
+    property public final float percentHeight;
+    property public final float percentWidth;
+    property public final float percentX;
+    property public final float percentY;
+  }
+
+  @SuppressCompatibility @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.constraintlayout.compose.ExperimentalMotionApi public final class KeyPositionsScope extends androidx.constraintlayout.compose.BaseKeyFramesScope {
+    method public void frame(@IntRange(from=0L, to=100L) int frame, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.KeyPositionScope,kotlin.Unit> keyFrameContent);
+    method public androidx.constraintlayout.compose.RelativePosition getType();
+    method public void setType(androidx.constraintlayout.compose.RelativePosition);
+    property public final androidx.constraintlayout.compose.RelativePosition type;
+  }
+
+  public enum LayoutInfoFlags {
+    enum_constant public static final androidx.constraintlayout.compose.LayoutInfoFlags BOUNDS;
+    enum_constant public static final androidx.constraintlayout.compose.LayoutInfoFlags NONE;
+  }
+
+  public interface LayoutInformationReceiver {
+    method public androidx.constraintlayout.compose.MotionLayoutDebugFlags getForcedDrawDebug();
+    method public int getForcedHeight();
+    method public float getForcedProgress();
+    method public int getForcedWidth();
+    method public androidx.constraintlayout.compose.LayoutInfoFlags getLayoutInformationMode();
+    method public void onNewProgress(float progress);
+    method public void resetForcedProgress();
+    method public void setLayoutInformation(String information);
+    method public void setUpdateFlag(androidx.compose.runtime.MutableState<java.lang.Long> needsUpdate);
+  }
+
+  @androidx.compose.runtime.Stable public abstract class LayoutReference {
+  }
+
+  public final class MotionCarouselKt {
+    method @androidx.compose.runtime.Composable public static void ItemHolder(int i, String slotPrefix, boolean showSlot, kotlin.jvm.functions.Function0<kotlin.Unit> function);
+    method @androidx.compose.runtime.Composable public static void MotionCarousel(androidx.constraintlayout.compose.MotionScene motionScene, int initialSlotIndex, int numSlots, optional String backwardTransition, optional String forwardTransition, optional String slotPrefix, optional boolean showSlots, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.MotionCarouselScope,kotlin.Unit> content);
+    method public static inline <T> void items(androidx.constraintlayout.compose.MotionCarouselScope, java.util.List<? extends T> items, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> itemContent);
+    method public static inline <T> void itemsWithProperties(androidx.constraintlayout.compose.MotionCarouselScope, java.util.List<? extends T> items, kotlin.jvm.functions.Function2<? super T,? super androidx.compose.runtime.State<androidx.constraintlayout.compose.MotionLayoutScope.MotionProperties>,kotlin.Unit> itemContent);
+  }
+
+  public interface MotionCarouselScope {
+    method public void items(int count, kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit> itemContent);
+    method public void itemsWithProperties(int count, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super androidx.compose.runtime.State<androidx.constraintlayout.compose.MotionLayoutScope.MotionProperties>,kotlin.Unit> itemContent);
+  }
+
+  public interface MotionItemsProvider {
+    method public int count();
+    method public kotlin.jvm.functions.Function0<kotlin.Unit> getContent(int index);
+    method public kotlin.jvm.functions.Function0<kotlin.Unit> getContent(int index, androidx.compose.runtime.State<androidx.constraintlayout.compose.MotionLayoutScope.MotionProperties> properties);
+    method public boolean hasItemsWithProperties();
+  }
+
+  public enum MotionLayoutDebugFlags {
+    enum_constant public static final androidx.constraintlayout.compose.MotionLayoutDebugFlags NONE;
+    enum_constant public static final androidx.constraintlayout.compose.MotionLayoutDebugFlags SHOW_ALL;
+    enum_constant public static final androidx.constraintlayout.compose.MotionLayoutDebugFlags UNKNOWN;
+  }
+
+  @Deprecated public enum MotionLayoutFlag {
+    enum_constant @Deprecated public static final androidx.constraintlayout.compose.MotionLayoutFlag Default;
+    enum_constant @Deprecated public static final androidx.constraintlayout.compose.MotionLayoutFlag FullMeasure;
+  }
+
+  public final class MotionLayoutKt {
+    method @SuppressCompatibility @androidx.compose.runtime.Composable @androidx.constraintlayout.compose.ExperimentalMotionApi public static inline void MotionLayout(androidx.constraintlayout.compose.ConstraintSet start, androidx.constraintlayout.compose.ConstraintSet end, float progress, optional androidx.compose.ui.Modifier modifier, optional androidx.constraintlayout.compose.Transition? transition, optional int debugFlags, optional int optimizationLevel, optional androidx.constraintlayout.compose.InvalidationStrategy invalidationStrategy, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.MotionLayoutScope,kotlin.Unit> content);
+    method @SuppressCompatibility @androidx.compose.runtime.Composable @androidx.constraintlayout.compose.ExperimentalMotionApi public static inline void MotionLayout(androidx.constraintlayout.compose.MotionScene motionScene, float progress, optional androidx.compose.ui.Modifier modifier, optional String transitionName, optional int debugFlags, optional int optimizationLevel, optional androidx.constraintlayout.compose.InvalidationStrategy invalidationStrategy, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.MotionLayoutScope,kotlin.Unit> content);
+    method @SuppressCompatibility @androidx.compose.runtime.Composable @androidx.constraintlayout.compose.ExperimentalMotionApi public static inline void MotionLayout(androidx.constraintlayout.compose.MotionScene motionScene, String? constraintSetName, androidx.compose.animation.core.AnimationSpec<java.lang.Float> animationSpec, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? finishedAnimationListener, optional int debugFlags, optional int optimizationLevel, optional androidx.constraintlayout.compose.InvalidationStrategy invalidationStrategy, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.MotionLayoutScope,kotlin.Unit> content);
+  }
+
+  @SuppressCompatibility @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.constraintlayout.compose.ExperimentalMotionApi public final class MotionLayoutScope {
+    method public long customColor(String id, String name);
+    method public float customDistance(String id, String name);
+    method public float customFloat(String id, String name);
+    method public long customFontSize(String id, String name);
+    method public int customInt(String id, String name);
+    method public androidx.constraintlayout.compose.MotionLayoutScope.CustomProperties customProperties(String id);
+    method @Deprecated public long motionColor(String id, String name);
+    method @Deprecated public float motionDistance(String id, String name);
+    method @Deprecated public float motionFloat(String id, String name);
+    method @Deprecated public long motionFontSize(String id, String name);
+    method @Deprecated public int motionInt(String id, String name);
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.runtime.State<androidx.constraintlayout.compose.MotionLayoutScope.MotionProperties> motionProperties(String id);
+    method @Deprecated public androidx.constraintlayout.compose.MotionLayoutScope.MotionProperties motionProperties(String id, String tag);
+    method public androidx.compose.ui.Modifier onStartEndBoundsChanged(androidx.compose.ui.Modifier, Object layoutId, kotlin.jvm.functions.Function2<? super androidx.compose.ui.geometry.Rect,? super androidx.compose.ui.geometry.Rect,kotlin.Unit> onBoundsChanged);
+  }
+
+  public final class MotionLayoutScope.CustomProperties {
+    method public long color(String name);
+    method public float distance(String name);
+    method public float float(String name);
+    method public long fontSize(String name);
+    method public int int(String name);
+  }
+
+  public final class MotionLayoutScope.MotionProperties {
+    method public long color(String name);
+    method public float distance(String name);
+    method public float float(String name);
+    method public long fontSize(String name);
+    method public String id();
+    method public int int(String name);
+    method public String? tag();
+  }
+
+  @SuppressCompatibility @androidx.compose.runtime.Immutable @androidx.constraintlayout.compose.ExperimentalMotionApi public interface MotionScene extends androidx.constraintlayout.core.state.CoreMotionScene {
+    method public androidx.constraintlayout.compose.ConstraintSet? getConstraintSetInstance(String name);
+    method public androidx.constraintlayout.compose.Transition? getTransitionInstance(String name);
+  }
+
+  public final class MotionSceneKt {
+    method @SuppressCompatibility @androidx.compose.runtime.Composable @androidx.constraintlayout.compose.ExperimentalMotionApi public static androidx.constraintlayout.compose.MotionScene MotionScene(@org.intellij.lang.annotations.Language("json5") String content);
+  }
+
+  @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public final class MotionSceneScope {
+    method public androidx.constraintlayout.compose.ConstraintSetRef addConstraintSet(androidx.constraintlayout.compose.ConstraintSet constraintSet, optional String? name);
+    method public void addTransition(androidx.constraintlayout.compose.Transition transition, optional String? name);
+    method public androidx.constraintlayout.compose.ConstraintSetRef constraintSet(optional String? name, optional androidx.constraintlayout.compose.ConstraintSetRef? extendConstraintSet, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.ConstraintSetScope,kotlin.Unit> constraintSetContent);
+    method public androidx.constraintlayout.compose.ConstrainedLayoutReference createRefFor(Object id);
+    method public androidx.constraintlayout.compose.MotionSceneScope.ConstrainedLayoutReferences createRefsFor(java.lang.Object... ids);
+    method public void customColor(androidx.constraintlayout.compose.ConstrainScope, String name, long value);
+    method public void customColor(androidx.constraintlayout.compose.KeyAttributeScope, String name, long value);
+    method public void customDistance(androidx.constraintlayout.compose.ConstrainScope, String name, float value);
+    method public void customDistance(androidx.constraintlayout.compose.KeyAttributeScope, String name, float value);
+    method public void customFloat(androidx.constraintlayout.compose.ConstrainScope, String name, float value);
+    method public void customFloat(androidx.constraintlayout.compose.KeyAttributeScope, String name, float value);
+    method public void customFontSize(androidx.constraintlayout.compose.ConstrainScope, String name, long value);
+    method public void customFontSize(androidx.constraintlayout.compose.KeyAttributeScope, String name, long value);
+    method public void customInt(androidx.constraintlayout.compose.ConstrainScope, String name, int value);
+    method public void customInt(androidx.constraintlayout.compose.KeyAttributeScope, String name, int value);
+    method public void defaultTransition(androidx.constraintlayout.compose.ConstraintSetRef from, androidx.constraintlayout.compose.ConstraintSetRef to, optional kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.TransitionScope,kotlin.Unit> transitionContent);
+    method public float getStaggeredWeight(androidx.constraintlayout.compose.ConstrainScope);
+    method public void setStaggeredWeight(androidx.constraintlayout.compose.ConstrainScope, float);
+    method public void transition(androidx.constraintlayout.compose.ConstraintSetRef from, androidx.constraintlayout.compose.ConstraintSetRef to, optional String? name, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.TransitionScope,kotlin.Unit> transitionContent);
+  }
+
+  public final class MotionSceneScope.ConstrainedLayoutReferences {
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component1();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component10();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component11();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component12();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component13();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component14();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component15();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component16();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component2();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component3();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component4();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component5();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component6();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component7();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component8();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component9();
+  }
+
+  public final class MotionSceneScopeKt {
+    method @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public static androidx.constraintlayout.compose.MotionScene MotionScene(kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.MotionSceneScope,kotlin.Unit> motionSceneContent);
+  }
+
+  @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public final class OnSwipe {
+    ctor public OnSwipe(androidx.constraintlayout.compose.ConstrainedLayoutReference anchor, androidx.constraintlayout.compose.SwipeSide side, androidx.constraintlayout.compose.SwipeDirection direction, optional float dragScale, optional float dragThreshold, optional androidx.constraintlayout.compose.ConstrainedLayoutReference? dragAround, optional androidx.constraintlayout.compose.ConstrainedLayoutReference? limitBoundsTo, optional androidx.constraintlayout.compose.SwipeTouchUp onTouchUp, optional androidx.constraintlayout.compose.SwipeMode mode);
+    method public androidx.constraintlayout.compose.ConstrainedLayoutReference getAnchor();
+    method public androidx.constraintlayout.compose.SwipeDirection getDirection();
+    method public androidx.constraintlayout.compose.ConstrainedLayoutReference? getDragAround();
+    method public float getDragScale();
+    method public float getDragThreshold();
+    method public androidx.constraintlayout.compose.ConstrainedLayoutReference? getLimitBoundsTo();
+    method public androidx.constraintlayout.compose.SwipeMode getMode();
+    method public androidx.constraintlayout.compose.SwipeTouchUp getOnTouchUp();
+    method public androidx.constraintlayout.compose.SwipeSide getSide();
+    property public final androidx.constraintlayout.compose.ConstrainedLayoutReference anchor;
+    property public final androidx.constraintlayout.compose.SwipeDirection direction;
+    property public final androidx.constraintlayout.compose.ConstrainedLayoutReference? dragAround;
+    property public final float dragScale;
+    property public final float dragThreshold;
+    property public final androidx.constraintlayout.compose.ConstrainedLayoutReference? limitBoundsTo;
+    property public final androidx.constraintlayout.compose.SwipeMode mode;
+    property public final androidx.constraintlayout.compose.SwipeTouchUp onTouchUp;
+    property public final androidx.constraintlayout.compose.SwipeSide side;
+  }
+
+  @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public final class RelativePosition {
+    method public String getName();
+    property public String name;
+    field public static final androidx.constraintlayout.compose.RelativePosition.Companion Companion;
+  }
+
+  public static final class RelativePosition.Companion {
+    method public androidx.constraintlayout.compose.RelativePosition getDelta();
+    method public androidx.constraintlayout.compose.RelativePosition getParent();
+    method public androidx.constraintlayout.compose.RelativePosition getPath();
+    property public final androidx.constraintlayout.compose.RelativePosition Delta;
+    property public final androidx.constraintlayout.compose.RelativePosition Parent;
+    property public final androidx.constraintlayout.compose.RelativePosition Path;
+  }
+
+  @kotlin.jvm.JvmInline public final value class Skip {
+    ctor public Skip(@IntRange(from=0L) int position, @IntRange(from=1L) int size);
+    ctor public Skip(@IntRange(from=0L) int position, @IntRange(from=1L) int rows, @IntRange(from=1L) int columns);
+    method public String getDescription();
+    property public final String description;
+  }
+
+  @kotlin.jvm.JvmInline public final value class Span {
+    ctor public Span(@IntRange(from=0L) int position, @IntRange(from=1L) int size);
+    ctor public Span(@IntRange(from=0L) int position, @IntRange(from=1L) int rows, @IntRange(from=1L) int columns);
+    ctor public Span(String description);
+    method public String getDescription();
+    property public final String description;
+  }
+
+  @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public final class SpringBoundary {
+    method public String getName();
+    property public final String name;
+    field public static final androidx.constraintlayout.compose.SpringBoundary.Companion Companion;
+  }
+
+  public static final class SpringBoundary.Companion {
+    method public androidx.constraintlayout.compose.SpringBoundary getBounceBoth();
+    method public androidx.constraintlayout.compose.SpringBoundary getBounceEnd();
+    method public androidx.constraintlayout.compose.SpringBoundary getBounceStart();
+    method public androidx.constraintlayout.compose.SpringBoundary getOvershoot();
+    property public final androidx.constraintlayout.compose.SpringBoundary BounceBoth;
+    property public final androidx.constraintlayout.compose.SpringBoundary BounceEnd;
+    property public final androidx.constraintlayout.compose.SpringBoundary BounceStart;
+    property public final androidx.constraintlayout.compose.SpringBoundary Overshoot;
+  }
+
+  public final class State extends androidx.constraintlayout.core.state.State {
+    ctor public State(androidx.compose.ui.unit.Density density);
+    method public androidx.compose.ui.unit.Density getDensity();
+    method @Deprecated public androidx.compose.ui.unit.LayoutDirection getLayoutDirection();
+    method public long getRootIncomingConstraints();
+    method @Deprecated public void setLayoutDirection(androidx.compose.ui.unit.LayoutDirection);
+    method public void setRootIncomingConstraints(long);
+    property public final androidx.compose.ui.unit.Density density;
+    property @Deprecated public final androidx.compose.ui.unit.LayoutDirection layoutDirection;
+    property public final long rootIncomingConstraints;
+  }
+
+  @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public final class SwipeDirection {
+    method public String getName();
+    property public final String name;
+    field public static final androidx.constraintlayout.compose.SwipeDirection.Companion Companion;
+  }
+
+  public static final class SwipeDirection.Companion {
+    method public androidx.constraintlayout.compose.SwipeDirection getClockwise();
+    method public androidx.constraintlayout.compose.SwipeDirection getCounterclockwise();
+    method public androidx.constraintlayout.compose.SwipeDirection getDown();
+    method public androidx.constraintlayout.compose.SwipeDirection getEnd();
+    method public androidx.constraintlayout.compose.SwipeDirection getLeft();
+    method public androidx.constraintlayout.compose.SwipeDirection getRight();
+    method public androidx.constraintlayout.compose.SwipeDirection getStart();
+    method public androidx.constraintlayout.compose.SwipeDirection getUp();
+    property public final androidx.constraintlayout.compose.SwipeDirection Clockwise;
+    property public final androidx.constraintlayout.compose.SwipeDirection Counterclockwise;
+    property public final androidx.constraintlayout.compose.SwipeDirection Down;
+    property public final androidx.constraintlayout.compose.SwipeDirection End;
+    property public final androidx.constraintlayout.compose.SwipeDirection Left;
+    property public final androidx.constraintlayout.compose.SwipeDirection Right;
+    property public final androidx.constraintlayout.compose.SwipeDirection Start;
+    property public final androidx.constraintlayout.compose.SwipeDirection Up;
+  }
+
+  @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public final class SwipeMode {
+    method public String getName();
+    property public final String name;
+    field public static final androidx.constraintlayout.compose.SwipeMode.Companion Companion;
+  }
+
+  public static final class SwipeMode.Companion {
+    method public androidx.constraintlayout.compose.SwipeMode getSpring();
+    method public androidx.constraintlayout.compose.SwipeMode getVelocity();
+    method public androidx.constraintlayout.compose.SwipeMode spring(optional float mass, optional float stiffness, optional float damping, optional float threshold, optional androidx.constraintlayout.compose.SpringBoundary boundary);
+    method public androidx.constraintlayout.compose.SwipeMode velocity(optional float maxVelocity, optional float maxAcceleration);
+    property public final androidx.constraintlayout.compose.SwipeMode Spring;
+    property public final androidx.constraintlayout.compose.SwipeMode Velocity;
+  }
+
+  @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public final class SwipeSide {
+    method public String getName();
+    property public final String name;
+    field public static final androidx.constraintlayout.compose.SwipeSide.Companion Companion;
+  }
+
+  public static final class SwipeSide.Companion {
+    method public androidx.constraintlayout.compose.SwipeSide getBottom();
+    method public androidx.constraintlayout.compose.SwipeSide getEnd();
+    method public androidx.constraintlayout.compose.SwipeSide getLeft();
+    method public androidx.constraintlayout.compose.SwipeSide getMiddle();
+    method public androidx.constraintlayout.compose.SwipeSide getRight();
+    method public androidx.constraintlayout.compose.SwipeSide getStart();
+    method public androidx.constraintlayout.compose.SwipeSide getTop();
+    property public final androidx.constraintlayout.compose.SwipeSide Bottom;
+    property public final androidx.constraintlayout.compose.SwipeSide End;
+    property public final androidx.constraintlayout.compose.SwipeSide Left;
+    property public final androidx.constraintlayout.compose.SwipeSide Middle;
+    property public final androidx.constraintlayout.compose.SwipeSide Right;
+    property public final androidx.constraintlayout.compose.SwipeSide Start;
+    property public final androidx.constraintlayout.compose.SwipeSide Top;
+  }
+
+  @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public final class SwipeTouchUp {
+    method public String getName();
+    property public final String name;
+    field public static final androidx.constraintlayout.compose.SwipeTouchUp.Companion Companion;
+  }
+
+  public static final class SwipeTouchUp.Companion {
+    method public androidx.constraintlayout.compose.SwipeTouchUp getAutoComplete();
+    method public androidx.constraintlayout.compose.SwipeTouchUp getDecelerate();
+    method public androidx.constraintlayout.compose.SwipeTouchUp getNeverCompleteEnd();
+    method public androidx.constraintlayout.compose.SwipeTouchUp getNeverCompleteStart();
+    method public androidx.constraintlayout.compose.SwipeTouchUp getStop();
+    method public androidx.constraintlayout.compose.SwipeTouchUp getToEnd();
+    method public androidx.constraintlayout.compose.SwipeTouchUp getToStart();
+    property public final androidx.constraintlayout.compose.SwipeTouchUp AutoComplete;
+    property public final androidx.constraintlayout.compose.SwipeTouchUp Decelerate;
+    property public final androidx.constraintlayout.compose.SwipeTouchUp NeverCompleteEnd;
+    property public final androidx.constraintlayout.compose.SwipeTouchUp NeverCompleteStart;
+    property public final androidx.constraintlayout.compose.SwipeTouchUp Stop;
+    property public final androidx.constraintlayout.compose.SwipeTouchUp ToEnd;
+    property public final androidx.constraintlayout.compose.SwipeTouchUp ToStart;
+  }
+
+  public final class ToolingUtilsKt {
+    method public static androidx.compose.ui.semantics.SemanticsPropertyKey<androidx.constraintlayout.compose.DesignInfoProvider> getDesignInfoDataKey();
+    property public static final androidx.compose.ui.semantics.SemanticsPropertyKey<androidx.constraintlayout.compose.DesignInfoProvider> DesignInfoDataKey;
+  }
+
+  @SuppressCompatibility @androidx.compose.runtime.Immutable @androidx.constraintlayout.compose.ExperimentalMotionApi public interface Transition {
+    method public String getEndConstraintSetId();
+    method public String getStartConstraintSetId();
+  }
+
+  public final class TransitionKt {
+    method @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public static androidx.constraintlayout.compose.Transition Transition(@org.intellij.lang.annotations.Language("json5") String content);
+  }
+
+  @SuppressCompatibility @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.constraintlayout.compose.ExperimentalMotionApi public final class TransitionScope {
+    method public androidx.constraintlayout.compose.ConstrainedLayoutReference createRefFor(Object id);
+    method public float getMaxStaggerDelay();
+    method public androidx.constraintlayout.compose.Arc getMotionArc();
+    method public androidx.constraintlayout.compose.OnSwipe? getOnSwipe();
+    method public void keyAttributes(androidx.constraintlayout.compose.ConstrainedLayoutReference[] targets, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.KeyAttributesScope,kotlin.Unit> keyAttributesContent);
+    method public void keyCycles(androidx.constraintlayout.compose.ConstrainedLayoutReference[] targets, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.KeyCyclesScope,kotlin.Unit> keyCyclesContent);
+    method public void keyPositions(androidx.constraintlayout.compose.ConstrainedLayoutReference[] targets, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.KeyPositionsScope,kotlin.Unit> keyPositionsContent);
+    method public void setMaxStaggerDelay(float);
+    method public void setMotionArc(androidx.constraintlayout.compose.Arc);
+    method public void setOnSwipe(androidx.constraintlayout.compose.OnSwipe?);
+    property public final float maxStaggerDelay;
+    property public final androidx.constraintlayout.compose.Arc motionArc;
+    property public final androidx.constraintlayout.compose.OnSwipe? onSwipe;
+  }
+
+  public final class TransitionScopeKt {
+    method @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public static androidx.constraintlayout.compose.Transition Transition(optional String from, optional String to, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.TransitionScope,kotlin.Unit> content);
+  }
+
+  @androidx.compose.runtime.Immutable public final class VerticalAlign {
+    field public static final androidx.constraintlayout.compose.VerticalAlign.Companion Companion;
+  }
+
+  public static final class VerticalAlign.Companion {
+    method public androidx.constraintlayout.compose.VerticalAlign getBaseline();
+    method public androidx.constraintlayout.compose.VerticalAlign getBottom();
+    method public androidx.constraintlayout.compose.VerticalAlign getCenter();
+    method public androidx.constraintlayout.compose.VerticalAlign getTop();
+    property public final androidx.constraintlayout.compose.VerticalAlign Baseline;
+    property public final androidx.constraintlayout.compose.VerticalAlign Bottom;
+    property public final androidx.constraintlayout.compose.VerticalAlign Center;
+    property public final androidx.constraintlayout.compose.VerticalAlign Top;
+  }
+
+  @kotlin.jvm.JvmDefaultWithCompatibility public interface VerticalAnchorable {
+    method public void linkTo(androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor anchor, optional float margin, optional float goneMargin);
+  }
+
+  @androidx.compose.runtime.Stable public final class VerticalChainReference extends androidx.constraintlayout.compose.LayoutReference {
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor getBottom();
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor getTop();
+    property public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor bottom;
+    property public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor top;
+  }
+
+  @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Stable public final class VerticalChainScope {
+    method public androidx.constraintlayout.compose.HorizontalAnchorable getBottom();
+    method public androidx.constraintlayout.compose.ConstrainedLayoutReference getParent();
+    method public androidx.constraintlayout.compose.HorizontalAnchorable getTop();
+    property public final androidx.constraintlayout.compose.HorizontalAnchorable bottom;
+    property public final androidx.constraintlayout.compose.ConstrainedLayoutReference parent;
+    property public final androidx.constraintlayout.compose.HorizontalAnchorable top;
+  }
+
+  @androidx.compose.runtime.Immutable public final class Visibility {
+    field public static final androidx.constraintlayout.compose.Visibility.Companion Companion;
+  }
+
+  public static final class Visibility.Companion {
+    method public androidx.constraintlayout.compose.Visibility getGone();
+    method public androidx.constraintlayout.compose.Visibility getInvisible();
+    method public androidx.constraintlayout.compose.Visibility getVisible();
+    property public final androidx.constraintlayout.compose.Visibility Gone;
+    property public final androidx.constraintlayout.compose.Visibility Invisible;
+    property public final androidx.constraintlayout.compose.Visibility Visible;
+  }
+
+  @androidx.compose.runtime.Immutable public final class Wrap {
+    field public static final androidx.constraintlayout.compose.Wrap.Companion Companion;
+  }
+
+  public static final class Wrap.Companion {
+    method public androidx.constraintlayout.compose.Wrap getAligned();
+    method public androidx.constraintlayout.compose.Wrap getChain();
+    method public androidx.constraintlayout.compose.Wrap getNone();
+    property public final androidx.constraintlayout.compose.Wrap Aligned;
+    property public final androidx.constraintlayout.compose.Wrap Chain;
+    property public final androidx.constraintlayout.compose.Wrap None;
+  }
+
+}
+
diff --git a/constraintlayout/constraintlayout-compose/api/current.txt b/constraintlayout/constraintlayout-compose/api/current.txt
index 8d66405..0375873 100644
--- a/constraintlayout/constraintlayout-compose/api/current.txt
+++ b/constraintlayout/constraintlayout-compose/api/current.txt
@@ -170,15 +170,12 @@
     method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createAbsoluteLeftBarrier(androidx.constraintlayout.compose.LayoutReference[] elements, optional float margin);
     method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createAbsoluteRightBarrier(androidx.constraintlayout.compose.LayoutReference[] elements, optional float margin);
     method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor createBottomBarrier(androidx.constraintlayout.compose.LayoutReference[] elements, optional float margin);
-    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createColumn(androidx.constraintlayout.compose.LayoutReference[] elements, optional androidx.constraintlayout.compose.Skip[] skips, optional androidx.constraintlayout.compose.Span[] spans, optional float verticalGap, optional int[] rowWeights, optional float paddingHorizontal, optional float paddingVertical);
-    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createColumn(androidx.constraintlayout.compose.LayoutReference[] elements, optional androidx.constraintlayout.compose.Skip[] skips, optional androidx.constraintlayout.compose.Span[] spans, optional int[] rowWeights, optional float verticalGap, optional float padding);
+    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createColumn(androidx.constraintlayout.compose.LayoutReference[] elements, optional float spacing, optional float[] weights);
     method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createEndBarrier(androidx.constraintlayout.compose.LayoutReference[] elements, optional float margin);
     method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createFlow(androidx.constraintlayout.compose.LayoutReference?[] elements, optional boolean flowVertically, optional float verticalGap, optional float horizontalGap, optional int maxElement, optional float padding, optional androidx.constraintlayout.compose.Wrap wrapMode, optional androidx.constraintlayout.compose.VerticalAlign verticalAlign, optional androidx.constraintlayout.compose.HorizontalAlign horizontalAlign, optional float horizontalFlowBias, optional float verticalFlowBias, optional androidx.constraintlayout.compose.FlowStyle verticalStyle, optional androidx.constraintlayout.compose.FlowStyle horizontalStyle);
     method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createFlow(androidx.constraintlayout.compose.LayoutReference?[] elements, optional boolean flowVertically, optional float verticalGap, optional float horizontalGap, optional int maxElement, optional float paddingHorizontal, optional float paddingVertical, optional androidx.constraintlayout.compose.Wrap wrapMode, optional androidx.constraintlayout.compose.VerticalAlign verticalAlign, optional androidx.constraintlayout.compose.HorizontalAlign horizontalAlign, optional float horizontalFlowBias, optional float verticalFlowBias, optional androidx.constraintlayout.compose.FlowStyle verticalStyle, optional androidx.constraintlayout.compose.FlowStyle horizontalStyle);
     method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createFlow(androidx.constraintlayout.compose.LayoutReference?[] elements, optional boolean flowVertically, optional float verticalGap, optional float horizontalGap, optional int maxElement, optional float paddingLeft, optional float paddingTop, optional float paddingRight, optional float paddingBottom, optional androidx.constraintlayout.compose.Wrap wrapMode, optional androidx.constraintlayout.compose.VerticalAlign verticalAlign, optional androidx.constraintlayout.compose.HorizontalAlign horizontalAlign, optional float horizontalFlowBias, optional float verticalFlowBias, optional androidx.constraintlayout.compose.FlowStyle verticalStyle, optional androidx.constraintlayout.compose.FlowStyle horizontalStyle);
-    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createGrid(androidx.constraintlayout.compose.LayoutReference[] elements, optional int orientation, optional int rows, optional int columns, optional float verticalGap, optional float horizontalGap, optional int[] rowWeights, optional int[] columnWeights, optional androidx.constraintlayout.compose.Skip[] skips, optional androidx.constraintlayout.compose.Span[] spans, optional float padding, optional androidx.constraintlayout.compose.GridFlag[] flags);
-    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createGrid(androidx.constraintlayout.compose.LayoutReference[] elements, optional int orientation, optional int rows, optional int columns, optional float verticalGap, optional float horizontalGap, optional int[] rowWeights, optional int[] columnWeights, optional androidx.constraintlayout.compose.Skip[] skips, optional androidx.constraintlayout.compose.Span[] spans, optional float paddingHorizontal, optional float paddingVertical, optional androidx.constraintlayout.compose.GridFlag[] flags);
-    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createGrid(androidx.constraintlayout.compose.LayoutReference[] elements, optional int orientation, optional int rows, optional int columns, optional float verticalGap, optional float horizontalGap, optional int[] rowWeights, optional int[] columnWeights, optional androidx.constraintlayout.compose.Skip[] skips, optional androidx.constraintlayout.compose.Span[] spans, optional float paddingStart, optional float paddingTop, optional float paddingEnd, optional float paddingBottom, optional androidx.constraintlayout.compose.GridFlag[] flags);
+    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createGrid(androidx.constraintlayout.compose.LayoutReference[] elements, @IntRange(from=1L) int rows, @IntRange(from=1L) int columns, optional boolean isHorizontalArrangement, optional float verticalSpacing, optional float horizontalSpacing, optional float[] rowWeights, optional float[] columnWeights, optional androidx.constraintlayout.compose.Skip[] skips, optional androidx.constraintlayout.compose.Span[] spans, optional int flags);
     method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteLeft(float offset);
     method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteLeft(float fraction);
     method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteRight(float offset);
@@ -192,8 +189,7 @@
     method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromTop(float offset);
     method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromTop(float fraction);
     method public final androidx.constraintlayout.compose.HorizontalChainReference createHorizontalChain(androidx.constraintlayout.compose.LayoutReference[] elements, optional androidx.constraintlayout.compose.ChainStyle chainStyle);
-    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createRow(androidx.constraintlayout.compose.LayoutReference[] elements, optional androidx.constraintlayout.compose.Skip[] skips, optional androidx.constraintlayout.compose.Span[] spans, optional float horizontalGap, optional int[] columnWeights, optional float padding);
-    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createRow(androidx.constraintlayout.compose.LayoutReference[] elements, optional androidx.constraintlayout.compose.Skip[] skips, optional androidx.constraintlayout.compose.Span[] spans, optional float horizontalGap, optional int[] columnWeights, optional float paddingHorizontal, optional float paddingVertical);
+    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createRow(androidx.constraintlayout.compose.LayoutReference[] elements, optional float spacing, optional float[] weights);
     method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createStartBarrier(androidx.constraintlayout.compose.LayoutReference[] elements, optional float margin);
     method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor createTopBarrier(androidx.constraintlayout.compose.LayoutReference[] elements, optional float margin);
     method public final androidx.constraintlayout.compose.VerticalChainReference createVerticalChain(androidx.constraintlayout.compose.LayoutReference[] elements, optional androidx.constraintlayout.compose.ChainStyle chainStyle);
@@ -429,15 +425,18 @@
     property public final androidx.constraintlayout.compose.FlowStyle SpreadInside;
   }
 
-  @androidx.compose.runtime.Immutable public final class GridFlag {
-    field public static final androidx.constraintlayout.compose.GridFlag.Companion Companion;
+  @kotlin.jvm.JvmInline public final value class GridFlags {
+    ctor public GridFlags(optional boolean isPlaceLayoutsOnSpansFirst);
+    method public boolean isPlaceLayoutsOnSpansFirst();
+    property public final boolean isPlaceLayoutsOnSpansFirst;
+    field public static final androidx.constraintlayout.compose.GridFlags.Companion Companion;
   }
 
-  public static final class GridFlag.Companion {
-    method public androidx.constraintlayout.compose.GridFlag getSpansRespectWidgetOrder();
-    method public androidx.constraintlayout.compose.GridFlag getSubGridByColRow();
-    property public final androidx.constraintlayout.compose.GridFlag SpansRespectWidgetOrder;
-    property public final androidx.constraintlayout.compose.GridFlag SubGridByColRow;
+  public static final class GridFlags.Companion {
+    method public int getNone();
+    method public int getPlaceLayoutsOnSpansFirst();
+    property public final int None;
+    property public final int PlaceLayoutsOnSpansFirst;
   }
 
   @androidx.compose.runtime.Immutable public final class HorizontalAlign {
@@ -786,16 +785,15 @@
   }
 
   @kotlin.jvm.JvmInline public final value class Skip {
-    ctor public Skip(int position, int size);
-    ctor public Skip(int position, int rows, int columns);
-    ctor public Skip(String description);
+    ctor public Skip(@IntRange(from=0L) int position, @IntRange(from=1L) int size);
+    ctor public Skip(@IntRange(from=0L) int position, @IntRange(from=1L) int rows, @IntRange(from=1L) int columns);
     method public String getDescription();
     property public final String description;
   }
 
   @kotlin.jvm.JvmInline public final value class Span {
-    ctor public Span(int position, int size);
-    ctor public Span(int position, int rows, int columns);
+    ctor public Span(@IntRange(from=0L) int position, @IntRange(from=1L) int size);
+    ctor public Span(@IntRange(from=0L) int position, @IntRange(from=1L) int rows, @IntRange(from=1L) int columns);
     ctor public Span(String description);
     method public String getDescription();
     property public final String description;
diff --git a/constraintlayout/constraintlayout-compose/api/res-1.1.0-beta01.txt b/constraintlayout/constraintlayout-compose/api/res-1.1.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/constraintlayout/constraintlayout-compose/api/res-1.1.0-beta01.txt
diff --git a/constraintlayout/constraintlayout-compose/api/restricted_1.1.0-beta01.txt b/constraintlayout/constraintlayout-compose/api/restricted_1.1.0-beta01.txt
new file mode 100644
index 0000000..60bc75d
--- /dev/null
+++ b/constraintlayout/constraintlayout-compose/api/restricted_1.1.0-beta01.txt
@@ -0,0 +1,1103 @@
+// Signature format: 4.0
+package androidx.constraintlayout.compose {
+
+  @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public final class Arc {
+    method public String getName();
+    property public final String name;
+    field public static final androidx.constraintlayout.compose.Arc.Companion Companion;
+  }
+
+  public static final class Arc.Companion {
+    method public androidx.constraintlayout.compose.Arc getAbove();
+    method public androidx.constraintlayout.compose.Arc getBelow();
+    method public androidx.constraintlayout.compose.Arc getFlip();
+    method public androidx.constraintlayout.compose.Arc getNone();
+    method public androidx.constraintlayout.compose.Arc getStartHorizontal();
+    method public androidx.constraintlayout.compose.Arc getStartVertical();
+    property public final androidx.constraintlayout.compose.Arc Above;
+    property public final androidx.constraintlayout.compose.Arc Below;
+    property public final androidx.constraintlayout.compose.Arc Flip;
+    property public final androidx.constraintlayout.compose.Arc None;
+    property public final androidx.constraintlayout.compose.Arc StartHorizontal;
+    property public final androidx.constraintlayout.compose.Arc StartVertical;
+  }
+
+  @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public abstract sealed class BaseKeyFrameScope {
+    method protected final <E extends androidx.constraintlayout.compose.NamedPropertyOrValue> kotlin.properties.ObservableProperty<E> addNameOnPropertyChange(E initialValue, optional String? nameOverride);
+    method protected final <T> kotlin.properties.ObservableProperty<T> addOnPropertyChange(T initialValue, optional String? nameOverride);
+  }
+
+  @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public abstract sealed class BaseKeyFramesScope {
+    method public final androidx.constraintlayout.compose.Easing getEasing();
+    method public final void setEasing(androidx.constraintlayout.compose.Easing);
+    property public final androidx.constraintlayout.compose.Easing easing;
+  }
+
+  @kotlin.jvm.JvmDefaultWithCompatibility public interface BaselineAnchorable {
+    method public void linkTo(androidx.constraintlayout.compose.ConstraintLayoutBaseScope.BaselineAnchor anchor, optional float margin, optional float goneMargin);
+    method public void linkTo(androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor anchor, optional float margin, optional float goneMargin);
+  }
+
+  @androidx.compose.runtime.Immutable public final class ChainStyle {
+    field public static final androidx.constraintlayout.compose.ChainStyle.Companion Companion;
+  }
+
+  public static final class ChainStyle.Companion {
+    method @androidx.compose.runtime.Stable public androidx.constraintlayout.compose.ChainStyle Packed(float bias);
+    method public androidx.constraintlayout.compose.ChainStyle getPacked();
+    method public androidx.constraintlayout.compose.ChainStyle getSpread();
+    method public androidx.constraintlayout.compose.ChainStyle getSpreadInside();
+    property public final androidx.constraintlayout.compose.ChainStyle Packed;
+    property public final androidx.constraintlayout.compose.ChainStyle Spread;
+    property public final androidx.constraintlayout.compose.ChainStyle SpreadInside;
+  }
+
+  @kotlin.PublishedApi internal enum CompositionSource {
+    enum_constant public static final androidx.constraintlayout.compose.CompositionSource Content;
+    enum_constant public static final androidx.constraintlayout.compose.CompositionSource Unknown;
+  }
+
+  @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Stable public final class ConstrainScope {
+    method public androidx.constraintlayout.compose.Dimension asDimension(float);
+    method public void centerAround(androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor anchor);
+    method public void centerAround(androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor anchor);
+    method public void centerHorizontallyTo(androidx.constraintlayout.compose.ConstrainedLayoutReference other, optional @FloatRange(from=0.0, to=1.0) float bias);
+    method public void centerTo(androidx.constraintlayout.compose.ConstrainedLayoutReference other);
+    method public void centerVerticallyTo(androidx.constraintlayout.compose.ConstrainedLayoutReference other, optional @FloatRange(from=0.0, to=1.0) float bias);
+    method public void circular(androidx.constraintlayout.compose.ConstrainedLayoutReference other, float angle, float distance);
+    method public void clearConstraints();
+    method public void clearHorizontal();
+    method public void clearVertical();
+    method public androidx.constraintlayout.compose.VerticalAnchorable getAbsoluteLeft();
+    method public androidx.constraintlayout.compose.VerticalAnchorable getAbsoluteRight();
+    method public float getAlpha();
+    method public androidx.constraintlayout.compose.BaselineAnchorable getBaseline();
+    method public androidx.constraintlayout.compose.HorizontalAnchorable getBottom();
+    method public androidx.constraintlayout.compose.VerticalAnchorable getEnd();
+    method public androidx.constraintlayout.compose.Dimension getHeight();
+    method public float getHorizontalBias();
+    method public float getHorizontalChainWeight();
+    method public androidx.constraintlayout.compose.ConstrainedLayoutReference getParent();
+    method public float getPivotX();
+    method public float getPivotY();
+    method public float getRotationX();
+    method public float getRotationY();
+    method public float getRotationZ();
+    method public float getScaleX();
+    method public float getScaleY();
+    method public androidx.constraintlayout.compose.VerticalAnchorable getStart();
+    method public androidx.constraintlayout.compose.HorizontalAnchorable getTop();
+    method public float getTranslationX();
+    method public float getTranslationY();
+    method public float getTranslationZ();
+    method public float getVerticalBias();
+    method public float getVerticalChainWeight();
+    method public androidx.constraintlayout.compose.Visibility getVisibility();
+    method public androidx.constraintlayout.compose.Dimension getWidth();
+    method public void linkTo(androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor top, androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor bottom, optional float topMargin, optional float bottomMargin, optional float topGoneMargin, optional float bottomGoneMargin, optional @FloatRange(from=0.0, to=1.0) float bias);
+    method public void linkTo(androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor start, androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor top, androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor end, androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor bottom, optional float startMargin, optional float topMargin, optional float endMargin, optional float bottomMargin, optional float startGoneMargin, optional float topGoneMargin, optional float endGoneMargin, optional float bottomGoneMargin, optional @FloatRange(from=0.0, to=1.0) float horizontalBias, optional @FloatRange(from=0.0, to=1.0) float verticalBias);
+    method public void linkTo(androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor start, androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor end, optional float startMargin, optional float endMargin, optional float startGoneMargin, optional float endGoneMargin, optional @FloatRange(from=0.0, to=1.0) float bias);
+    method public void resetDimensions();
+    method public void resetTransforms();
+    method public void setAlpha(float);
+    method public void setHeight(androidx.constraintlayout.compose.Dimension);
+    method public void setHorizontalBias(float);
+    method public void setHorizontalChainWeight(float);
+    method public void setPivotX(float);
+    method public void setPivotY(float);
+    method public void setRotationX(float);
+    method public void setRotationY(float);
+    method public void setRotationZ(float);
+    method public void setScaleX(float);
+    method public void setScaleY(float);
+    method public void setTranslationX(float);
+    method public void setTranslationY(float);
+    method public void setTranslationZ(float);
+    method public void setVerticalBias(float);
+    method public void setVerticalChainWeight(float);
+    method public void setVisibility(androidx.constraintlayout.compose.Visibility);
+    method public void setWidth(androidx.constraintlayout.compose.Dimension);
+    property public final androidx.constraintlayout.compose.VerticalAnchorable absoluteLeft;
+    property public final androidx.constraintlayout.compose.VerticalAnchorable absoluteRight;
+    property public final float alpha;
+    property public final androidx.constraintlayout.compose.BaselineAnchorable baseline;
+    property public final androidx.constraintlayout.compose.HorizontalAnchorable bottom;
+    property public final androidx.constraintlayout.compose.VerticalAnchorable end;
+    property public final androidx.constraintlayout.compose.Dimension height;
+    property public final float horizontalBias;
+    property public final float horizontalChainWeight;
+    property public final androidx.constraintlayout.compose.ConstrainedLayoutReference parent;
+    property public final float pivotX;
+    property public final float pivotY;
+    property public final float rotationX;
+    property public final float rotationY;
+    property public final float rotationZ;
+    property public final float scaleX;
+    property public final float scaleY;
+    property public final androidx.constraintlayout.compose.VerticalAnchorable start;
+    property public final androidx.constraintlayout.compose.HorizontalAnchorable top;
+    property public final float translationX;
+    property public final float translationY;
+    property public final float translationZ;
+    property public final float verticalBias;
+    property public final float verticalChainWeight;
+    property public final androidx.constraintlayout.compose.Visibility visibility;
+    property public final androidx.constraintlayout.compose.Dimension width;
+  }
+
+  @androidx.compose.runtime.Stable public final class ConstrainedLayoutReference extends androidx.constraintlayout.compose.LayoutReference {
+    ctor public ConstrainedLayoutReference(Object id);
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor getAbsoluteLeft();
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor getAbsoluteRight();
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.BaselineAnchor getBaseline();
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor getBottom();
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor getEnd();
+    method public Object getId();
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor getStart();
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor getTop();
+    property public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor absoluteLeft;
+    property public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor absoluteRight;
+    property public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.BaselineAnchor baseline;
+    property public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor bottom;
+    property public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor end;
+    property public Object id;
+    property public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor start;
+    property public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor top;
+  }
+
+  public abstract class ConstraintLayoutBaseScope {
+    ctor public ConstraintLayoutBaseScope();
+    method public final void applyTo(androidx.constraintlayout.compose.State state);
+    method public final androidx.constraintlayout.compose.ConstrainScope constrain(androidx.constraintlayout.compose.ConstrainedLayoutReference ref, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.ConstrainScope,kotlin.Unit> constrainBlock);
+    method public final void constrain(androidx.constraintlayout.compose.ConstrainedLayoutReference[] refs, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.ConstrainScope,kotlin.Unit> constrainBlock);
+    method public final androidx.constraintlayout.compose.HorizontalChainScope constrain(androidx.constraintlayout.compose.HorizontalChainReference ref, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.HorizontalChainScope,kotlin.Unit> constrainBlock);
+    method public final androidx.constraintlayout.compose.VerticalChainScope constrain(androidx.constraintlayout.compose.VerticalChainReference ref, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.VerticalChainScope,kotlin.Unit> constrainBlock);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createAbsoluteLeftBarrier(androidx.constraintlayout.compose.LayoutReference[] elements, optional float margin);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createAbsoluteRightBarrier(androidx.constraintlayout.compose.LayoutReference[] elements, optional float margin);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor createBottomBarrier(androidx.constraintlayout.compose.LayoutReference[] elements, optional float margin);
+    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createColumn(androidx.constraintlayout.compose.LayoutReference[] elements, optional float spacing, optional float[] weights);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createEndBarrier(androidx.constraintlayout.compose.LayoutReference[] elements, optional float margin);
+    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createFlow(androidx.constraintlayout.compose.LayoutReference?[] elements, optional boolean flowVertically, optional float verticalGap, optional float horizontalGap, optional int maxElement, optional float padding, optional androidx.constraintlayout.compose.Wrap wrapMode, optional androidx.constraintlayout.compose.VerticalAlign verticalAlign, optional androidx.constraintlayout.compose.HorizontalAlign horizontalAlign, optional float horizontalFlowBias, optional float verticalFlowBias, optional androidx.constraintlayout.compose.FlowStyle verticalStyle, optional androidx.constraintlayout.compose.FlowStyle horizontalStyle);
+    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createFlow(androidx.constraintlayout.compose.LayoutReference?[] elements, optional boolean flowVertically, optional float verticalGap, optional float horizontalGap, optional int maxElement, optional float paddingHorizontal, optional float paddingVertical, optional androidx.constraintlayout.compose.Wrap wrapMode, optional androidx.constraintlayout.compose.VerticalAlign verticalAlign, optional androidx.constraintlayout.compose.HorizontalAlign horizontalAlign, optional float horizontalFlowBias, optional float verticalFlowBias, optional androidx.constraintlayout.compose.FlowStyle verticalStyle, optional androidx.constraintlayout.compose.FlowStyle horizontalStyle);
+    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createFlow(androidx.constraintlayout.compose.LayoutReference?[] elements, optional boolean flowVertically, optional float verticalGap, optional float horizontalGap, optional int maxElement, optional float paddingLeft, optional float paddingTop, optional float paddingRight, optional float paddingBottom, optional androidx.constraintlayout.compose.Wrap wrapMode, optional androidx.constraintlayout.compose.VerticalAlign verticalAlign, optional androidx.constraintlayout.compose.HorizontalAlign horizontalAlign, optional float horizontalFlowBias, optional float verticalFlowBias, optional androidx.constraintlayout.compose.FlowStyle verticalStyle, optional androidx.constraintlayout.compose.FlowStyle horizontalStyle);
+    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createGrid(androidx.constraintlayout.compose.LayoutReference[] elements, @IntRange(from=1L) int rows, @IntRange(from=1L) int columns, optional boolean isHorizontalArrangement, optional float verticalSpacing, optional float horizontalSpacing, optional float[] rowWeights, optional float[] columnWeights, optional androidx.constraintlayout.compose.Skip[] skips, optional androidx.constraintlayout.compose.Span[] spans, optional int flags);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteLeft(float offset);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteLeft(float fraction);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteRight(float offset);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteRight(float fraction);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromBottom(float offset);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromBottom(float fraction);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromEnd(float offset);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromEnd(float fraction);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromStart(float offset);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromStart(float fraction);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromTop(float offset);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromTop(float fraction);
+    method public final androidx.constraintlayout.compose.HorizontalChainReference createHorizontalChain(androidx.constraintlayout.compose.LayoutReference[] elements, optional androidx.constraintlayout.compose.ChainStyle chainStyle);
+    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createRow(androidx.constraintlayout.compose.LayoutReference[] elements, optional float spacing, optional float[] weights);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createStartBarrier(androidx.constraintlayout.compose.LayoutReference[] elements, optional float margin);
+    method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor createTopBarrier(androidx.constraintlayout.compose.LayoutReference[] elements, optional float margin);
+    method public final androidx.constraintlayout.compose.VerticalChainReference createVerticalChain(androidx.constraintlayout.compose.LayoutReference[] elements, optional androidx.constraintlayout.compose.ChainStyle chainStyle);
+    method @Deprecated protected final java.util.List<kotlin.jvm.functions.Function1<androidx.constraintlayout.compose.State,kotlin.Unit>> getTasks();
+    method public void reset();
+    method public final androidx.constraintlayout.compose.LayoutReference withChainParams(androidx.constraintlayout.compose.LayoutReference, optional float startMargin, optional float topMargin, optional float endMargin, optional float bottomMargin, optional float startGoneMargin, optional float topGoneMargin, optional float endGoneMargin, optional float bottomGoneMargin, optional float weight);
+    method public final androidx.constraintlayout.compose.LayoutReference withHorizontalChainParams(androidx.constraintlayout.compose.LayoutReference, optional float startMargin, optional float endMargin, optional float startGoneMargin, optional float endGoneMargin, optional float weight);
+    method public final androidx.constraintlayout.compose.LayoutReference withVerticalChainParams(androidx.constraintlayout.compose.LayoutReference, optional float topMargin, optional float bottomMargin, optional float topGoneMargin, optional float bottomGoneMargin, optional float weight);
+    property @Deprecated protected final java.util.List<kotlin.jvm.functions.Function1<androidx.constraintlayout.compose.State,kotlin.Unit>> tasks;
+    field @kotlin.PublishedApi internal final androidx.constraintlayout.core.parser.CLObject containerObject;
+    field @kotlin.PublishedApi internal int helpersHashCode;
+  }
+
+  @androidx.compose.runtime.Stable public static final class ConstraintLayoutBaseScope.BaselineAnchor {
+    method public androidx.constraintlayout.compose.LayoutReference component2();
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.BaselineAnchor copy(Object id, androidx.constraintlayout.compose.LayoutReference reference);
+    method public androidx.constraintlayout.compose.LayoutReference getReference();
+    property public final androidx.constraintlayout.compose.LayoutReference reference;
+  }
+
+  @androidx.compose.runtime.Stable public static final class ConstraintLayoutBaseScope.HorizontalAnchor {
+    method public androidx.constraintlayout.compose.LayoutReference component3();
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor copy(Object id, int index, androidx.constraintlayout.compose.LayoutReference reference);
+    method public androidx.constraintlayout.compose.LayoutReference getReference();
+    property public final androidx.constraintlayout.compose.LayoutReference reference;
+  }
+
+  @androidx.compose.runtime.Stable public static final class ConstraintLayoutBaseScope.VerticalAnchor {
+    method public androidx.constraintlayout.compose.LayoutReference component3();
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor copy(Object id, int index, androidx.constraintlayout.compose.LayoutReference reference);
+    method public androidx.constraintlayout.compose.LayoutReference getReference();
+    property public final androidx.constraintlayout.compose.LayoutReference reference;
+  }
+
+  public final class ConstraintLayoutKt {
+    method @androidx.compose.runtime.Composable public static inline void ConstraintLayout(optional androidx.compose.ui.Modifier modifier, optional int optimizationLevel, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float>? animateChangesSpec, optional kotlin.jvm.functions.Function0<kotlin.Unit>? finishedAnimationListener, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.ConstraintLayoutScope,kotlin.Unit> content);
+    method @Deprecated @androidx.compose.runtime.Composable public static inline void ConstraintLayout(optional androidx.compose.ui.Modifier modifier, optional int optimizationLevel, optional boolean animateChanges, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> animationSpec, optional kotlin.jvm.functions.Function0<kotlin.Unit>? finishedAnimationListener, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.ConstraintLayoutScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static inline void ConstraintLayout(androidx.constraintlayout.compose.ConstraintSet constraintSet, optional androidx.compose.ui.Modifier modifier, optional int optimizationLevel, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float>? animateChangesSpec, optional kotlin.jvm.functions.Function0<kotlin.Unit>? finishedAnimationListener, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @Deprecated @androidx.compose.runtime.Composable public static inline void ConstraintLayout(androidx.constraintlayout.compose.ConstraintSet constraintSet, optional androidx.compose.ui.Modifier modifier, optional int optimizationLevel, optional boolean animateChanges, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> animationSpec, optional kotlin.jvm.functions.Function0<kotlin.Unit>? finishedAnimationListener, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method public static androidx.constraintlayout.compose.ConstraintSet ConstraintSet(androidx.constraintlayout.compose.ConstraintSet extendConstraintSet, @org.intellij.lang.annotations.Language("json5") String jsonContent);
+    method public static androidx.constraintlayout.compose.ConstraintSet ConstraintSet(androidx.constraintlayout.compose.ConstraintSet extendConstraintSet, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.ConstraintSetScope,kotlin.Unit> description);
+    method public static androidx.constraintlayout.compose.ConstraintSet ConstraintSet(@org.intellij.lang.annotations.Language("json5") String jsonContent);
+    method @androidx.compose.runtime.Composable public static androidx.constraintlayout.compose.ConstraintSet ConstraintSet(@org.intellij.lang.annotations.Language("json5") String content, optional @org.intellij.lang.annotations.Language("json5") String? overrideVariables);
+    method public static androidx.constraintlayout.compose.ConstraintSet ConstraintSet(kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.ConstraintSetScope,kotlin.Unit> description);
+    method public static androidx.constraintlayout.compose.Dimension.MaxCoercible atLeast(androidx.constraintlayout.compose.Dimension.Coercible, float dp);
+    method public static androidx.constraintlayout.compose.Dimension atLeast(androidx.constraintlayout.compose.Dimension.MinCoercible, float dp);
+    method @Deprecated public static androidx.constraintlayout.compose.Dimension atLeastWrapContent(androidx.constraintlayout.compose.Dimension.MinCoercible, float dp);
+    method public static androidx.constraintlayout.compose.Dimension.MinCoercible atMost(androidx.constraintlayout.compose.Dimension.Coercible, float dp);
+    method public static androidx.constraintlayout.compose.Dimension atMost(androidx.constraintlayout.compose.Dimension.MaxCoercible, float dp);
+    method public static androidx.constraintlayout.compose.Dimension.MaxCoercible getAtLeastWrapContent(androidx.constraintlayout.compose.Dimension.Coercible);
+    method public static androidx.constraintlayout.compose.Dimension getAtLeastWrapContent(androidx.constraintlayout.compose.Dimension.MinCoercible);
+    method public static androidx.constraintlayout.compose.Dimension.MinCoercible getAtMostWrapContent(androidx.constraintlayout.compose.Dimension.Coercible);
+    method public static androidx.constraintlayout.compose.Dimension getAtMostWrapContent(androidx.constraintlayout.compose.Dimension.MaxCoercible);
+  }
+
+  @androidx.compose.foundation.layout.LayoutScopeMarker public final class ConstraintLayoutScope extends androidx.constraintlayout.compose.ConstraintLayoutBaseScope {
+    ctor @kotlin.PublishedApi internal ConstraintLayoutScope();
+    method @androidx.compose.runtime.Stable public androidx.compose.ui.Modifier constrainAs(androidx.compose.ui.Modifier, androidx.constraintlayout.compose.ConstrainedLayoutReference ref, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.ConstrainScope,kotlin.Unit> constrainBlock);
+    method public androidx.constraintlayout.compose.ConstrainedLayoutReference createRef();
+    method @androidx.compose.runtime.Stable public androidx.constraintlayout.compose.ConstraintLayoutScope.ConstrainedLayoutReferences createRefs();
+    field @kotlin.PublishedApi internal boolean isAnimateChanges;
+  }
+
+  public final class ConstraintLayoutScope.ConstrainedLayoutReferences {
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component1();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component10();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component11();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component12();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component13();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component14();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component15();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component16();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component2();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component3();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component4();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component5();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component6();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component7();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component8();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component9();
+  }
+
+  public final class ConstraintLayoutTagKt {
+    method public static Object? getConstraintLayoutId(androidx.compose.ui.layout.Measurable);
+    method public static Object? getConstraintLayoutTag(androidx.compose.ui.layout.Measurable);
+    method public static androidx.compose.ui.Modifier layoutId(androidx.compose.ui.Modifier, String layoutId, optional String? tag);
+  }
+
+  public interface ConstraintLayoutTagParentData {
+    method public String getConstraintLayoutId();
+    method public String getConstraintLayoutTag();
+    property public abstract String constraintLayoutId;
+    property public abstract String constraintLayoutTag;
+  }
+
+  @androidx.compose.runtime.Immutable @kotlin.jvm.JvmDefaultWithCompatibility public interface ConstraintSet {
+    method public void applyTo(androidx.constraintlayout.compose.State state, java.util.List<? extends androidx.compose.ui.layout.Measurable> measurables);
+    method public default void applyTo(androidx.constraintlayout.core.state.Transition transition, int type);
+    method public default boolean isDirty(java.util.List<? extends androidx.compose.ui.layout.Measurable> measurables);
+    method public default androidx.constraintlayout.compose.ConstraintSet override(String name, float value);
+  }
+
+  @kotlin.PublishedApi internal final class ConstraintSetForInlineDsl implements androidx.constraintlayout.compose.ConstraintSet androidx.compose.runtime.RememberObserver {
+    ctor public ConstraintSetForInlineDsl(androidx.constraintlayout.compose.ConstraintLayoutScope scope);
+    method public void applyTo(androidx.constraintlayout.compose.State state, java.util.List<? extends androidx.compose.ui.layout.Measurable> measurables);
+    method public boolean getKnownDirty();
+    method public androidx.constraintlayout.compose.ConstraintLayoutScope getScope();
+    method public void onAbandoned();
+    method public void onForgotten();
+    method public void onRemembered();
+    method public void setKnownDirty(boolean);
+    property public final boolean knownDirty;
+    property public final androidx.constraintlayout.compose.ConstraintLayoutScope scope;
+  }
+
+  public final class ConstraintSetRef {
+    method public androidx.constraintlayout.compose.ConstraintSetRef copy(String name);
+  }
+
+  @androidx.compose.foundation.layout.LayoutScopeMarker public final class ConstraintSetScope extends androidx.constraintlayout.compose.ConstraintLayoutBaseScope {
+    method public androidx.constraintlayout.compose.ConstrainedLayoutReference createRefFor(Object id);
+    method public androidx.constraintlayout.compose.ConstraintSetScope.ConstrainedLayoutReferences createRefsFor(java.lang.Object... ids);
+  }
+
+  public final class ConstraintSetScope.ConstrainedLayoutReferences {
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component1();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component10();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component11();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component12();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component13();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component14();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component15();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component16();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component2();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component3();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component4();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component5();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component6();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component7();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component8();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component9();
+  }
+
+  @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public final class CurveFit {
+    method public String getName();
+    property public String name;
+    field public static final androidx.constraintlayout.compose.CurveFit.Companion Companion;
+  }
+
+  public static final class CurveFit.Companion {
+    method public androidx.constraintlayout.compose.CurveFit getLinear();
+    method public androidx.constraintlayout.compose.CurveFit getSpline();
+    property public final androidx.constraintlayout.compose.CurveFit Linear;
+    property public final androidx.constraintlayout.compose.CurveFit Spline;
+  }
+
+  @kotlin.jvm.JvmInline public final value class DebugFlags {
+    ctor public DebugFlags(optional boolean showBounds, optional boolean showPaths, optional boolean showKeyPositions);
+    method public boolean getShowBounds();
+    method public boolean getShowKeyPositions();
+    method public boolean getShowPaths();
+    property public final boolean showBounds;
+    property public final boolean showKeyPositions;
+    property public final boolean showPaths;
+    field public static final androidx.constraintlayout.compose.DebugFlags.Companion Companion;
+  }
+
+  public static final class DebugFlags.Companion {
+    method public int getAll();
+    method public int getNone();
+    property public final int All;
+    property public final int None;
+  }
+
+  public final class DesignElements {
+    method public void define(String name, kotlin.jvm.functions.Function2<? super java.lang.String,? super java.util.HashMap<java.lang.String,java.lang.String>,kotlin.Unit> function);
+    method public java.util.HashMap<java.lang.String,kotlin.jvm.functions.Function2<java.lang.String,java.util.HashMap<java.lang.String,java.lang.String>,kotlin.Unit>> getMap();
+    method public void setMap(java.util.HashMap<java.lang.String,kotlin.jvm.functions.Function2<java.lang.String,java.util.HashMap<java.lang.String,java.lang.String>,kotlin.Unit>>);
+    property public final java.util.HashMap<java.lang.String,kotlin.jvm.functions.Function2<java.lang.String,java.util.HashMap<java.lang.String,java.lang.String>,kotlin.Unit>> map;
+    field public static final androidx.constraintlayout.compose.DesignElements INSTANCE;
+  }
+
+  public interface DesignInfoProvider {
+    method public String getDesignInfo(int startX, int startY, String args);
+  }
+
+  public interface Dimension {
+    field public static final androidx.constraintlayout.compose.Dimension.Companion Companion;
+  }
+
+  public static interface Dimension.Coercible extends androidx.constraintlayout.compose.Dimension {
+  }
+
+  public static final class Dimension.Companion {
+    method public androidx.constraintlayout.compose.Dimension.Coercible getFillToConstraints();
+    method public androidx.constraintlayout.compose.Dimension getMatchParent();
+    method public androidx.constraintlayout.compose.Dimension.Coercible getPreferredWrapContent();
+    method public androidx.constraintlayout.compose.Dimension getWrapContent();
+    method public androidx.constraintlayout.compose.Dimension percent(float percent);
+    method public androidx.constraintlayout.compose.Dimension.MinCoercible preferredValue(float dp);
+    method public androidx.constraintlayout.compose.Dimension ratio(String ratio);
+    method public androidx.constraintlayout.compose.Dimension value(float dp);
+    property public final androidx.constraintlayout.compose.Dimension.Coercible fillToConstraints;
+    property public final androidx.constraintlayout.compose.Dimension matchParent;
+    property public final androidx.constraintlayout.compose.Dimension.Coercible preferredWrapContent;
+    property public final androidx.constraintlayout.compose.Dimension wrapContent;
+  }
+
+  public static interface Dimension.MaxCoercible extends androidx.constraintlayout.compose.Dimension {
+  }
+
+  public static interface Dimension.MinCoercible extends androidx.constraintlayout.compose.Dimension {
+  }
+
+  @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public final class Easing {
+    method public String getName();
+    property public String name;
+    field public static final androidx.constraintlayout.compose.Easing.Companion Companion;
+  }
+
+  public static final class Easing.Companion {
+    method public androidx.constraintlayout.compose.Easing cubic(float x1, float y1, float x2, float y2);
+    method public androidx.constraintlayout.compose.Easing getAccelerate();
+    method public androidx.constraintlayout.compose.Easing getAnticipate();
+    method public androidx.constraintlayout.compose.Easing getDecelerate();
+    method public androidx.constraintlayout.compose.Easing getLinear();
+    method public androidx.constraintlayout.compose.Easing getOvershoot();
+    method public androidx.constraintlayout.compose.Easing getStandard();
+    property public final androidx.constraintlayout.compose.Easing Accelerate;
+    property public final androidx.constraintlayout.compose.Easing Anticipate;
+    property public final androidx.constraintlayout.compose.Easing Decelerate;
+    property public final androidx.constraintlayout.compose.Easing Linear;
+    property public final androidx.constraintlayout.compose.Easing Overshoot;
+    property public final androidx.constraintlayout.compose.Easing Standard;
+  }
+
+  @kotlin.PublishedApi internal abstract class EditableJSONLayout implements androidx.constraintlayout.compose.LayoutInformationReceiver {
+    ctor public EditableJSONLayout(@org.intellij.lang.annotations.Language("json5") String content);
+    method public final String getCurrentContent();
+    method public final String? getDebugName();
+    method public androidx.constraintlayout.compose.MotionLayoutDebugFlags getForcedDrawDebug();
+    method public int getForcedHeight();
+    method public int getForcedWidth();
+    method public final String getLayoutInformation();
+    method public androidx.constraintlayout.compose.LayoutInfoFlags getLayoutInformationMode();
+    method protected final void initialization();
+    method protected final void onDrawDebug(int debugMode);
+    method protected final void onLayoutInformation(int mode);
+    method protected void onNewContent(String content);
+    method public final void onNewDimensions(int width, int height);
+    method public final void setCurrentContent(String content);
+    method public final void setDebugName(String? name);
+    method public void setLayoutInformation(String information);
+    method public void setUpdateFlag(androidx.compose.runtime.MutableState<java.lang.Long> needsUpdate);
+    method protected final void signalUpdate();
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn(message="MotionLayout API is experimental and it is likely to change.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalMotionApi {
+  }
+
+  @androidx.compose.runtime.Immutable public final class FlowStyle {
+    field public static final androidx.constraintlayout.compose.FlowStyle.Companion Companion;
+  }
+
+  public static final class FlowStyle.Companion {
+    method public androidx.constraintlayout.compose.FlowStyle getPacked();
+    method public androidx.constraintlayout.compose.FlowStyle getSpread();
+    method public androidx.constraintlayout.compose.FlowStyle getSpreadInside();
+    property public final androidx.constraintlayout.compose.FlowStyle Packed;
+    property public final androidx.constraintlayout.compose.FlowStyle Spread;
+    property public final androidx.constraintlayout.compose.FlowStyle SpreadInside;
+  }
+
+  @kotlin.jvm.JvmInline public final value class GridFlags {
+    ctor public GridFlags(optional boolean isPlaceLayoutsOnSpansFirst);
+    method public boolean isPlaceLayoutsOnSpansFirst();
+    property public final boolean isPlaceLayoutsOnSpansFirst;
+    field public static final androidx.constraintlayout.compose.GridFlags.Companion Companion;
+  }
+
+  public static final class GridFlags.Companion {
+    method public int getNone();
+    method public int getPlaceLayoutsOnSpansFirst();
+    property public final int None;
+    property public final int PlaceLayoutsOnSpansFirst;
+  }
+
+  @androidx.compose.runtime.Immutable public final class HorizontalAlign {
+    field public static final androidx.constraintlayout.compose.HorizontalAlign.Companion Companion;
+  }
+
+  public static final class HorizontalAlign.Companion {
+    method public androidx.constraintlayout.compose.HorizontalAlign getCenter();
+    method public androidx.constraintlayout.compose.HorizontalAlign getEnd();
+    method public androidx.constraintlayout.compose.HorizontalAlign getStart();
+    property public final androidx.constraintlayout.compose.HorizontalAlign Center;
+    property public final androidx.constraintlayout.compose.HorizontalAlign End;
+    property public final androidx.constraintlayout.compose.HorizontalAlign Start;
+  }
+
+  @kotlin.jvm.JvmDefaultWithCompatibility public interface HorizontalAnchorable {
+    method public void linkTo(androidx.constraintlayout.compose.ConstraintLayoutBaseScope.BaselineAnchor anchor, optional float margin, optional float goneMargin);
+    method public void linkTo(androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor anchor, optional float margin, optional float goneMargin);
+  }
+
+  @androidx.compose.runtime.Stable public final class HorizontalChainReference extends androidx.constraintlayout.compose.LayoutReference {
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor getAbsoluteLeft();
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor getAbsoluteRight();
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor getEnd();
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor getStart();
+    property public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor absoluteLeft;
+    property public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor absoluteRight;
+    property public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor end;
+    property public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor start;
+  }
+
+  @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Stable public final class HorizontalChainScope {
+    method public androidx.constraintlayout.compose.VerticalAnchorable getAbsoluteLeft();
+    method public androidx.constraintlayout.compose.VerticalAnchorable getAbsoluteRight();
+    method public androidx.constraintlayout.compose.VerticalAnchorable getEnd();
+    method public androidx.constraintlayout.compose.ConstrainedLayoutReference getParent();
+    method public androidx.constraintlayout.compose.VerticalAnchorable getStart();
+    property public final androidx.constraintlayout.compose.VerticalAnchorable absoluteLeft;
+    property public final androidx.constraintlayout.compose.VerticalAnchorable absoluteRight;
+    property public final androidx.constraintlayout.compose.VerticalAnchorable end;
+    property public final androidx.constraintlayout.compose.ConstrainedLayoutReference parent;
+    property public final androidx.constraintlayout.compose.VerticalAnchorable start;
+  }
+
+  public final class InvalidationStrategy {
+    ctor public InvalidationStrategy(optional kotlin.jvm.functions.Function3<? super androidx.constraintlayout.compose.InvalidationStrategySpecification,? super androidx.compose.ui.unit.Constraints,? super androidx.compose.ui.unit.Constraints,java.lang.Boolean>? onIncomingConstraints, kotlin.jvm.functions.Function0<kotlin.Unit>? onObservedStateChange);
+    method public kotlin.jvm.functions.Function3<androidx.constraintlayout.compose.InvalidationStrategySpecification,androidx.compose.ui.unit.Constraints,androidx.compose.ui.unit.Constraints,java.lang.Boolean>? getOnIncomingConstraints();
+    method public kotlin.jvm.functions.Function0<kotlin.Unit>? getOnObservedStateChange();
+    property public final kotlin.jvm.functions.Function3<androidx.constraintlayout.compose.InvalidationStrategySpecification,androidx.compose.ui.unit.Constraints,androidx.compose.ui.unit.Constraints,java.lang.Boolean>? onIncomingConstraints;
+    property public final kotlin.jvm.functions.Function0<kotlin.Unit>? onObservedStateChange;
+    field public static final androidx.constraintlayout.compose.InvalidationStrategy.Companion Companion;
+  }
+
+  public static final class InvalidationStrategy.Companion {
+    method public androidx.constraintlayout.compose.InvalidationStrategy getDefaultInvalidationStrategy();
+    property public final androidx.constraintlayout.compose.InvalidationStrategy DefaultInvalidationStrategy;
+  }
+
+  public final class InvalidationStrategySpecification {
+    method public boolean shouldInvalidateOnFixedHeight(long oldConstraints, long newConstraints, int skipCount, int threshold);
+    method public boolean shouldInvalidateOnFixedWidth(long oldConstraints, long newConstraints, int skipCount, int threshold);
+  }
+
+  @SuppressCompatibility @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.constraintlayout.compose.ExperimentalMotionApi public final class KeyAttributeScope extends androidx.constraintlayout.compose.BaseKeyFrameScope {
+    method public float getAlpha();
+    method public float getRotationX();
+    method public float getRotationY();
+    method public float getRotationZ();
+    method public float getScaleX();
+    method public float getScaleY();
+    method public float getTranslationX();
+    method public float getTranslationY();
+    method public float getTranslationZ();
+    method public void setAlpha(float);
+    method public void setRotationX(float);
+    method public void setRotationY(float);
+    method public void setRotationZ(float);
+    method public void setScaleX(float);
+    method public void setScaleY(float);
+    method public void setTranslationX(float);
+    method public void setTranslationY(float);
+    method public void setTranslationZ(float);
+    property public final float alpha;
+    property public final float rotationX;
+    property public final float rotationY;
+    property public final float rotationZ;
+    property public final float scaleX;
+    property public final float scaleY;
+    property public final float translationX;
+    property public final float translationY;
+    property public final float translationZ;
+  }
+
+  @SuppressCompatibility @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.constraintlayout.compose.ExperimentalMotionApi public final class KeyAttributesScope extends androidx.constraintlayout.compose.BaseKeyFramesScope {
+    method public void frame(@IntRange(from=0L, to=100L) int frame, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.KeyAttributeScope,kotlin.Unit> keyFrameContent);
+  }
+
+  @SuppressCompatibility @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.constraintlayout.compose.ExperimentalMotionApi public final class KeyCycleScope extends androidx.constraintlayout.compose.BaseKeyFrameScope {
+    method public float getAlpha();
+    method public float getOffset();
+    method public float getPeriod();
+    method public float getPhase();
+    method public float getRotationX();
+    method public float getRotationY();
+    method public float getRotationZ();
+    method public float getScaleX();
+    method public float getScaleY();
+    method public float getTranslationX();
+    method public float getTranslationY();
+    method public float getTranslationZ();
+    method public void setAlpha(float);
+    method public void setOffset(float);
+    method public void setPeriod(float);
+    method public void setPhase(float);
+    method public void setRotationX(float);
+    method public void setRotationY(float);
+    method public void setRotationZ(float);
+    method public void setScaleX(float);
+    method public void setScaleY(float);
+    method public void setTranslationX(float);
+    method public void setTranslationY(float);
+    method public void setTranslationZ(float);
+    property public final float alpha;
+    property public final float offset;
+    property public final float period;
+    property public final float phase;
+    property public final float rotationX;
+    property public final float rotationY;
+    property public final float rotationZ;
+    property public final float scaleX;
+    property public final float scaleY;
+    property public final float translationX;
+    property public final float translationY;
+    property public final float translationZ;
+  }
+
+  @SuppressCompatibility @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.constraintlayout.compose.ExperimentalMotionApi public final class KeyCyclesScope extends androidx.constraintlayout.compose.BaseKeyFramesScope {
+    method public void frame(@IntRange(from=0L, to=100L) int frame, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.KeyCycleScope,kotlin.Unit> keyFrameContent);
+  }
+
+  @SuppressCompatibility @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.constraintlayout.compose.ExperimentalMotionApi public final class KeyPositionScope extends androidx.constraintlayout.compose.BaseKeyFrameScope {
+    method public androidx.constraintlayout.compose.CurveFit? getCurveFit();
+    method public float getPercentHeight();
+    method public float getPercentWidth();
+    method public float getPercentX();
+    method public float getPercentY();
+    method public void setCurveFit(androidx.constraintlayout.compose.CurveFit?);
+    method public void setPercentHeight(float);
+    method public void setPercentWidth(float);
+    method public void setPercentX(float);
+    method public void setPercentY(float);
+    property public final androidx.constraintlayout.compose.CurveFit? curveFit;
+    property public final float percentHeight;
+    property public final float percentWidth;
+    property public final float percentX;
+    property public final float percentY;
+  }
+
+  @SuppressCompatibility @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.constraintlayout.compose.ExperimentalMotionApi public final class KeyPositionsScope extends androidx.constraintlayout.compose.BaseKeyFramesScope {
+    method public void frame(@IntRange(from=0L, to=100L) int frame, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.KeyPositionScope,kotlin.Unit> keyFrameContent);
+    method public androidx.constraintlayout.compose.RelativePosition getType();
+    method public void setType(androidx.constraintlayout.compose.RelativePosition);
+    property public final androidx.constraintlayout.compose.RelativePosition type;
+  }
+
+  public final class LateMotionLayoutKt {
+    method @androidx.compose.runtime.Composable @kotlin.PublishedApi internal static void LateMotionLayout(androidx.compose.runtime.MutableState<androidx.constraintlayout.compose.ConstraintSet?> start, androidx.compose.runtime.MutableState<androidx.constraintlayout.compose.ConstraintSet?> end, androidx.compose.animation.core.AnimationSpec<java.lang.Float> animationSpec, kotlinx.coroutines.channels.Channel<androidx.constraintlayout.compose.ConstraintSet> channel, androidx.compose.runtime.State<kotlin.Unit> contentTracker, androidx.compose.ui.node.Ref<androidx.constraintlayout.compose.CompositionSource> compositionSource, int optimizationLevel, kotlin.jvm.functions.Function0<kotlin.Unit>? finishedAnimationListener, androidx.compose.ui.Modifier modifier, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+  }
+
+  public enum LayoutInfoFlags {
+    enum_constant public static final androidx.constraintlayout.compose.LayoutInfoFlags BOUNDS;
+    enum_constant public static final androidx.constraintlayout.compose.LayoutInfoFlags NONE;
+  }
+
+  public interface LayoutInformationReceiver {
+    method public androidx.constraintlayout.compose.MotionLayoutDebugFlags getForcedDrawDebug();
+    method public int getForcedHeight();
+    method public float getForcedProgress();
+    method public int getForcedWidth();
+    method public androidx.constraintlayout.compose.LayoutInfoFlags getLayoutInformationMode();
+    method public void onNewProgress(float progress);
+    method public void resetForcedProgress();
+    method public void setLayoutInformation(String information);
+    method public void setUpdateFlag(androidx.compose.runtime.MutableState<java.lang.Long> needsUpdate);
+  }
+
+  @androidx.compose.runtime.Stable public abstract class LayoutReference {
+  }
+
+  @kotlin.PublishedApi internal class Measurer implements androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.Measurer androidx.constraintlayout.compose.DesignInfoProvider {
+    ctor public Measurer(androidx.compose.ui.unit.Density density);
+    method public final void addLayoutInformationReceiver(androidx.constraintlayout.compose.LayoutInformationReceiver? layoutReceiver);
+    method protected final void applyRootSize(long constraints);
+    method public void computeLayoutResult();
+    method @androidx.compose.runtime.Composable public final void createDesignElements();
+    method public void didMeasures();
+    method @androidx.compose.runtime.Composable public final void drawDebugBounds(androidx.compose.foundation.layout.BoxScope, float forcedScaleFactor);
+    method public final void drawDebugBounds(androidx.compose.ui.graphics.drawscope.DrawScope, float forcedScaleFactor);
+    method public String getDesignInfo(int startX, int startY, String args);
+    method public final float getForcedScaleFactor();
+    method protected final java.util.Map<androidx.compose.ui.layout.Measurable,androidx.constraintlayout.core.state.WidgetFrame> getFrameCache();
+    method public final int getLayoutCurrentHeight();
+    method public final int getLayoutCurrentWidth();
+    method protected final androidx.constraintlayout.compose.LayoutInformationReceiver? getLayoutInformationReceiver();
+    method protected final java.util.Map<androidx.compose.ui.layout.Measurable,androidx.compose.ui.layout.Placeable> getPlaceables();
+    method protected final androidx.constraintlayout.core.widgets.ConstraintWidgetContainer getRoot();
+    method protected final androidx.constraintlayout.compose.State getState();
+    method public void measure(androidx.constraintlayout.core.widgets.ConstraintWidget constraintWidget, androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.Measure measure);
+    method public final void parseDesignElements(androidx.constraintlayout.compose.ConstraintSet constraintSet);
+    method public final void performLayout(androidx.compose.ui.layout.Placeable.PlacementScope, java.util.List<? extends androidx.compose.ui.layout.Measurable> measurables);
+    method public final long performMeasure(long constraints, androidx.compose.ui.unit.LayoutDirection layoutDirection, androidx.constraintlayout.compose.ConstraintSet constraintSet, java.util.List<? extends androidx.compose.ui.layout.Measurable> measurables, int optimizationLevel);
+    method public final void setForcedScaleFactor(float);
+    method protected final void setLayoutInformationReceiver(androidx.constraintlayout.compose.LayoutInformationReceiver?);
+    property public final float forcedScaleFactor;
+    property protected final java.util.Map<androidx.compose.ui.layout.Measurable,androidx.constraintlayout.core.state.WidgetFrame> frameCache;
+    property public final int layoutCurrentHeight;
+    property public final int layoutCurrentWidth;
+    property protected final androidx.constraintlayout.compose.LayoutInformationReceiver? layoutInformationReceiver;
+    property protected final java.util.Map<androidx.compose.ui.layout.Measurable,androidx.compose.ui.layout.Placeable> placeables;
+    property protected final androidx.constraintlayout.core.widgets.ConstraintWidgetContainer root;
+    property protected final androidx.constraintlayout.compose.State state;
+  }
+
+  public final class MotionCarouselKt {
+    method @androidx.compose.runtime.Composable public static void ItemHolder(int i, String slotPrefix, boolean showSlot, kotlin.jvm.functions.Function0<kotlin.Unit> function);
+    method @androidx.compose.runtime.Composable public static void MotionCarousel(androidx.constraintlayout.compose.MotionScene motionScene, int initialSlotIndex, int numSlots, optional String backwardTransition, optional String forwardTransition, optional String slotPrefix, optional boolean showSlots, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.MotionCarouselScope,kotlin.Unit> content);
+    method public static inline <T> void items(androidx.constraintlayout.compose.MotionCarouselScope, java.util.List<? extends T> items, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> itemContent);
+    method public static inline <T> void itemsWithProperties(androidx.constraintlayout.compose.MotionCarouselScope, java.util.List<? extends T> items, kotlin.jvm.functions.Function2<? super T,? super androidx.compose.runtime.State<androidx.constraintlayout.compose.MotionLayoutScope.MotionProperties>,kotlin.Unit> itemContent);
+  }
+
+  public interface MotionCarouselScope {
+    method public void items(int count, kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit> itemContent);
+    method public void itemsWithProperties(int count, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super androidx.compose.runtime.State<androidx.constraintlayout.compose.MotionLayoutScope.MotionProperties>,kotlin.Unit> itemContent);
+  }
+
+  public interface MotionItemsProvider {
+    method public int count();
+    method public kotlin.jvm.functions.Function0<kotlin.Unit> getContent(int index);
+    method public kotlin.jvm.functions.Function0<kotlin.Unit> getContent(int index, androidx.compose.runtime.State<androidx.constraintlayout.compose.MotionLayoutScope.MotionProperties> properties);
+    method public boolean hasItemsWithProperties();
+  }
+
+  public enum MotionLayoutDebugFlags {
+    enum_constant public static final androidx.constraintlayout.compose.MotionLayoutDebugFlags NONE;
+    enum_constant public static final androidx.constraintlayout.compose.MotionLayoutDebugFlags SHOW_ALL;
+    enum_constant public static final androidx.constraintlayout.compose.MotionLayoutDebugFlags UNKNOWN;
+  }
+
+  @Deprecated public enum MotionLayoutFlag {
+    enum_constant @Deprecated public static final androidx.constraintlayout.compose.MotionLayoutFlag Default;
+    enum_constant @Deprecated public static final androidx.constraintlayout.compose.MotionLayoutFlag FullMeasure;
+  }
+
+  public final class MotionLayoutKt {
+    method @SuppressCompatibility @androidx.compose.runtime.Composable @androidx.constraintlayout.compose.ExperimentalMotionApi public static inline void MotionLayout(androidx.constraintlayout.compose.ConstraintSet start, androidx.constraintlayout.compose.ConstraintSet end, float progress, optional androidx.compose.ui.Modifier modifier, optional androidx.constraintlayout.compose.Transition? transition, optional int debugFlags, optional int optimizationLevel, optional androidx.constraintlayout.compose.InvalidationStrategy invalidationStrategy, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.MotionLayoutScope,kotlin.Unit> content);
+    method @SuppressCompatibility @androidx.compose.runtime.Composable @androidx.constraintlayout.compose.ExperimentalMotionApi public static inline void MotionLayout(androidx.constraintlayout.compose.MotionScene motionScene, float progress, optional androidx.compose.ui.Modifier modifier, optional String transitionName, optional int debugFlags, optional int optimizationLevel, optional androidx.constraintlayout.compose.InvalidationStrategy invalidationStrategy, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.MotionLayoutScope,kotlin.Unit> content);
+    method @SuppressCompatibility @androidx.compose.runtime.Composable @androidx.constraintlayout.compose.ExperimentalMotionApi public static inline void MotionLayout(androidx.constraintlayout.compose.MotionScene motionScene, String? constraintSetName, androidx.compose.animation.core.AnimationSpec<java.lang.Float> animationSpec, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? finishedAnimationListener, optional int debugFlags, optional int optimizationLevel, optional androidx.constraintlayout.compose.InvalidationStrategy invalidationStrategy, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.MotionLayoutScope,kotlin.Unit> content);
+    method @SuppressCompatibility @androidx.compose.runtime.Composable @androidx.constraintlayout.compose.ExperimentalMotionApi @kotlin.PublishedApi internal static void MotionLayoutCore(androidx.constraintlayout.compose.ConstraintSet start, androidx.constraintlayout.compose.ConstraintSet end, androidx.constraintlayout.compose.Transition? transition, float progress, androidx.constraintlayout.compose.LayoutInformationReceiver? informationReceiver, int optimizationLevel, boolean showBounds, boolean showPaths, boolean showKeyPositions, androidx.compose.ui.Modifier modifier, androidx.compose.runtime.MutableState<kotlin.Unit> contentTracker, androidx.compose.ui.node.Ref<androidx.constraintlayout.compose.CompositionSource> compositionSource, androidx.constraintlayout.compose.InvalidationStrategy invalidationStrategy, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.MotionLayoutScope,kotlin.Unit> content);
+    method @SuppressCompatibility @androidx.compose.runtime.Composable @androidx.constraintlayout.compose.ExperimentalMotionApi @kotlin.PublishedApi internal static void MotionLayoutCore(androidx.constraintlayout.compose.MotionScene motionScene, float progress, String transitionName, int optimizationLevel, int debugFlags, androidx.compose.ui.Modifier modifier, androidx.compose.runtime.MutableState<kotlin.Unit> contentTracker, androidx.compose.ui.node.Ref<androidx.constraintlayout.compose.CompositionSource> compositionSource, androidx.constraintlayout.compose.InvalidationStrategy invalidationStrategy, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.MotionLayoutScope,kotlin.Unit> content);
+    method @SuppressCompatibility @androidx.compose.runtime.Composable @androidx.constraintlayout.compose.ExperimentalMotionApi @kotlin.PublishedApi internal static void MotionLayoutCore(androidx.constraintlayout.compose.MotionScene motionScene, String? constraintSetName, androidx.compose.animation.core.AnimationSpec<java.lang.Float> animationSpec, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? finishedAnimationListener, optional int debugFlags, optional int optimizationLevel, androidx.compose.runtime.MutableState<kotlin.Unit> contentTracker, androidx.compose.ui.node.Ref<androidx.constraintlayout.compose.CompositionSource> compositionSource, androidx.constraintlayout.compose.InvalidationStrategy invalidationStrategy, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.MotionLayoutScope,kotlin.Unit> content);
+  }
+
+  @SuppressCompatibility @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.constraintlayout.compose.ExperimentalMotionApi public final class MotionLayoutScope {
+    method public long customColor(String id, String name);
+    method public float customDistance(String id, String name);
+    method public float customFloat(String id, String name);
+    method public long customFontSize(String id, String name);
+    method public int customInt(String id, String name);
+    method public androidx.constraintlayout.compose.MotionLayoutScope.CustomProperties customProperties(String id);
+    method @Deprecated public long motionColor(String id, String name);
+    method @Deprecated public float motionDistance(String id, String name);
+    method @Deprecated public float motionFloat(String id, String name);
+    method @Deprecated public long motionFontSize(String id, String name);
+    method @Deprecated public int motionInt(String id, String name);
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.runtime.State<androidx.constraintlayout.compose.MotionLayoutScope.MotionProperties> motionProperties(String id);
+    method @Deprecated public androidx.constraintlayout.compose.MotionLayoutScope.MotionProperties motionProperties(String id, String tag);
+    method public androidx.compose.ui.Modifier onStartEndBoundsChanged(androidx.compose.ui.Modifier, Object layoutId, kotlin.jvm.functions.Function2<? super androidx.compose.ui.geometry.Rect,? super androidx.compose.ui.geometry.Rect,kotlin.Unit> onBoundsChanged);
+  }
+
+  public final class MotionLayoutScope.CustomProperties {
+    method public long color(String name);
+    method public float distance(String name);
+    method public float float(String name);
+    method public long fontSize(String name);
+    method public int int(String name);
+  }
+
+  public final class MotionLayoutScope.MotionProperties {
+    method public long color(String name);
+    method public float distance(String name);
+    method public float float(String name);
+    method public long fontSize(String name);
+    method public String id();
+    method public int int(String name);
+    method public String? tag();
+  }
+
+  @SuppressCompatibility @androidx.compose.runtime.Immutable @androidx.constraintlayout.compose.ExperimentalMotionApi public interface MotionScene extends androidx.constraintlayout.core.state.CoreMotionScene {
+    method public androidx.constraintlayout.compose.ConstraintSet? getConstraintSetInstance(String name);
+    method public androidx.constraintlayout.compose.Transition? getTransitionInstance(String name);
+  }
+
+  public final class MotionSceneKt {
+    method @SuppressCompatibility @androidx.compose.runtime.Composable @androidx.constraintlayout.compose.ExperimentalMotionApi public static androidx.constraintlayout.compose.MotionScene MotionScene(@org.intellij.lang.annotations.Language("json5") String content);
+  }
+
+  @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public final class MotionSceneScope {
+    method public androidx.constraintlayout.compose.ConstraintSetRef addConstraintSet(androidx.constraintlayout.compose.ConstraintSet constraintSet, optional String? name);
+    method public void addTransition(androidx.constraintlayout.compose.Transition transition, optional String? name);
+    method public androidx.constraintlayout.compose.ConstraintSetRef constraintSet(optional String? name, optional androidx.constraintlayout.compose.ConstraintSetRef? extendConstraintSet, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.ConstraintSetScope,kotlin.Unit> constraintSetContent);
+    method public androidx.constraintlayout.compose.ConstrainedLayoutReference createRefFor(Object id);
+    method public androidx.constraintlayout.compose.MotionSceneScope.ConstrainedLayoutReferences createRefsFor(java.lang.Object... ids);
+    method public void customColor(androidx.constraintlayout.compose.ConstrainScope, String name, long value);
+    method public void customColor(androidx.constraintlayout.compose.KeyAttributeScope, String name, long value);
+    method public void customDistance(androidx.constraintlayout.compose.ConstrainScope, String name, float value);
+    method public void customDistance(androidx.constraintlayout.compose.KeyAttributeScope, String name, float value);
+    method public void customFloat(androidx.constraintlayout.compose.ConstrainScope, String name, float value);
+    method public void customFloat(androidx.constraintlayout.compose.KeyAttributeScope, String name, float value);
+    method public void customFontSize(androidx.constraintlayout.compose.ConstrainScope, String name, long value);
+    method public void customFontSize(androidx.constraintlayout.compose.KeyAttributeScope, String name, long value);
+    method public void customInt(androidx.constraintlayout.compose.ConstrainScope, String name, int value);
+    method public void customInt(androidx.constraintlayout.compose.KeyAttributeScope, String name, int value);
+    method public void defaultTransition(androidx.constraintlayout.compose.ConstraintSetRef from, androidx.constraintlayout.compose.ConstraintSetRef to, optional kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.TransitionScope,kotlin.Unit> transitionContent);
+    method public float getStaggeredWeight(androidx.constraintlayout.compose.ConstrainScope);
+    method public void setStaggeredWeight(androidx.constraintlayout.compose.ConstrainScope, float);
+    method public void transition(androidx.constraintlayout.compose.ConstraintSetRef from, androidx.constraintlayout.compose.ConstraintSetRef to, optional String? name, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.TransitionScope,kotlin.Unit> transitionContent);
+  }
+
+  public final class MotionSceneScope.ConstrainedLayoutReferences {
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component1();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component10();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component11();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component12();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component13();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component14();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component15();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component16();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component2();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component3();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component4();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component5();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component6();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component7();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component8();
+    method public operator androidx.constraintlayout.compose.ConstrainedLayoutReference component9();
+  }
+
+  public final class MotionSceneScopeKt {
+    method @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public static androidx.constraintlayout.compose.MotionScene MotionScene(kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.MotionSceneScope,kotlin.Unit> motionSceneContent);
+  }
+
+  @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public final class OnSwipe {
+    ctor public OnSwipe(androidx.constraintlayout.compose.ConstrainedLayoutReference anchor, androidx.constraintlayout.compose.SwipeSide side, androidx.constraintlayout.compose.SwipeDirection direction, optional float dragScale, optional float dragThreshold, optional androidx.constraintlayout.compose.ConstrainedLayoutReference? dragAround, optional androidx.constraintlayout.compose.ConstrainedLayoutReference? limitBoundsTo, optional androidx.constraintlayout.compose.SwipeTouchUp onTouchUp, optional androidx.constraintlayout.compose.SwipeMode mode);
+    method public androidx.constraintlayout.compose.ConstrainedLayoutReference getAnchor();
+    method public androidx.constraintlayout.compose.SwipeDirection getDirection();
+    method public androidx.constraintlayout.compose.ConstrainedLayoutReference? getDragAround();
+    method public float getDragScale();
+    method public float getDragThreshold();
+    method public androidx.constraintlayout.compose.ConstrainedLayoutReference? getLimitBoundsTo();
+    method public androidx.constraintlayout.compose.SwipeMode getMode();
+    method public androidx.constraintlayout.compose.SwipeTouchUp getOnTouchUp();
+    method public androidx.constraintlayout.compose.SwipeSide getSide();
+    property public final androidx.constraintlayout.compose.ConstrainedLayoutReference anchor;
+    property public final androidx.constraintlayout.compose.SwipeDirection direction;
+    property public final androidx.constraintlayout.compose.ConstrainedLayoutReference? dragAround;
+    property public final float dragScale;
+    property public final float dragThreshold;
+    property public final androidx.constraintlayout.compose.ConstrainedLayoutReference? limitBoundsTo;
+    property public final androidx.constraintlayout.compose.SwipeMode mode;
+    property public final androidx.constraintlayout.compose.SwipeTouchUp onTouchUp;
+    property public final androidx.constraintlayout.compose.SwipeSide side;
+  }
+
+  @androidx.compose.runtime.Immutable @kotlin.PublishedApi internal final class RawConstraintSet implements androidx.constraintlayout.compose.ConstraintSet {
+    ctor public RawConstraintSet(androidx.constraintlayout.core.parser.CLObject clObject);
+    method public void applyTo(androidx.constraintlayout.compose.State state, java.util.List<? extends androidx.compose.ui.layout.Measurable> measurables);
+  }
+
+  @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public final class RelativePosition {
+    method public String getName();
+    property public String name;
+    field public static final androidx.constraintlayout.compose.RelativePosition.Companion Companion;
+  }
+
+  public static final class RelativePosition.Companion {
+    method public androidx.constraintlayout.compose.RelativePosition getDelta();
+    method public androidx.constraintlayout.compose.RelativePosition getParent();
+    method public androidx.constraintlayout.compose.RelativePosition getPath();
+    property public final androidx.constraintlayout.compose.RelativePosition Delta;
+    property public final androidx.constraintlayout.compose.RelativePosition Parent;
+    property public final androidx.constraintlayout.compose.RelativePosition Path;
+  }
+
+  @kotlin.jvm.JvmInline public final value class Skip {
+    ctor public Skip(@IntRange(from=0L) int position, @IntRange(from=1L) int size);
+    ctor public Skip(@IntRange(from=0L) int position, @IntRange(from=1L) int rows, @IntRange(from=1L) int columns);
+    method public String getDescription();
+    property public final String description;
+  }
+
+  @kotlin.jvm.JvmInline public final value class Span {
+    ctor public Span(@IntRange(from=0L) int position, @IntRange(from=1L) int size);
+    ctor public Span(@IntRange(from=0L) int position, @IntRange(from=1L) int rows, @IntRange(from=1L) int columns);
+    ctor public Span(String description);
+    method public String getDescription();
+    property public final String description;
+  }
+
+  @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public final class SpringBoundary {
+    method public String getName();
+    property public final String name;
+    field public static final androidx.constraintlayout.compose.SpringBoundary.Companion Companion;
+  }
+
+  public static final class SpringBoundary.Companion {
+    method public androidx.constraintlayout.compose.SpringBoundary getBounceBoth();
+    method public androidx.constraintlayout.compose.SpringBoundary getBounceEnd();
+    method public androidx.constraintlayout.compose.SpringBoundary getBounceStart();
+    method public androidx.constraintlayout.compose.SpringBoundary getOvershoot();
+    property public final androidx.constraintlayout.compose.SpringBoundary BounceBoth;
+    property public final androidx.constraintlayout.compose.SpringBoundary BounceEnd;
+    property public final androidx.constraintlayout.compose.SpringBoundary BounceStart;
+    property public final androidx.constraintlayout.compose.SpringBoundary Overshoot;
+  }
+
+  public final class State extends androidx.constraintlayout.core.state.State {
+    ctor public State(androidx.compose.ui.unit.Density density);
+    method public androidx.compose.ui.unit.Density getDensity();
+    method @Deprecated public androidx.compose.ui.unit.LayoutDirection getLayoutDirection();
+    method public long getRootIncomingConstraints();
+    method @Deprecated public void setLayoutDirection(androidx.compose.ui.unit.LayoutDirection);
+    method public void setRootIncomingConstraints(long);
+    property public final androidx.compose.ui.unit.Density density;
+    property @Deprecated public final androidx.compose.ui.unit.LayoutDirection layoutDirection;
+    property public final long rootIncomingConstraints;
+  }
+
+  @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public final class SwipeDirection {
+    method public String getName();
+    property public final String name;
+    field public static final androidx.constraintlayout.compose.SwipeDirection.Companion Companion;
+  }
+
+  public static final class SwipeDirection.Companion {
+    method public androidx.constraintlayout.compose.SwipeDirection getClockwise();
+    method public androidx.constraintlayout.compose.SwipeDirection getCounterclockwise();
+    method public androidx.constraintlayout.compose.SwipeDirection getDown();
+    method public androidx.constraintlayout.compose.SwipeDirection getEnd();
+    method public androidx.constraintlayout.compose.SwipeDirection getLeft();
+    method public androidx.constraintlayout.compose.SwipeDirection getRight();
+    method public androidx.constraintlayout.compose.SwipeDirection getStart();
+    method public androidx.constraintlayout.compose.SwipeDirection getUp();
+    property public final androidx.constraintlayout.compose.SwipeDirection Clockwise;
+    property public final androidx.constraintlayout.compose.SwipeDirection Counterclockwise;
+    property public final androidx.constraintlayout.compose.SwipeDirection Down;
+    property public final androidx.constraintlayout.compose.SwipeDirection End;
+    property public final androidx.constraintlayout.compose.SwipeDirection Left;
+    property public final androidx.constraintlayout.compose.SwipeDirection Right;
+    property public final androidx.constraintlayout.compose.SwipeDirection Start;
+    property public final androidx.constraintlayout.compose.SwipeDirection Up;
+  }
+
+  @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public final class SwipeMode {
+    method public String getName();
+    property public final String name;
+    field public static final androidx.constraintlayout.compose.SwipeMode.Companion Companion;
+  }
+
+  public static final class SwipeMode.Companion {
+    method public androidx.constraintlayout.compose.SwipeMode getSpring();
+    method public androidx.constraintlayout.compose.SwipeMode getVelocity();
+    method public androidx.constraintlayout.compose.SwipeMode spring(optional float mass, optional float stiffness, optional float damping, optional float threshold, optional androidx.constraintlayout.compose.SpringBoundary boundary);
+    method public androidx.constraintlayout.compose.SwipeMode velocity(optional float maxVelocity, optional float maxAcceleration);
+    property public final androidx.constraintlayout.compose.SwipeMode Spring;
+    property public final androidx.constraintlayout.compose.SwipeMode Velocity;
+  }
+
+  @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public final class SwipeSide {
+    method public String getName();
+    property public final String name;
+    field public static final androidx.constraintlayout.compose.SwipeSide.Companion Companion;
+  }
+
+  public static final class SwipeSide.Companion {
+    method public androidx.constraintlayout.compose.SwipeSide getBottom();
+    method public androidx.constraintlayout.compose.SwipeSide getEnd();
+    method public androidx.constraintlayout.compose.SwipeSide getLeft();
+    method public androidx.constraintlayout.compose.SwipeSide getMiddle();
+    method public androidx.constraintlayout.compose.SwipeSide getRight();
+    method public androidx.constraintlayout.compose.SwipeSide getStart();
+    method public androidx.constraintlayout.compose.SwipeSide getTop();
+    property public final androidx.constraintlayout.compose.SwipeSide Bottom;
+    property public final androidx.constraintlayout.compose.SwipeSide End;
+    property public final androidx.constraintlayout.compose.SwipeSide Left;
+    property public final androidx.constraintlayout.compose.SwipeSide Middle;
+    property public final androidx.constraintlayout.compose.SwipeSide Right;
+    property public final androidx.constraintlayout.compose.SwipeSide Start;
+    property public final androidx.constraintlayout.compose.SwipeSide Top;
+  }
+
+  @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public final class SwipeTouchUp {
+    method public String getName();
+    property public final String name;
+    field public static final androidx.constraintlayout.compose.SwipeTouchUp.Companion Companion;
+  }
+
+  public static final class SwipeTouchUp.Companion {
+    method public androidx.constraintlayout.compose.SwipeTouchUp getAutoComplete();
+    method public androidx.constraintlayout.compose.SwipeTouchUp getDecelerate();
+    method public androidx.constraintlayout.compose.SwipeTouchUp getNeverCompleteEnd();
+    method public androidx.constraintlayout.compose.SwipeTouchUp getNeverCompleteStart();
+    method public androidx.constraintlayout.compose.SwipeTouchUp getStop();
+    method public androidx.constraintlayout.compose.SwipeTouchUp getToEnd();
+    method public androidx.constraintlayout.compose.SwipeTouchUp getToStart();
+    property public final androidx.constraintlayout.compose.SwipeTouchUp AutoComplete;
+    property public final androidx.constraintlayout.compose.SwipeTouchUp Decelerate;
+    property public final androidx.constraintlayout.compose.SwipeTouchUp NeverCompleteEnd;
+    property public final androidx.constraintlayout.compose.SwipeTouchUp NeverCompleteStart;
+    property public final androidx.constraintlayout.compose.SwipeTouchUp Stop;
+    property public final androidx.constraintlayout.compose.SwipeTouchUp ToEnd;
+    property public final androidx.constraintlayout.compose.SwipeTouchUp ToStart;
+  }
+
+  public final class ToolingUtilsKt {
+    method public static androidx.compose.ui.semantics.SemanticsPropertyKey<androidx.constraintlayout.compose.DesignInfoProvider> getDesignInfoDataKey();
+    property public static final androidx.compose.ui.semantics.SemanticsPropertyKey<androidx.constraintlayout.compose.DesignInfoProvider> DesignInfoDataKey;
+    field @kotlin.PublishedApi internal static final androidx.compose.ui.semantics.SemanticsPropertyKey<androidx.constraintlayout.compose.DesignInfoProvider> designInfoProvider$delegate;
+  }
+
+  @SuppressCompatibility @androidx.compose.runtime.Immutable @androidx.constraintlayout.compose.ExperimentalMotionApi public interface Transition {
+    method public String getEndConstraintSetId();
+    method public String getStartConstraintSetId();
+  }
+
+  public final class TransitionKt {
+    method @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public static androidx.constraintlayout.compose.Transition Transition(@org.intellij.lang.annotations.Language("json5") String content);
+  }
+
+  @SuppressCompatibility @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.constraintlayout.compose.ExperimentalMotionApi public final class TransitionScope {
+    method public androidx.constraintlayout.compose.ConstrainedLayoutReference createRefFor(Object id);
+    method public float getMaxStaggerDelay();
+    method public androidx.constraintlayout.compose.Arc getMotionArc();
+    method public androidx.constraintlayout.compose.OnSwipe? getOnSwipe();
+    method public void keyAttributes(androidx.constraintlayout.compose.ConstrainedLayoutReference[] targets, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.KeyAttributesScope,kotlin.Unit> keyAttributesContent);
+    method public void keyCycles(androidx.constraintlayout.compose.ConstrainedLayoutReference[] targets, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.KeyCyclesScope,kotlin.Unit> keyCyclesContent);
+    method public void keyPositions(androidx.constraintlayout.compose.ConstrainedLayoutReference[] targets, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.KeyPositionsScope,kotlin.Unit> keyPositionsContent);
+    method public void setMaxStaggerDelay(float);
+    method public void setMotionArc(androidx.constraintlayout.compose.Arc);
+    method public void setOnSwipe(androidx.constraintlayout.compose.OnSwipe?);
+    property public final float maxStaggerDelay;
+    property public final androidx.constraintlayout.compose.Arc motionArc;
+    property public final androidx.constraintlayout.compose.OnSwipe? onSwipe;
+  }
+
+  public final class TransitionScopeKt {
+    method @SuppressCompatibility @androidx.constraintlayout.compose.ExperimentalMotionApi public static androidx.constraintlayout.compose.Transition Transition(optional String from, optional String to, kotlin.jvm.functions.Function1<? super androidx.constraintlayout.compose.TransitionScope,kotlin.Unit> content);
+  }
+
+  @androidx.compose.runtime.Immutable public final class VerticalAlign {
+    field public static final androidx.constraintlayout.compose.VerticalAlign.Companion Companion;
+  }
+
+  public static final class VerticalAlign.Companion {
+    method public androidx.constraintlayout.compose.VerticalAlign getBaseline();
+    method public androidx.constraintlayout.compose.VerticalAlign getBottom();
+    method public androidx.constraintlayout.compose.VerticalAlign getCenter();
+    method public androidx.constraintlayout.compose.VerticalAlign getTop();
+    property public final androidx.constraintlayout.compose.VerticalAlign Baseline;
+    property public final androidx.constraintlayout.compose.VerticalAlign Bottom;
+    property public final androidx.constraintlayout.compose.VerticalAlign Center;
+    property public final androidx.constraintlayout.compose.VerticalAlign Top;
+  }
+
+  @kotlin.jvm.JvmDefaultWithCompatibility public interface VerticalAnchorable {
+    method public void linkTo(androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor anchor, optional float margin, optional float goneMargin);
+  }
+
+  @androidx.compose.runtime.Stable public final class VerticalChainReference extends androidx.constraintlayout.compose.LayoutReference {
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor getBottom();
+    method public androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor getTop();
+    property public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor bottom;
+    property public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor top;
+  }
+
+  @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Stable public final class VerticalChainScope {
+    method public androidx.constraintlayout.compose.HorizontalAnchorable getBottom();
+    method public androidx.constraintlayout.compose.ConstrainedLayoutReference getParent();
+    method public androidx.constraintlayout.compose.HorizontalAnchorable getTop();
+    property public final androidx.constraintlayout.compose.HorizontalAnchorable bottom;
+    property public final androidx.constraintlayout.compose.ConstrainedLayoutReference parent;
+    property public final androidx.constraintlayout.compose.HorizontalAnchorable top;
+  }
+
+  @androidx.compose.runtime.Immutable public final class Visibility {
+    field public static final androidx.constraintlayout.compose.Visibility.Companion Companion;
+  }
+
+  public static final class Visibility.Companion {
+    method public androidx.constraintlayout.compose.Visibility getGone();
+    method public androidx.constraintlayout.compose.Visibility getInvisible();
+    method public androidx.constraintlayout.compose.Visibility getVisible();
+    property public final androidx.constraintlayout.compose.Visibility Gone;
+    property public final androidx.constraintlayout.compose.Visibility Invisible;
+    property public final androidx.constraintlayout.compose.Visibility Visible;
+  }
+
+  @androidx.compose.runtime.Immutable public final class Wrap {
+    field public static final androidx.constraintlayout.compose.Wrap.Companion Companion;
+  }
+
+  public static final class Wrap.Companion {
+    method public androidx.constraintlayout.compose.Wrap getAligned();
+    method public androidx.constraintlayout.compose.Wrap getChain();
+    method public androidx.constraintlayout.compose.Wrap getNone();
+    property public final androidx.constraintlayout.compose.Wrap Aligned;
+    property public final androidx.constraintlayout.compose.Wrap Chain;
+    property public final androidx.constraintlayout.compose.Wrap None;
+  }
+
+}
+
diff --git a/constraintlayout/constraintlayout-compose/api/restricted_current.txt b/constraintlayout/constraintlayout-compose/api/restricted_current.txt
index e4ca4a1..60bc75d 100644
--- a/constraintlayout/constraintlayout-compose/api/restricted_current.txt
+++ b/constraintlayout/constraintlayout-compose/api/restricted_current.txt
@@ -175,15 +175,12 @@
     method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createAbsoluteLeftBarrier(androidx.constraintlayout.compose.LayoutReference[] elements, optional float margin);
     method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createAbsoluteRightBarrier(androidx.constraintlayout.compose.LayoutReference[] elements, optional float margin);
     method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor createBottomBarrier(androidx.constraintlayout.compose.LayoutReference[] elements, optional float margin);
-    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createColumn(androidx.constraintlayout.compose.LayoutReference[] elements, optional androidx.constraintlayout.compose.Skip[] skips, optional androidx.constraintlayout.compose.Span[] spans, optional float verticalGap, optional int[] rowWeights, optional float paddingHorizontal, optional float paddingVertical);
-    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createColumn(androidx.constraintlayout.compose.LayoutReference[] elements, optional androidx.constraintlayout.compose.Skip[] skips, optional androidx.constraintlayout.compose.Span[] spans, optional int[] rowWeights, optional float verticalGap, optional float padding);
+    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createColumn(androidx.constraintlayout.compose.LayoutReference[] elements, optional float spacing, optional float[] weights);
     method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createEndBarrier(androidx.constraintlayout.compose.LayoutReference[] elements, optional float margin);
     method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createFlow(androidx.constraintlayout.compose.LayoutReference?[] elements, optional boolean flowVertically, optional float verticalGap, optional float horizontalGap, optional int maxElement, optional float padding, optional androidx.constraintlayout.compose.Wrap wrapMode, optional androidx.constraintlayout.compose.VerticalAlign verticalAlign, optional androidx.constraintlayout.compose.HorizontalAlign horizontalAlign, optional float horizontalFlowBias, optional float verticalFlowBias, optional androidx.constraintlayout.compose.FlowStyle verticalStyle, optional androidx.constraintlayout.compose.FlowStyle horizontalStyle);
     method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createFlow(androidx.constraintlayout.compose.LayoutReference?[] elements, optional boolean flowVertically, optional float verticalGap, optional float horizontalGap, optional int maxElement, optional float paddingHorizontal, optional float paddingVertical, optional androidx.constraintlayout.compose.Wrap wrapMode, optional androidx.constraintlayout.compose.VerticalAlign verticalAlign, optional androidx.constraintlayout.compose.HorizontalAlign horizontalAlign, optional float horizontalFlowBias, optional float verticalFlowBias, optional androidx.constraintlayout.compose.FlowStyle verticalStyle, optional androidx.constraintlayout.compose.FlowStyle horizontalStyle);
     method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createFlow(androidx.constraintlayout.compose.LayoutReference?[] elements, optional boolean flowVertically, optional float verticalGap, optional float horizontalGap, optional int maxElement, optional float paddingLeft, optional float paddingTop, optional float paddingRight, optional float paddingBottom, optional androidx.constraintlayout.compose.Wrap wrapMode, optional androidx.constraintlayout.compose.VerticalAlign verticalAlign, optional androidx.constraintlayout.compose.HorizontalAlign horizontalAlign, optional float horizontalFlowBias, optional float verticalFlowBias, optional androidx.constraintlayout.compose.FlowStyle verticalStyle, optional androidx.constraintlayout.compose.FlowStyle horizontalStyle);
-    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createGrid(androidx.constraintlayout.compose.LayoutReference[] elements, optional int orientation, optional int rows, optional int columns, optional float verticalGap, optional float horizontalGap, optional int[] rowWeights, optional int[] columnWeights, optional androidx.constraintlayout.compose.Skip[] skips, optional androidx.constraintlayout.compose.Span[] spans, optional float padding, optional androidx.constraintlayout.compose.GridFlag[] flags);
-    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createGrid(androidx.constraintlayout.compose.LayoutReference[] elements, optional int orientation, optional int rows, optional int columns, optional float verticalGap, optional float horizontalGap, optional int[] rowWeights, optional int[] columnWeights, optional androidx.constraintlayout.compose.Skip[] skips, optional androidx.constraintlayout.compose.Span[] spans, optional float paddingHorizontal, optional float paddingVertical, optional androidx.constraintlayout.compose.GridFlag[] flags);
-    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createGrid(androidx.constraintlayout.compose.LayoutReference[] elements, optional int orientation, optional int rows, optional int columns, optional float verticalGap, optional float horizontalGap, optional int[] rowWeights, optional int[] columnWeights, optional androidx.constraintlayout.compose.Skip[] skips, optional androidx.constraintlayout.compose.Span[] spans, optional float paddingStart, optional float paddingTop, optional float paddingEnd, optional float paddingBottom, optional androidx.constraintlayout.compose.GridFlag[] flags);
+    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createGrid(androidx.constraintlayout.compose.LayoutReference[] elements, @IntRange(from=1L) int rows, @IntRange(from=1L) int columns, optional boolean isHorizontalArrangement, optional float verticalSpacing, optional float horizontalSpacing, optional float[] rowWeights, optional float[] columnWeights, optional androidx.constraintlayout.compose.Skip[] skips, optional androidx.constraintlayout.compose.Span[] spans, optional int flags);
     method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteLeft(float offset);
     method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteLeft(float fraction);
     method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteRight(float offset);
@@ -197,8 +194,7 @@
     method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromTop(float offset);
     method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromTop(float fraction);
     method public final androidx.constraintlayout.compose.HorizontalChainReference createHorizontalChain(androidx.constraintlayout.compose.LayoutReference[] elements, optional androidx.constraintlayout.compose.ChainStyle chainStyle);
-    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createRow(androidx.constraintlayout.compose.LayoutReference[] elements, optional androidx.constraintlayout.compose.Skip[] skips, optional androidx.constraintlayout.compose.Span[] spans, optional float horizontalGap, optional int[] columnWeights, optional float padding);
-    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createRow(androidx.constraintlayout.compose.LayoutReference[] elements, optional androidx.constraintlayout.compose.Skip[] skips, optional androidx.constraintlayout.compose.Span[] spans, optional float horizontalGap, optional int[] columnWeights, optional float paddingHorizontal, optional float paddingVertical);
+    method public final androidx.constraintlayout.compose.ConstrainedLayoutReference createRow(androidx.constraintlayout.compose.LayoutReference[] elements, optional float spacing, optional float[] weights);
     method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.VerticalAnchor createStartBarrier(androidx.constraintlayout.compose.LayoutReference[] elements, optional float margin);
     method public final androidx.constraintlayout.compose.ConstraintLayoutBaseScope.HorizontalAnchor createTopBarrier(androidx.constraintlayout.compose.LayoutReference[] elements, optional float margin);
     method public final androidx.constraintlayout.compose.VerticalChainReference createVerticalChain(androidx.constraintlayout.compose.LayoutReference[] elements, optional androidx.constraintlayout.compose.ChainStyle chainStyle);
@@ -472,15 +468,18 @@
     property public final androidx.constraintlayout.compose.FlowStyle SpreadInside;
   }
 
-  @androidx.compose.runtime.Immutable public final class GridFlag {
-    field public static final androidx.constraintlayout.compose.GridFlag.Companion Companion;
+  @kotlin.jvm.JvmInline public final value class GridFlags {
+    ctor public GridFlags(optional boolean isPlaceLayoutsOnSpansFirst);
+    method public boolean isPlaceLayoutsOnSpansFirst();
+    property public final boolean isPlaceLayoutsOnSpansFirst;
+    field public static final androidx.constraintlayout.compose.GridFlags.Companion Companion;
   }
 
-  public static final class GridFlag.Companion {
-    method public androidx.constraintlayout.compose.GridFlag getSpansRespectWidgetOrder();
-    method public androidx.constraintlayout.compose.GridFlag getSubGridByColRow();
-    property public final androidx.constraintlayout.compose.GridFlag SpansRespectWidgetOrder;
-    property public final androidx.constraintlayout.compose.GridFlag SubGridByColRow;
+  public static final class GridFlags.Companion {
+    method public int getNone();
+    method public int getPlaceLayoutsOnSpansFirst();
+    property public final int None;
+    property public final int PlaceLayoutsOnSpansFirst;
   }
 
   @androidx.compose.runtime.Immutable public final class HorizontalAlign {
@@ -875,16 +874,15 @@
   }
 
   @kotlin.jvm.JvmInline public final value class Skip {
-    ctor public Skip(int position, int size);
-    ctor public Skip(int position, int rows, int columns);
-    ctor public Skip(String description);
+    ctor public Skip(@IntRange(from=0L) int position, @IntRange(from=1L) int size);
+    ctor public Skip(@IntRange(from=0L) int position, @IntRange(from=1L) int rows, @IntRange(from=1L) int columns);
     method public String getDescription();
     property public final String description;
   }
 
   @kotlin.jvm.JvmInline public final value class Span {
-    ctor public Span(int position, int size);
-    ctor public Span(int position, int rows, int columns);
+    ctor public Span(@IntRange(from=0L) int position, @IntRange(from=1L) int size);
+    ctor public Span(@IntRange(from=0L) int position, @IntRange(from=1L) int rows, @IntRange(from=1L) int columns);
     ctor public Span(String description);
     method public String getDescription();
     property public final String description;
diff --git a/constraintlayout/constraintlayout-compose/build.gradle b/constraintlayout/constraintlayout-compose/build.gradle
index bcb8c0f..99ecbd1 100644
--- a/constraintlayout/constraintlayout-compose/build.gradle
+++ b/constraintlayout/constraintlayout-compose/build.gradle
@@ -35,13 +35,13 @@
     sourceSets {
         commonMain {
             dependencies {
-                implementation(project(":compose:ui:ui"))
-                implementation(project(":compose:ui:ui-unit"))
-                implementation(project(":compose:ui:ui-util"))
-                implementation(project(":compose:foundation:foundation"))
-                implementation(project(":compose:foundation:foundation-layout"))
+                implementation("androidx.compose.ui:ui:1.7.0-beta04")
+                implementation("androidx.compose.ui:ui-unit:1.7.0-beta04")
+                implementation("androidx.compose.ui:ui-util:1.7.0-beta04")
+                implementation("androidx.compose.foundation:foundation:1.7.0-beta04")
+                implementation("androidx.compose.foundation:foundation-layout:1.7.0-beta04")
                 implementation(project(":constraintlayout:constraintlayout-core"))
-                implementation(project(":collection:collection"))
+                implementation("androidx.collection:collection:1.4.0")
             }
         }
 
diff --git a/constraintlayout/constraintlayout-compose/src/androidInstrumentedTest/kotlin/androidx/constraintlayout/compose/ConstraintLayoutTest.kt b/constraintlayout/constraintlayout-compose/src/androidInstrumentedTest/kotlin/androidx/constraintlayout/compose/ConstraintLayoutTest.kt
index 8d3c0fee..e7f7289 100644
--- a/constraintlayout/constraintlayout-compose/src/androidInstrumentedTest/kotlin/androidx/constraintlayout/compose/ConstraintLayoutTest.kt
+++ b/constraintlayout/constraintlayout-compose/src/androidInstrumentedTest/kotlin/androidx/constraintlayout/compose/ConstraintLayoutTest.kt
@@ -21,6 +21,7 @@
 import androidx.compose.animation.core.tween
 import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.IntrinsicSize
 import androidx.compose.foundation.layout.aspectRatio
 import androidx.compose.foundation.layout.fillMaxSize
@@ -30,6 +31,8 @@
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.layout.width
 import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
@@ -60,12 +63,14 @@
 import androidx.compose.ui.test.captureToImage
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.unit.Constraints
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.IntOffset
 import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.round
+import androidx.compose.ui.util.fastRoundToInt
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
@@ -2367,6 +2372,88 @@
             assertEquals(expectedEndPosition, box0Position)
         }
 
+    @Test
+    fun testEmptyConstraintLayoutSize() =
+        with(rule.density) {
+            val rootSizePx = 200f
+
+            // Mutable state to trigger invalidations. By default simply passes original
+            // constraints.
+            // But we'll use this to test empty ConstraintLayout under different constraints
+            var transformConstraints: ((Constraints) -> Constraints) by
+                mutableStateOf({ constraints -> constraints })
+
+            // To capture measured ConstraintLayout size
+            var layoutSize = IntSize(-1, -1)
+
+            rule.setContent {
+                Column(Modifier.size(rootSizePx.toDp()).verticalScroll(rememberScrollState())) {
+                    ConstraintLayout(
+                        modifier =
+                            Modifier.layout { measurable, constraints ->
+                                    // Measure policy to test ConstraintLayout under different
+                                    // constraints
+                                    val placeable =
+                                        measurable.measure(transformConstraints(constraints))
+                                    layout(placeable.width, placeable.height) {
+                                        placeable.place(0, 0)
+                                    }
+                                }
+                                .onGloballyPositioned { layoutSize = it.size }
+                    ) {
+                        // Empty content
+                    }
+                }
+            }
+            // For this case, the default behavior should be a ConstraintLayout of size 0x0
+            rule.waitForIdle()
+            assertEquals(IntSize.Zero, layoutSize)
+
+            // Test with min constraints
+            transformConstraints = { constraints ->
+                // Demonstrate that vertical scroll constraints propagate
+                assert(constraints.maxHeight == Constraints.Infinity)
+                constraints.copy(minWidth = 123, minHeight = 321)
+            }
+            rule.waitForIdle()
+
+            // Minimum size is preferred for empty layouts. Should not crash :)
+            assertEquals(IntSize(width = 123, height = 321), layoutSize)
+
+            // Transform to an equivalent of fillMaxSize(), which fills bounded constraints only
+            transformConstraints = { constraints ->
+                val minWidth: Int
+                val maxWidth: Int
+                val minHeight: Int
+                val maxHeight: Int
+
+                if (constraints.hasBoundedWidth) {
+                    minWidth = constraints.maxWidth
+                    maxWidth = constraints.maxWidth
+                } else {
+                    minWidth = constraints.minWidth
+                    maxWidth = constraints.maxWidth
+                }
+                if (constraints.hasBoundedHeight) {
+                    minHeight = constraints.maxHeight
+                    maxHeight = constraints.maxHeight
+                } else {
+                    minHeight = constraints.minHeight
+                    maxHeight = constraints.maxHeight
+                }
+                Constraints(
+                    minWidth = minWidth,
+                    maxWidth = maxWidth,
+                    minHeight = minHeight,
+                    maxHeight = maxHeight
+                )
+            }
+            rule.waitForIdle()
+
+            // Vertical is infinity, fillMaxSize behavior should pin it to minimum height (Zero)
+            assertEquals(IntSize(rootSizePx.fastRoundToInt(), 0), layoutSize)
+        }
+
     /**
      * Provides a list constraints combination for horizontal anchors: `start`, `end`,
      * `absoluteLeft`, `absoluteRight`.
diff --git a/constraintlayout/constraintlayout-compose/src/androidInstrumentedTest/kotlin/androidx/constraintlayout/compose/GridDslTest.kt b/constraintlayout/constraintlayout-compose/src/androidInstrumentedTest/kotlin/androidx/constraintlayout/compose/GridDslTest.kt
index 6971f0a..6d130abe 100644
--- a/constraintlayout/constraintlayout-compose/src/androidInstrumentedTest/kotlin/androidx/constraintlayout/compose/GridDslTest.kt
+++ b/constraintlayout/constraintlayout-compose/src/androidInstrumentedTest/kotlin/androidx/constraintlayout/compose/GridDslTest.kt
@@ -22,9 +22,7 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.layout.layoutId
 import androidx.compose.ui.platform.isDebugInspectorInfoEnabled
-import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.test.assertPositionInRootIsEqualTo
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.test.onNodeWithTag
@@ -63,23 +61,21 @@
         rule.setContent {
             gridComposableTest(
                 modifier = Modifier.size(rootSize),
-                boxesCount = boxesCount,
-                gridOrientation = 0,
                 numRows = rows,
                 numColumns = columns,
-                hGap = 0,
-                vGap = 0,
                 gridSpans = arrayOf(),
                 gridSkips = arrayOf(),
-                gridRowWeights = intArrayOf(),
-                gridColumnWeights = intArrayOf(),
-                gridFlags = arrayOf(),
+                gridRowWeights = floatArrayOf(),
+                gridColumnWeights = floatArrayOf(),
+                boxesCount = boxesCount,
+                isHorizontalArrangement = true,
+                gridFlags = GridFlags.None,
             )
         }
         var leftX = 0.dp
         var topY = 0.dp
-        var rightX: Dp
-        var bottomY: Dp
+        val rightX: Dp
+        val bottomY: Dp
 
         // 10.dp is the size of a singular box
         val gapSize = (rootSize - (10.dp * 2f)) / (columns * 2f)
@@ -103,23 +99,21 @@
         rule.setContent {
             gridComposableTest(
                 modifier = Modifier.size(rootSize),
-                boxesCount = boxesCount,
-                gridOrientation = 1,
                 numRows = rows,
                 numColumns = columns,
-                hGap = 0,
-                vGap = 0,
                 gridSpans = arrayOf(),
                 gridSkips = arrayOf(),
-                gridRowWeights = intArrayOf(),
-                gridColumnWeights = intArrayOf(),
-                gridFlags = arrayOf(),
+                gridRowWeights = floatArrayOf(),
+                gridColumnWeights = floatArrayOf(),
+                boxesCount = boxesCount,
+                isHorizontalArrangement = false,
+                gridFlags = GridFlags.None,
             )
         }
         var leftX = 0.dp
         var topY = 0.dp
-        var rightX: Dp
-        var bottomY: Dp
+        val rightX: Dp
+        val bottomY: Dp
 
         // 10.dp is the size of a singular box
         val gapSize = (rootSize - (10.dp * 2f)) / (columns * 2f)
@@ -143,17 +137,15 @@
         rule.setContent {
             gridComposableTest(
                 modifier = Modifier.size(rootSize),
-                boxesCount = boxesCount,
-                gridOrientation = 0,
                 numRows = rows,
                 numColumns = columns,
-                hGap = 0,
-                vGap = 0,
                 gridSpans = arrayOf(),
                 gridSkips = arrayOf(),
-                gridRowWeights = intArrayOf(),
-                gridColumnWeights = intArrayOf(),
-                gridFlags = arrayOf(),
+                gridRowWeights = floatArrayOf(),
+                gridColumnWeights = floatArrayOf(),
+                boxesCount = boxesCount,
+                isHorizontalArrangement = true,
+                gridFlags = GridFlags.None,
             )
         }
         var expectedX = 0.dp
@@ -183,17 +175,15 @@
         rule.setContent {
             gridComposableTest(
                 modifier = Modifier.size(rootSize),
-                boxesCount = boxesCount,
-                gridOrientation = 0,
                 numRows = rows,
                 numColumns = columns,
-                hGap = 0,
-                vGap = 0,
                 gridSpans = arrayOf(),
                 gridSkips = arrayOf(),
-                gridRowWeights = intArrayOf(),
-                gridColumnWeights = intArrayOf(),
-                gridFlags = arrayOf(),
+                gridRowWeights = floatArrayOf(),
+                gridColumnWeights = floatArrayOf(),
+                boxesCount = boxesCount,
+                isHorizontalArrangement = true,
+                gridFlags = GridFlags.None,
             )
         }
         var expectedX = 0.dp
@@ -223,23 +213,21 @@
         rule.setContent {
             gridComposableTest(
                 modifier = Modifier.size(rootSize),
-                boxesCount = boxesCount,
-                gridOrientation = 0,
                 numRows = rows,
                 numColumns = columns,
-                hGap = 0,
-                vGap = 0,
                 gridSpans = arrayOf(),
                 gridSkips = arrayOf(Skip(0, 1, 1)),
-                gridRowWeights = intArrayOf(),
-                gridColumnWeights = intArrayOf(),
-                gridFlags = arrayOf(),
+                gridRowWeights = floatArrayOf(),
+                gridColumnWeights = floatArrayOf(),
+                boxesCount = boxesCount,
+                isHorizontalArrangement = true,
+                gridFlags = GridFlags.None,
             )
         }
         var leftX = 0.dp
         var topY = 0.dp
-        var rightX: Dp
-        var bottomY: Dp
+        val rightX: Dp
+        val bottomY: Dp
 
         // 10.dp is the size of a singular box
         val gapSize = (rootSize - (10.dp * 2f)) / (columns * 2f)
@@ -262,23 +250,21 @@
         rule.setContent {
             gridComposableTest(
                 modifier = Modifier.size(rootSize),
-                boxesCount = boxesCount,
-                gridOrientation = 0,
                 numRows = rows,
                 numColumns = columns,
-                hGap = 0,
-                vGap = 0,
                 gridSpans = arrayOf(),
                 gridSkips = arrayOf(Skip(0, 2, 1)),
-                gridRowWeights = intArrayOf(),
-                gridColumnWeights = intArrayOf(),
-                gridFlags = arrayOf(GridFlag.SpansRespectWidgetOrder, GridFlag.SubGridByColRow)
+                gridRowWeights = floatArrayOf(),
+                gridColumnWeights = floatArrayOf(),
+                boxesCount = boxesCount,
+                isHorizontalArrangement = true,
+                gridFlags = GridFlags(isSubGridByColRow = true)
             )
         }
         var leftX = 0.dp
         var topY = 0.dp
-        var rightX: Dp
-        var bottomY: Dp
+        val rightX: Dp
+        val bottomY: Dp
 
         // 10.dp is the size of a singular box
         val gapSize = (rootSize - (10.dp * 2f)) / (columns * 2f)
@@ -300,26 +286,24 @@
         rule.setContent {
             gridComposableTest(
                 modifier = Modifier.size(rootSize),
-                boxesCount = boxesCount,
-                gridOrientation = 0,
                 numRows = rows,
                 numColumns = columns,
-                hGap = 0,
-                vGap = 0,
                 gridSpans = arrayOf(Span(0, 1, 2)),
                 gridSkips = arrayOf(),
-                gridRowWeights = intArrayOf(),
-                gridColumnWeights = intArrayOf(),
-                gridFlags = arrayOf(),
+                gridRowWeights = floatArrayOf(),
+                gridColumnWeights = floatArrayOf(),
+                boxesCount = boxesCount,
+                isHorizontalArrangement = true,
+                gridFlags = GridFlags.None,
             )
         }
         var leftX = 0.dp
         var topY = 0.dp
-        var rightX: Dp
-        var bottomY: Dp
+        val rightX: Dp
+        val bottomY: Dp
 
         // 10.dp is the size of a singular box
-        var spanLeft = (rootSize - 10.dp) / 2f
+        val spanLeft = (rootSize - 10.dp) / 2f
         val gapSize = (rootSize - (10.dp * 2f)) / (columns * 2f)
         rule.waitForIdle()
         leftX += gapSize
@@ -332,6 +316,46 @@
     }
 
     @Test
+    fun testSpans_placeOnSpansFirstFlag() {
+        val rootSize = 200.dp
+        val boxesCount = 3
+        val rows = 2
+        val columns = 2
+        rule.setContent {
+            gridComposableTest(
+                modifier = Modifier.size(rootSize),
+                numRows = rows,
+                numColumns = columns,
+                gridSpans = arrayOf(Span(2, 1, 2)),
+                gridSkips = arrayOf(),
+                gridRowWeights = floatArrayOf(),
+                gridColumnWeights = floatArrayOf(),
+                boxesCount = boxesCount,
+                isHorizontalArrangement = true,
+                gridFlags = GridFlags.PlaceLayoutsOnSpansFirst,
+            )
+        }
+        var leftX = 0.dp
+        var topY = 0.dp
+
+        // 10.dp is the size of a singular box
+        val gapSize = (rootSize - (10.dp * 2f)) / (columns * 2f)
+        rule.waitForIdle()
+        leftX += gapSize
+        topY += gapSize
+        // Because of the flag, box0 is first positioned on the Span, which is on cells 2 and 3
+        // So the boxes at cells 0 and 1 are box1 and box2 respectively.
+        rule.onNodeWithTag("box1").assertPositionInRootIsEqualTo(leftX, topY)
+        leftX += 10.dp + gapSize + gapSize
+        rule.onNodeWithTag("box2").assertPositionInRootIsEqualTo(leftX, topY)
+
+        // Layout is centered within the span
+        val spanLeft = (rootSize - 10.dp) / 2f
+        topY += 10.dp + gapSize + gapSize
+        rule.onNodeWithTag("box0").assertPositionInRootIsEqualTo(spanLeft, topY)
+    }
+
+    @Test
     fun testMultipleSpans() {
         val rootSize = 200.dp
         val boxesCount = 2
@@ -340,24 +364,22 @@
         rule.setContent {
             gridComposableTest(
                 modifier = Modifier.size(rootSize),
-                boxesCount = boxesCount,
-                gridOrientation = 0,
                 numRows = rows,
                 numColumns = columns,
-                hGap = 0,
-                vGap = 0,
                 gridSpans = arrayOf(Span(2, 1, 2), Span(0, 1, 2)),
                 gridSkips = arrayOf(),
-                gridRowWeights = intArrayOf(),
-                gridColumnWeights = intArrayOf(),
-                gridFlags = arrayOf(GridFlag.SpansRespectWidgetOrder),
+                gridRowWeights = floatArrayOf(),
+                gridColumnWeights = floatArrayOf(),
+                boxesCount = boxesCount,
+                isHorizontalArrangement = true,
+                gridFlags = GridFlags.None,
             )
         }
         var topY = 0.dp
-        var bottomY: Dp
+        val bottomY: Dp
 
         // 10.dp is the size of a singular box
-        var spanLeft = (rootSize - 10.dp) / 2f
+        val spanLeft = (rootSize - 10.dp) / 2f
         val gapSize = (rootSize - (10.dp * 2f)) / (columns * 2f)
         rule.waitForIdle()
         topY += gapSize
@@ -375,26 +397,24 @@
         rule.setContent {
             gridComposableTest(
                 modifier = Modifier.size(rootSize),
-                boxesCount = boxesCount,
-                gridOrientation = 0,
                 numRows = rows,
                 numColumns = columns,
-                hGap = 0,
-                vGap = 0,
                 gridSpans = arrayOf(Span(1, 2, 1)),
                 gridSkips = arrayOf(),
-                gridRowWeights = intArrayOf(),
-                gridColumnWeights = intArrayOf(),
-                gridFlags = arrayOf(GridFlag.SpansRespectWidgetOrder),
+                gridRowWeights = floatArrayOf(),
+                gridColumnWeights = floatArrayOf(),
+                boxesCount = boxesCount,
+                isHorizontalArrangement = true,
+                gridFlags = GridFlags.None,
             )
         }
         var leftX = 0.dp
         var topY = 0.dp
-        var rightX: Dp
-        var bottomY: Dp
+        val rightX: Dp
+        val bottomY: Dp
 
         // 10.dp is the size of a singular box
-        var spanTop = (rootSize - 10.dp) / 2f
+        val spanTop = (rootSize - 10.dp) / 2f
         val gapSize = (rootSize - (10.dp * 2f)) / (columns * 2f)
         rule.waitForIdle()
         leftX += gapSize
@@ -415,26 +435,24 @@
         rule.setContent {
             gridComposableTest(
                 modifier = Modifier.size(rootSize),
-                boxesCount = boxesCount,
-                gridOrientation = 0,
                 numRows = rows,
                 numColumns = columns,
-                hGap = 0,
-                vGap = 0,
                 gridSpans = arrayOf(Span(0, 2, 1)),
                 gridSkips = arrayOf(),
-                gridRowWeights = intArrayOf(),
-                gridColumnWeights = intArrayOf(),
-                gridFlags = arrayOf(GridFlag.SubGridByColRow),
+                gridRowWeights = floatArrayOf(),
+                gridColumnWeights = floatArrayOf(),
+                boxesCount = boxesCount,
+                isHorizontalArrangement = true,
+                gridFlags = GridFlags(isSubGridByColRow = true),
             )
         }
         var leftX = 0.dp
         var topY = 0.dp
-        var rightX: Dp
-        var bottomY: Dp
+        val rightX: Dp
+        val bottomY: Dp
 
         // 10.dp is the size of a singular box
-        var spanLeft = (rootSize - 10.dp) / 2f
+        val spanLeft = (rootSize - 10.dp) / 2f
         val gapSize = (rootSize - (10.dp * 2f)) / (columns * 2f)
         rule.waitForIdle()
         leftX += gapSize
@@ -452,24 +470,22 @@
         val boxesCount = 2
         val rows = 0
         val columns = 1
-        val weights = intArrayOf(1, 3)
+        val weights = floatArrayOf(1f, 3f)
         rule.setContent {
             gridComposableTest(
                 modifier = Modifier.size(rootSize),
-                boxesCount = boxesCount,
-                gridOrientation = 0,
                 numRows = rows,
                 numColumns = columns,
-                hGap = 0,
-                vGap = 0,
                 gridSpans = arrayOf(),
                 gridSkips = arrayOf(),
                 gridRowWeights = weights,
-                gridColumnWeights = intArrayOf(),
-                gridFlags = arrayOf(),
+                gridColumnWeights = floatArrayOf(),
+                boxesCount = boxesCount,
+                isHorizontalArrangement = true,
+                gridFlags = GridFlags.None,
             )
         }
-        var expectedLeft = (rootSize - 10.dp) / 2f
+        val expectedLeft = (rootSize - 10.dp) / 2f
         var expectedTop = 0.dp
 
         // 10.dp is the size of a singular box
@@ -490,25 +506,23 @@
         val boxesCount = 2
         val rows = 1
         val columns = 0
-        val weights = intArrayOf(1, 3)
+        val weights = floatArrayOf(1f, 3f)
         rule.setContent {
             gridComposableTest(
                 modifier = Modifier.size(rootSize),
-                boxesCount = boxesCount,
-                gridOrientation = 0,
                 numRows = rows,
                 numColumns = columns,
-                hGap = 0,
-                vGap = 0,
                 gridSpans = arrayOf(),
                 gridSkips = arrayOf(),
-                gridRowWeights = intArrayOf(),
+                gridRowWeights = floatArrayOf(),
                 gridColumnWeights = weights,
-                gridFlags = arrayOf(),
+                boxesCount = boxesCount,
+                isHorizontalArrangement = true,
+                gridFlags = GridFlags.None,
             )
         }
         var expectedLeft = 0.dp
-        var expectedTop = (rootSize - 10.dp) / 2f
+        val expectedTop = (rootSize - 10.dp) / 2f
 
         // 10.dp is the size of a singular box
         // first box takes the 1/4 of the width
@@ -557,13 +571,11 @@
         numColumns: Int,
         gridSpans: Array<Span>,
         gridSkips: Array<Skip>,
-        gridRowWeights: IntArray,
-        gridColumnWeights: IntArray,
+        gridRowWeights: FloatArray,
+        gridColumnWeights: FloatArray,
         boxesCount: Int,
-        gridOrientation: Int,
-        vGap: Int,
-        hGap: Int,
-        gridFlags: Array<GridFlag>,
+        isHorizontalArrangement: Boolean,
+        gridFlags: GridFlags,
     ) {
         ConstraintLayout(
             ConstraintSet {
@@ -576,13 +588,11 @@
                 val g1 =
                     createGrid(
                         elements = elem.toTypedArray(),
-                        orientation = gridOrientation,
+                        isHorizontalArrangement = isHorizontalArrangement,
                         skips = gridSkips,
                         spans = gridSpans,
                         rows = numRows,
                         columns = numColumns,
-                        verticalGap = vGap.dp,
-                        horizontalGap = hGap.dp,
                         rowWeights = gridRowWeights,
                         columnWeights = gridColumnWeights,
                         flags = gridFlags,
@@ -595,9 +605,7 @@
             modifier = modifier
         ) {
             val ids = (0 until boxesCount).map { "box$it" }.toTypedArray()
-            ids.forEach { id ->
-                Box(Modifier.layoutId(id).background(Color.Red).testTag(id).size(10.dp))
-            }
+            ids.forEach { id -> Box(Modifier.layoutTestId(id).background(Color.Red).size(10.dp)) }
         }
     }
 
@@ -621,8 +629,8 @@
                         d,
                         rows = 2,
                         columns = 2,
-                        verticalGap = vGap.dp,
-                        horizontalGap = hGap.dp,
+                        verticalSpacing = vGap.dp,
+                        horizontalSpacing = hGap.dp,
                     )
                 constrain(g1) {
                     width = Dimension.matchParent
@@ -648,9 +656,7 @@
             modifier = modifier,
         ) {
             val ids = (0 until 4).map { "box$it" }.toTypedArray()
-            ids.forEach { id ->
-                Box(Modifier.layoutId(id).background(Color.Red).testTag(id).size(10.dp))
-            }
+            ids.forEach { id -> Box(Modifier.layoutTestId(id).background(Color.Red).size(10.dp)) }
         }
     }
 }
diff --git a/constraintlayout/constraintlayout-compose/src/androidInstrumentedTest/kotlin/androidx/constraintlayout/compose/RowColumnDslTest.kt b/constraintlayout/constraintlayout-compose/src/androidInstrumentedTest/kotlin/androidx/constraintlayout/compose/RowColumnDslTest.kt
index e3da17a..cf918c0 100644
--- a/constraintlayout/constraintlayout-compose/src/androidInstrumentedTest/kotlin/androidx/constraintlayout/compose/RowColumnDslTest.kt
+++ b/constraintlayout/constraintlayout-compose/src/androidInstrumentedTest/kotlin/androidx/constraintlayout/compose/RowColumnDslTest.kt
@@ -16,15 +16,16 @@
 
 package androidx.constraintlayout.compose
 
+import androidx.collection.IntSet
+import androidx.collection.emptyIntSet
+import androidx.collection.intSetOf
 import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.size
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.layout.layoutId
 import androidx.compose.ui.platform.isDebugInspectorInfoEnabled
-import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.test.assertPositionInRootIsEqualTo
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.test.onNodeWithTag
@@ -60,11 +61,9 @@
         rule.setContent {
             ColumnComposableTest(
                 modifier = Modifier.size(rootSize),
-                gridSkips = arrayOf(),
-                gridSpans = arrayOf(),
+                weights = floatArrayOf(),
+                skipIndices = emptyIntSet(),
                 boxesCount = boxesCount,
-                vGap = 0,
-                gridRowWeights = intArrayOf(),
             )
         }
         var expectedX = 0.dp
@@ -92,11 +91,10 @@
         rule.setContent {
             ColumnComposableTest(
                 modifier = Modifier.size(rootSize),
-                gridSkips = arrayOf(Skip(1, 2)),
-                gridSpans = arrayOf(),
+                weights = floatArrayOf(),
+                // Represents `Skip(position = 1, size = 2)`
+                skipIndices = intSetOf(1, 2),
                 boxesCount = boxesCount,
-                vGap = 0,
-                gridRowWeights = intArrayOf(),
             )
         }
         var expectedX = 0.dp
@@ -126,11 +124,9 @@
         rule.setContent {
             ColumnComposableTest(
                 modifier = Modifier.size(rootSize),
-                gridSkips = arrayOf(),
-                gridSpans = arrayOf(Span(0, 2)),
+                weights = floatArrayOf(2f, 1f, 1f, 1f),
+                skipIndices = emptyIntSet(),
                 boxesCount = boxesCount,
-                vGap = 0,
-                gridRowWeights = intArrayOf(),
             )
         }
 
@@ -158,11 +154,9 @@
         rule.setContent {
             RowComposableTest(
                 modifier = Modifier.size(rootSize),
-                gridSkips = arrayOf(),
-                gridSpans = arrayOf(),
+                weights = floatArrayOf(),
+                skipIndices = emptyIntSet(),
                 boxesCount = boxesCount,
-                hGap = 0,
-                gridColumnWeights = intArrayOf()
             )
         }
         var expectedX = 0.dp
@@ -190,11 +184,10 @@
         rule.setContent {
             RowComposableTest(
                 modifier = Modifier.size(rootSize),
-                gridSkips = arrayOf(Skip(1, 2)),
-                gridSpans = arrayOf(),
+                weights = floatArrayOf(),
+                // Represents `Skip(position = 1, size = 2)`
+                skipIndices = intSetOf(1, 2),
                 boxesCount = boxesCount,
-                hGap = 0,
-                gridColumnWeights = intArrayOf()
             )
         }
         var expectedX = 0.dp
@@ -224,11 +217,9 @@
         rule.setContent {
             RowComposableTest(
                 modifier = Modifier.size(rootSize),
-                gridSkips = arrayOf(),
-                gridSpans = arrayOf(Span(0, 2)),
+                weights = floatArrayOf(2f, 1f, 1f, 1f),
+                skipIndices = emptyIntSet(),
                 boxesCount = boxesCount,
-                hGap = 0,
-                gridColumnWeights = intArrayOf()
             )
         }
 
@@ -253,28 +244,29 @@
     @Composable
     private fun ColumnComposableTest(
         modifier: Modifier = Modifier,
-        gridSkips: Array<Skip>,
-        gridSpans: Array<Span>,
-        gridRowWeights: IntArray,
+        weights: FloatArray,
+        skipIndices: IntSet,
         boxesCount: Int,
-        vGap: Int,
     ) {
         ConstraintLayout(
             ConstraintSet {
-                val ids = (0 until boxesCount).map { "box$it" }.toTypedArray()
-                val elem = arrayListOf<LayoutReference>()
-                for (i in ids.indices) {
-                    elem.add(createRefFor(ids[i]))
-                }
+                // We consider the skips as fake boxes, so we need them as references
+                val totalBoxes = boxesCount + skipIndices.size
+                // Track "skipped" boxes to properly assign all incremental `id` to the boxes
+                var skipCount = 0
 
-                val g1 =
-                    createColumn(
-                        elements = elem.toTypedArray(),
-                        skips = gridSkips,
-                        spans = gridSpans,
-                        verticalGap = vGap.dp,
-                        rowWeights = gridRowWeights,
-                    )
+                val ids =
+                    Array(totalBoxes) { index ->
+                        if (skipIndices.contains(index)) {
+                            skipCount++
+                            createRefFor("placeholder")
+                        } else {
+                            createRefFor("box${index - skipCount}")
+                        }
+                    }
+
+                val g1 = createColumn(elements = ids, weights = weights)
+
                 constrain(g1) {
                     width = Dimension.matchParent
                     height = Dimension.matchParent
@@ -282,9 +274,8 @@
             },
             modifier = modifier
         ) {
-            val ids = (0 until boxesCount).map { "box$it" }.toTypedArray()
-            ids.forEach { id ->
-                Box(Modifier.layoutId(id).background(Color.Red).testTag(id).size(10.dp))
+            repeat(boxesCount) {
+                Box(Modifier.layoutTestId("box$it").background(Color.Red).size(10.dp))
             }
         }
     }
@@ -292,27 +283,31 @@
     @Composable
     private fun RowComposableTest(
         modifier: Modifier = Modifier,
-        gridSkips: Array<Skip>,
-        gridSpans: Array<Span>,
-        gridColumnWeights: IntArray,
+        weights: FloatArray,
+        skipIndices: IntSet,
         boxesCount: Int,
-        hGap: Int,
     ) {
         ConstraintLayout(
             ConstraintSet {
-                val ids = (0 until boxesCount).map { "box$it" }.toTypedArray()
-                val elem = arrayListOf<LayoutReference>()
-                for (i in ids.indices) {
-                    elem.add(createRefFor(ids[i]))
-                }
+                // We consider the skips as fake boxes, so we need them as references
+                val totalBoxes = boxesCount + skipIndices.size
+                // Track "skipped" boxes to properly assign all incremental `id` to the boxes
+                var skipCount = 0
+
+                val ids =
+                    Array(totalBoxes) { index ->
+                        if (skipIndices.contains(index)) {
+                            skipCount++
+                            createRefFor("placeholder")
+                        } else {
+                            createRefFor("box${index - skipCount}")
+                        }
+                    }
 
                 val g1 =
                     createRow(
-                        elements = elem.toTypedArray(),
-                        horizontalGap = hGap.dp,
-                        skips = gridSkips,
-                        spans = gridSpans,
-                        columnWeights = gridColumnWeights,
+                        elements = ids,
+                        weights = weights,
                     )
                 constrain(g1) {
                     width = Dimension.matchParent
@@ -321,9 +316,8 @@
             },
             modifier = modifier
         ) {
-            val ids = (0 until boxesCount).map { "box$it" }.toTypedArray()
-            ids.forEach { id ->
-                Box(Modifier.layoutId(id).background(Color.Red).testTag(id).size(10.dp))
+            repeat(boxesCount) {
+                Box(Modifier.layoutTestId("box$it").background(Color.Red).size(10.dp))
             }
         }
     }
diff --git a/constraintlayout/constraintlayout-compose/src/androidMain/kotlin/androidx/constraintlayout/compose/ConstraintLayout.kt b/constraintlayout/constraintlayout-compose/src/androidMain/kotlin/androidx/constraintlayout/compose/ConstraintLayout.kt
index 1f6a346..04acd28 100644
--- a/constraintlayout/constraintlayout-compose/src/androidMain/kotlin/androidx/constraintlayout/compose/ConstraintLayout.kt
+++ b/constraintlayout/constraintlayout-compose/src/androidMain/kotlin/androidx/constraintlayout/compose/ConstraintLayout.kt
@@ -1874,6 +1874,13 @@
         measurables: List<Measurable>,
         optimizationLevel: Int
     ): IntSize {
+        if (measurables.isEmpty()) {
+            // TODO(b/335524398): Behavior with zero children is unexpected. It's also inconsistent
+            //      with ViewGroup, so this is a workaround to handle those cases the way it seems
+            //      right for this implementation.
+            return IntSize(constraints.minWidth, constraints.minHeight)
+        }
+
         // Define the size of the ConstraintLayout.
         state.width(
             if (constraints.hasFixedWidth) {
diff --git a/constraintlayout/constraintlayout-compose/src/androidMain/kotlin/androidx/constraintlayout/compose/ConstraintLayoutBaseScope.kt b/constraintlayout/constraintlayout-compose/src/androidMain/kotlin/androidx/constraintlayout/compose/ConstraintLayoutBaseScope.kt
index df42a89..d4868c6 100644
--- a/constraintlayout/constraintlayout-compose/src/androidMain/kotlin/androidx/constraintlayout/compose/ConstraintLayoutBaseScope.kt
+++ b/constraintlayout/constraintlayout-compose/src/androidMain/kotlin/androidx/constraintlayout/compose/ConstraintLayoutBaseScope.kt
@@ -16,6 +16,8 @@
 
 package androidx.constraintlayout.compose
 
+import android.annotation.SuppressLint
+import androidx.annotation.IntRange
 import androidx.compose.runtime.Immutable
 import androidx.compose.runtime.Stable
 import androidx.compose.ui.layout.FirstBaseline
@@ -27,6 +29,8 @@
 import androidx.constraintlayout.core.parser.CLObject
 import androidx.constraintlayout.core.parser.CLString
 import androidx.constraintlayout.core.state.ConstraintSetParser
+import androidx.constraintlayout.core.utils.GridCore
+import org.jetbrains.annotations.TestOnly
 
 /**
  * Common scope for [ConstraintLayoutScope] and [ConstraintSetScope], the content being shared
@@ -640,396 +644,304 @@
 
     /**
      * Creates a Grid based helper that lays out its elements in a single Row. Example:
-     * ConstraintLayout( ConstraintSet { val a = createRefFor("1") val b = createRefFor("2") val c =
-     * createRefFor("3") val d = createRefFor("4") val e = createRefFor("5") val weights =
-     * intArrayOf(3, 3, 2, 2, 1) val g1 = createRow( a, b, c, d, e, skips = arrayOf(Skip(1, 1),
-     * Skip(3, 2)), spans = arrayOf(Span(1, 2)), horizontalGap = 10.dp, columnWeights = weights,
-     * padding = 10.dp, ) constrain(g1) { width = Dimension.matchParent height =
-     * Dimension.matchParent }, modifier = Modifier.fillMaxSize() ) { val numArray = arrayOf("1",
-     * "2", "3", "4", "5") for (num in numArray) { Button( modifier =
-     * Modifier.layoutId(num).width(120.dp), onClick = {}, ) { Text(text = String.format("btn%s",
-     * num)) } } }
+     * ```
+     * ConstraintLayout(
+     *     constraintSet = ConstraintSet {
+     *         val (a, b, c, d, e) = createRefsFor(0, 1, 2, 3, 4)
+     *         val row = createRow(
+     *             a, b, c, d, e,
+     *             spacing = 10.dp,
+     *             weights = floatArrayOf(3f, 3f, 2f, 2f, 1f),
+     *         )
+     *         constrain(row) {
+     *             width = Dimension.matchParent
+     *             height = Dimension.matchParent
+     *         }
      *
-     * @param elements [LayoutReference]s to be laid out by the Grid helper
-     * @param skips specify area(s) in a Row to be skipped - format: Skip(index, size)
-     * @param spans specify area(s) in a Row to be spanned - format: Span(index, size)
-     * @param horizontalGap defines the gap between views in the x axis
-     * @param columnWeights defines the weight of each column
-     * @param padding sets padding around the content
+     *         constrain(a, b, c, d, e) {
+     *             width = Dimension.fillToConstraints
+     *         }
+     *     },
+     *     modifier = Modifier.fillMaxSize()
+     * ) {
+     *     repeat(5) {
+     *         Text(
+     *             text = "item$it",
+     *             modifier = Modifier
+     *                 .layoutId(it)
+     *                 .background(Color.LightGray)
+     *         )
+     *     }
+     * }
+     * ```
+     *
+     * @param elements [LayoutReference]s to be laid out by the Grid-based Row helper.
+     * @param spacing Defines the horizontal spacing between each item in the Row.
+     * @param weights Defines the weight for each element in the Row. Note that the number of
+     *   weights provided are expected to match the number of [elements] given. Otherwise, weights
+     *   will be automatically appended (with a value of `1`), or trimmed to match the number of
+     *   given [elements].
+     * @see createGrid
      */
+    @SuppressLint("Range") // Enables internal grid mode for row and column
     fun createRow(
         vararg elements: LayoutReference,
-        skips: Array<Skip> = arrayOf(),
-        spans: Array<Span> = arrayOf(),
-        horizontalGap: Dp = 0.dp,
-        columnWeights: IntArray = intArrayOf(),
-        padding: Dp = 0.dp,
+        spacing: Dp = 0.dp,
+        weights: FloatArray = floatArrayOf(),
     ): ConstrainedLayoutReference {
         return createGrid(
             elements = elements,
             rows = 1,
-            skips = skips,
-            spans = spans,
-            horizontalGap = horizontalGap,
-            columnWeights = columnWeights,
-            paddingStart = padding,
-            paddingTop = padding,
-            paddingEnd = padding,
-            paddingBottom = padding,
+            columns = 0,
+            horizontalSpacing = spacing,
+            columnWeights = weights,
         )
     }
 
     /**
-     * Creates a Grid based helper that lays out its elements in a single Row. Example:
-     * ConstraintLayout( ConstraintSet { val a = createRefFor("1") val b = createRefFor("2") val c =
-     * createRefFor("3") val d = createRefFor("4") val e = createRefFor("5") val weights =
-     * intArrayOf(3, 3, 2, 2, 1) val g1 = createRow( a, b, c, d, e, skips = arrayOf(Skip(1, 1),
-     * Skip(3, 2)), spans = arrayOf(Span(1, 2)), horizontalGap = 10.dp, columnWeights = weights,
-     * paddingHorizontal = 10.dp, paddingVertical = 10.dp, ) constrain(g1) { width =
-     * Dimension.matchParent height = Dimension.matchParent }, modifier = Modifier.fillMaxSize() ) {
-     * val numArray = arrayOf("1", "2", "3", "4", "5") for (num in numArray) { Button( modifier =
-     * Modifier.layoutId(num).width(120.dp), onClick = {}, ) { Text(text = String.format("btn%s",
-     * num)) } } }
+     * Creates a Grid based helper that lays out its elements in a single Column.
      *
-     * @param elements [LayoutReference]s to be laid out by the Grid helper
-     * @param skips specify area(s) in a Row to be skipped - format: Skip(index, size)
-     * @param spans specify area(s) in a Row to be spanned - format: Span(index, size)
-     * @param horizontalGap defines the gap between views in the y axis
-     * @param columnWeights defines the weight of each column
-     * @param paddingHorizontal sets paddingStart and paddingEnd of the content
-     * @param paddingVertical sets paddingTop and paddingBottom of the content
-     */
-    fun createRow(
-        vararg elements: LayoutReference,
-        skips: Array<Skip> = arrayOf(),
-        spans: Array<Span> = arrayOf(),
-        horizontalGap: Dp = 0.dp,
-        columnWeights: IntArray = intArrayOf(),
-        paddingHorizontal: Dp = 0.dp,
-        paddingVertical: Dp = 0.dp,
-    ): ConstrainedLayoutReference {
-        return createGrid(
-            elements = elements,
-            rows = 1,
-            skips = skips,
-            spans = spans,
-            horizontalGap = horizontalGap,
-            columnWeights = columnWeights,
-            paddingStart = paddingHorizontal,
-            paddingTop = paddingVertical,
-            paddingEnd = paddingHorizontal,
-            paddingBottom = paddingVertical,
-        )
-    }
-
-    /**
-     * Creates a Grid based helper that lays out its elements in a single Column. Example:
-     * ConstraintLayout( ConstraintSet { val a = createRefFor("1") val b = createRefFor("2") val c =
-     * createRefFor("3") val d = createRefFor("4") val e = createRefFor("5") val weights =
-     * intArrayOf(3, 3, 2, 2, 1) val g1 = createColumn( a, b, c, d, e, skips = arrayOf(Skip(1, 1),
-     * Skip(3, 2)), spans = arrayOf(Span(1, 2)), verticalGap = 10.dp, rowWeights = weights, padding
-     * = 10.dp, ) constrain(g1) { width = Dimension.matchParent height = Dimension.matchParent },
-     * modifier = Modifier.fillMaxSize() ) { val numArray = arrayOf("1", "2", "3", "4", "5") for
-     * (num in numArray) { Button( modifier = Modifier.layoutId(num).width(120.dp), onClick = {}, )
-     * { Text(text = String.format("btn%s", num)) } } }
+     * Example:
+     * ```
+     * ConstraintLayout(
+     *     constraintSet = ConstraintSet {
+     *         val (a, b, c, d, e) = createRefsFor(0, 1, 2, 3, 4)
+     *         val column = createColumn(
+     *             a, b, c, d, e,
+     *             spacing = 10.dp,
+     *             weights = floatArrayOf(3f, 3f, 2f, 2f, 1f),
+     *         )
+     *         constrain(column) {
+     *             width = Dimension.matchParent
+     *             height = Dimension.matchParent
+     *         }
      *
-     * @param elements [LayoutReference]s to be laid out by the Grid helper
-     * @param spans specify area(s) in a Column to be spanned - format: Span(index, size)
-     * @param skips specify area(s) in a Column to be skipped - format: Skip(index, size)
-     * @param verticalGap defines the gap between views in the y axis
-     * @param rowWeights defines the weight of each row
-     * @param padding sets padding around the content
+     *         constrain(a, b, c, d, e) {
+     *             height = Dimension.fillToConstraints
+     *         }
+     *     },
+     *     modifier = Modifier.fillMaxSize()
+     * ) {
+     *     repeat(5) {
+     *         Text(
+     *             text = "item$it",
+     *             modifier = Modifier
+     *                 .layoutId(it)
+     *                 .background(Color.LightGray)
+     *         )
+     *     }
+     * }
+     * ```
+     *
+     * @param elements [LayoutReference]s to be laid out by the Grid-based Column helper
+     * @param spacing Defines the vertical spacing between each item in the Column.
+     * @param weights Defines the weight for each element in the Column. Note that the number of
+     *   weights provided are expected to match the number of [elements] given. Otherwise, weights
+     *   will be automatically appended (with a value of `1`), or trimmed to match the number of
+     *   given [elements].
+     * @see createGrid
      */
+    @SuppressLint("Range") // Enables internal grid mode for row and column
     fun createColumn(
         vararg elements: LayoutReference,
-        skips: Array<Skip> = arrayOf(),
-        spans: Array<Span> = arrayOf(),
-        rowWeights: IntArray = intArrayOf(),
-        verticalGap: Dp = 0.dp,
-        padding: Dp = 0.dp,
+        spacing: Dp = 0.dp,
+        weights: FloatArray = floatArrayOf(),
     ): ConstrainedLayoutReference {
         return createGrid(
             elements = elements,
+            rows = 0,
             columns = 1,
-            skips = skips,
-            spans = spans,
-            verticalGap = verticalGap,
-            rowWeights = rowWeights,
-            paddingStart = padding,
-            paddingTop = padding,
-            paddingEnd = padding,
-            paddingBottom = padding,
+            verticalSpacing = spacing,
+            rowWeights = weights,
         )
     }
 
     /**
-     * Creates a Grid based helper that lays out its elements in a single Column. Example:
-     * ConstraintLayout( ConstraintSet { val a = createRefFor("1") val b = createRefFor("2") val c =
-     * createRefFor("3") val d = createRefFor("4") val e = createRefFor("5") val weights =
-     * intArrayOf(3, 3, 2, 2, 1) val g1 = createColumn( a, b, c, d, e, skips = arrayOf(Skip(1, 1),
-     * Skip(3, 2)), spans = arrayOf(Span(1, 2)), verticalGap = 10.dp, rowWeights = weights, padding
-     * = 10.dp, ) constrain(g1) { width = Dimension.matchParent height = Dimension.matchParent },
-     * modifier = Modifier.fillMaxSize() ) { val numArray = arrayOf("1", "2", "3", "4", "5") for
-     * (num in numArray) { Button( modifier = Modifier.layoutId(num).width(120.dp), onClick = {}, )
-     * { Text(text = String.format("btn%s", num)) } } }
+     * Helper that creates a fixed Grid layout.
      *
-     * @param elements [LayoutReference]s to be laid out by the Grid helper
-     * @param skips specify area(s) in a Column to be skipped - format: Skip(index, size)
-     * @param spans specify area(s) in a Column to be spanned - format: Span(index, size)
-     * @param verticalGap defines the gap between views in the y axis
-     * @param rowWeights defines the weight of each row
-     * @param paddingHorizontal sets paddingStart and paddingEnd of the content
-     * @param paddingVertical sets paddingTop and paddingBottom of the content
-     */
-    fun createColumn(
-        vararg elements: LayoutReference,
-        skips: Array<Skip> = arrayOf(),
-        spans: Array<Span> = arrayOf(),
-        verticalGap: Dp = 0.dp,
-        rowWeights: IntArray = intArrayOf(),
-        paddingHorizontal: Dp = 0.dp,
-        paddingVertical: Dp = 0.dp,
-    ): ConstrainedLayoutReference {
-        return createGrid(
-            elements = elements,
-            columns = 1,
-            skips = skips,
-            spans = spans,
-            verticalGap = verticalGap,
-            rowWeights = rowWeights,
-            paddingStart = paddingHorizontal,
-            paddingTop = paddingVertical,
-            paddingEnd = paddingHorizontal,
-            paddingBottom = paddingVertical,
-        )
-    }
-
-    /**
-     * Creates a Grid representation with a Grid Helper. Example: ConstraintLayout( ConstraintSet {
-     * val a = createRefFor("1") val b = createRefFor("2") val c = createRefFor("3") val d =
-     * createRefFor("4") val e = createRefFor("5") val f = createRefFor("6") val g =
-     * createRefFor("7") val h = createRefFor("8") val i = createRefFor("9") val j =
-     * createRefFor("0") val k = createRefFor("box") val weights = intArrayOf(3, 3, 2, 2) val flags
-     * = arrayOf("SubGridByColRow", "SpansRespectWidgetOrder") val g1 = createGrid( k, a, b, c, d,
-     * e, f, g, h, i, j, k, rows = 5, columns = 3, verticalGap = 25.dp, horizontalGap = 25.dp, skips
-     * = arrayOf(Skip(12, 1, 1)), spans = arrayOf(Span(0, 1, 3)), rowWeights = weights,
-     * paddingHorizontal = 10.dp, paddingVertical = 10.dp, flags = flags, ) constrain(g1) { width =
-     * Dimension.matchParent height = Dimension.matchParent }, modifier = Modifier.fillMaxSize() ) {
-     * val numArray = arrayOf("1", "2", "3", "4", "5", "6", "7", "8", "9", "0") for (num in
-     * numArray) { Button( modifier = Modifier.layoutId(num).width(120.dp), onClick = {}, ) {
-     * Text(text = String.format("btn%s", num)) } } Box( modifier =
-     * Modifier.background(Color.Gray).layoutId("box"), Alignment.BottomEnd ) { Text("100", fontSize
-     * = 80.sp) } }
+     * A grid is defined by a set number of rows and columns. By default the given [elements] are
+     * arranged horizontally first (left to right, then top to bottom).
      *
-     * @param elements [LayoutReference]s to be laid out by the Grid helper
-     * @param orientation 0 if horizontal and 1 if vertical
-     * @param rows sets the number of rows in Grid
-     * @param columns sets the number of columns in Grid
-     * @param verticalGap defines the gap between views in the y axis
-     * @param horizontalGap defines the gap between views in the x axis
-     * @param rowWeights defines the weight of each row
-     * @param columnWeights defines the weight of each column
-     * @param skips defines the positions in a Grid to be skipped the format: Skip(position, rows,
-     *   columns) position - the index of the starting position rows - the number of rows to skip
-     *   coloumns - the number of columns to skip
-     * @param spans defines the spanned area(s) in Grid the format: Span(position, rows, columns)
-     *   position - the index of the starting position rows - the number of rows to span coloumns -
-     *   the number of columns to span
-     * @param padding sets padding around the content
-     * @param flags set different flags to be enabled (not case-sensitive), including
-     *   SubGridByColRow: reverse the width and height specification for spans/skips. Original -
-     *   Position:HeightxWidth; with the flag - Position:WidthxHeight SpansRespectWidgetOrder: spans
-     *   would respect the order of the widgets. Original - the widgets in the front of the widget
-     *   list would be assigned to the spanned area; with the flag - all the widges will be arranged
-     *   based on the given order. For example, for a layout with 1 row and 3 columns. If we have
-     *   two widgets: w1, w2 with a span as 1:1x2, the original layout would be [w2 w1 w1]. Since w1
-     *   is in the front of the list, it would be assigned to the spanned area. With the flag, the
-     *   layout would be [w1 w2 w2] that respects the order of the widget list.
+     * Either [rowWeights] or [columnWeights] may be provided to modify their size in the grid
+     * relative to each other.
+     *
+     * You may provide [Span]s to define size of each cell within the grid.
+     *
+     * To avoid placing Layouts in specific cells (or an area within the grid), you may provide
+     * [skips]. Note that if the provided [Span]s and [Skip]s overlap, the [Skip]s will take
+     * priority, ignoring the overlapping [Span] definition.
+     *
+     * Here's an example showing how to build a calculator layout using a couple of [Span]s:
+     * ```
+     * // For most of the keys we can just use the displayed text as the ID.
+     * val ids = arrayOf(
+     *     // Text box will span all 4 columns and the first 2 of rows
+     *     "textBox",
+     *     "C", "+/-", "%", "/",
+     *     "7", "8", "9", "*",
+     *     "4", "5", "6", "-",
+     *     "1", "2", "3", "+",
+     *     // The '0' will span two columns, note that it's on the 24th position in the grid
+     *     "0", ".", "="
+     * )
+     * ConstraintLayout(
+     *     constraintSet = ConstraintSet {
+     *         val idRefs = Array(ids.size) { createRefFor(ids[it]) }
+     *
+     *         val g1 = createGrid(
+     *             elements = idRefs,
+     *             rows = 7,
+     *             columns = 4,
+     *             verticalSpacing = 10.dp,
+     *             horizontalSpacing = 10.dp,
+     *             spans = arrayOf(
+     *                 // textBox
+     *                 Span(position = 0, rows = 2, columns = 4),
+     *                 // '0' key
+     *                 Span(position = 24, rows = 1, columns = 2)
+     *             )
+     *         )
+     *
+     *         constrain(g1) {
+     *             width = Dimension.matchParent
+     *             height = Dimension.matchParent
+     *         }
+     *
+     *         constrain(*idRefs) {
+     *             // Make all the layouts fill up their space, you may still use coercing methods
+     *             // such as `atMost(Dp)` or `atMostWrapContent()` to further limit their size.
+     *             width = Dimension.fillToConstraints
+     *             height = Dimension.fillToConstraints
+     *         }
+     *     },
+     *     modifier = Modifier.fillMaxSize()
+     * ) {
+     *     ids.forEach { id ->
+     *         when (id) {
+     *             "textBox" -> {
+     *                 Box(
+     *                     modifier = Modifier
+     *                         .background(Color.Gray)
+     *                         // As usual, IDs should only be assigned on top-level children
+     *                         .layoutId(id),
+     *                     contentAlignment = Alignment.BottomEnd
+     *                 ) {
+     *                     Text(text = "100", fontSize = 80.sp)
+     *                 }
+     *             }
+     *
+     *             else -> {
+     *                 Button(onClick = { }, Modifier.layoutId(id)) {
+     *                     Text(text = id, fontSize = 30.sp)
+     *                 }
+     *             }
+     *         }
+     *     }
+     * }
+     * ```
+     *
+     * Here's another example using [Skip]s to easily lay out the typical Keyboard navigation pad:
+     * ```
+     * val keys = arrayOf(
+     *     "Insert", "Home", "Page Up",
+     *     "Delete", "End", "Page Down",
+     *     "↑", "←", "↓", "→"
+     * )
+     * ConstraintLayout(
+     *     constraintSet = ConstraintSet {
+     *         val keyRefs = Array(keys.size) { createRefFor(keys[it]) }
+     *
+     *         val g1 = createGrid(
+     *             elements = keyRefs,
+     *             rows = 5,
+     *             columns = 3,
+     *             verticalSpacing = 8.dp,
+     *             horizontalSpacing = 8.dp,
+     *             skips = arrayOf(
+     *                 // These positions follow the expected Grid cells indexing
+     *                 // Arranged horizontally by default:
+     *                 //   - 0 is top-left
+     *                 //   - 14 is bottom-right (5 rows x 3 columns - 1)
+     *                 Skip(position = 6, rows = 1, columns = 3),
+     *                 Skip(position = 9, rows = 1, columns = 1),
+     *                 Skip(position = 11, rows = 1, columns = 1)
+     *             )
+     *         )
+     *         constrain(g1) {
+     *             width = Dimension.matchParent
+     *             height = Dimension.matchParent
+     *         }
+     *
+     *         constrain(*keyRefs) {
+     *             width = Dimension.fillToConstraints.atMost(100.dp)
+     *             height = Dimension.fillToConstraints.atMost(100.dp)
+     *         }
+     *     },
+     *     modifier = Modifier.fillMaxSize()
+     * ) {
+     *     keys.forEachIndexed { index, key ->
+     *         Box(
+     *             modifier = Modifier
+     *                 .layoutId(key)
+     *                 .background(Color.LightGray),
+     *             contentAlignment = Alignment.Center
+     *         ) {
+     *             Text(
+     *                 text = key,
+     *                 textAlign = TextAlign.Center,
+     *                 // Make fontSize bigger for the arrow keys
+     *                 fontSize = if (index >= 6) 24.sp else TextUnit.Unspecified
+     *             )
+     *         }
+     *     }
+     * }
+     * ```
+     *
+     * @param elements [LayoutReference]s to be laid out by the Grid helper. By default, they are
+     *   positioned in the given order based on the arrangement. Horizontal arrangement by default.
+     * @param rows Sets the number of rows in the Grid
+     * @param columns Sets the number of columns in the Grid
+     * @param isHorizontalArrangement Whether to place the given [elements] horizontally, filling
+     *   the cells from left to right and top to bottom. Otherwise, the [elements] are placed
+     *   vertically, filling each cell from top to bottom and left to right. `true` by default.
+     * @param verticalSpacing Defines the gap between each row.
+     * @param horizontalSpacing Defines the gap between each column.
+     * @param rowWeights Defines the weight for each row. The weight specifies how much space each
+     *   row takes relative to each other. Should be either an empty array (all rows are the same
+     *   size), or have a value corresponding for each row. Otherwise, these weights will be trimmed
+     *   or padded (with trailing 1f) to match the given [rows].
+     * @param columnWeights Defines the weight for each column. The weight specifies how much space
+     *   each column takes relative to each other. Should be either an empty array (all columns are
+     *   the same size), or have a value corresponding for each column. Otherwise, these weights
+     *   will be trimmed or padded (with trailing 1f) to match the given [columns].
+     * @param skips A [Skip] defines an area within the Grid where Layouts may **not** be placed.
+     *   So, as the [elements] are being placed, they will skip any cell covered by the given skips.
+     * @param spans A [Span] defines how much area should each cell occupy when placing an item on
+     *   it. Keep in mind that when laying out, the Grid won't place any overlapping items over the
+     *   spanned area. In that sense, a [Span] works similarly to a [Skip], except that an item will
+     *   be placed at the original spanned cell position. Also note, [skips] take priority over
+     *   spans, meaning that defining a [Span] that overlaps a [Skip] is a no-op.
+     * @param flags A [GridFlags] definition that may change certain behaviors of the Grid helper.
+     *   [GridFlags.None] by default.
+     * @see createColumn
+     * @see createRow
      */
     fun createGrid(
         vararg elements: LayoutReference,
-        orientation: Int = 0,
-        rows: Int = 0,
-        columns: Int = 0,
-        verticalGap: Dp = 0.dp,
-        horizontalGap: Dp = 0.dp,
-        rowWeights: IntArray = intArrayOf(),
-        columnWeights: IntArray = intArrayOf(),
+        @IntRange(from = 1) rows: Int,
+        @IntRange(from = 1) columns: Int,
+        isHorizontalArrangement: Boolean = true,
+        verticalSpacing: Dp = 0.dp,
+        horizontalSpacing: Dp = 0.dp,
+        rowWeights: FloatArray = floatArrayOf(),
+        columnWeights: FloatArray = floatArrayOf(),
         skips: Array<Skip> = arrayOf(),
         spans: Array<Span> = arrayOf(),
-        padding: Dp = 0.dp,
-        flags: Array<GridFlag> = arrayOf(),
-    ): ConstrainedLayoutReference {
-        return createGrid(
-            elements = elements,
-            orientation = orientation,
-            rows = rows,
-            columns = columns,
-            horizontalGap = horizontalGap,
-            verticalGap = verticalGap,
-            rowWeights = rowWeights,
-            columnWeights = columnWeights,
-            skips = skips,
-            spans = spans,
-            paddingStart = padding,
-            paddingTop = padding,
-            paddingEnd = padding,
-            paddingBottom = padding,
-            flags = flags,
-        )
-    }
-
-    /**
-     * Creates a Grid representation with a Grid Helper. Example: ConstraintLayout( ConstraintSet {
-     * val a = createRefFor("1") val b = createRefFor("2") val c = createRefFor("3") val d =
-     * createRefFor("4") val e = createRefFor("5") val f = createRefFor("6") val g =
-     * createRefFor("7") val h = createRefFor("8") val i = createRefFor("9") val j =
-     * createRefFor("0") val k = createRefFor("box") val weights = intArrayOf(3, 3, 2, 2) val flags
-     * = arrayOf("SubGridByColRow", "SpansRespectWidgetOrder") val g1 = createGrid( k, a, b, c, d,
-     * e, f, g, h, i, j, k, rows = 5, columns = 3, verticalGap = 25.dp, horizontalGap = 25.dp, skips
-     * = arrayOf(Skip(12, 1, 1)), spans = arrayOf(Span(0, 1, 3)), rowWeights = weights,
-     * paddingHorizontal = 10.dp, paddingVertical = 10.dp, flags = flags, ) constrain(g1) { width =
-     * Dimension.matchParent height = Dimension.matchParent }, modifier = Modifier.fillMaxSize() ) {
-     * val numArray = arrayOf("1", "2", "3", "4", "5", "6", "7", "8", "9", "0") for (num in
-     * numArray) { Button( modifier = Modifier.layoutId(num).width(120.dp), onClick = {}, ) {
-     * Text(text = String.format("btn%s", num)) } } Box( modifier =
-     * Modifier.background(Color.Gray).layoutId("box"), Alignment.BottomEnd ) { Text("100", fontSize
-     * = 80.sp) } }
-     *
-     * @param elements [LayoutReference]s to be laid out by the Grid helper
-     * @param rowWeights defines the weight of each row
-     * @param rows sets the number of rows in Grid
-     * @param columns sets the number of columns in Grid
-     * @param verticalGap defines the gap between views in the y axis
-     * @param horizontalGap defines the gap between views in the x axis
-     * @param columnWeights defines the weight of each column
-     * @param orientation 0 if horizontal and 1 if vertical
-     * @param skips defines the positions in a Grid to be skipped the format: Skip(position, rows,
-     *   columns) position - the index of the starting position rows - the number of rows to skip
-     *   coloumns - the number of columns to skip
-     * @param spans defines the spanned area(s) in Grid the format: Span(position, rows, columns)
-     *   position - the index of the starting position rows - the number of rows to span coloumns -
-     *   the number of columns to span
-     * @param paddingHorizontal sets paddingStart and paddingEnd of the content
-     * @param paddingVertical sets paddingTop and paddingBottom of the content
-     * @param flags set different flags to be enabled (not case-sensitive), including
-     *   SubGridByColRow: reverse the width and height specification for spans/skips. Original -
-     *   Position:HeightxWidth; with the flag - Position:WidthxHeight SpansRespectWidgetOrder: spans
-     *   would respect the order of the widgets. Original - the widgets in the front of the widget
-     *   list would be assigned to the spanned area; with the flag - all the widges will be arranged
-     *   based on the given order. For example, for a layout with 1 row and 3 columns. If we have
-     *   two widgets: w1, w2 with a span as 1:1x2, the original layout would be [w2 w1 w1]. Since w1
-     *   is in the front of the list, it would be assigned to the spanned area. With the flag, the
-     *   layout would be [w1 w2 w2] that respects the order of the widget list.
-     */
-    fun createGrid(
-        vararg elements: LayoutReference,
-        orientation: Int = 0,
-        rows: Int = 0,
-        columns: Int = 0,
-        verticalGap: Dp = 0.dp,
-        horizontalGap: Dp = 0.dp,
-        rowWeights: IntArray = intArrayOf(),
-        columnWeights: IntArray = intArrayOf(),
-        skips: Array<Skip> = arrayOf(),
-        spans: Array<Span> = arrayOf(),
-        paddingHorizontal: Dp = 0.dp,
-        paddingVertical: Dp = 0.dp,
-        flags: Array<GridFlag> = arrayOf(),
-    ): ConstrainedLayoutReference {
-        return createGrid(
-            elements = elements,
-            rowWeights = rowWeights,
-            columnWeights = columnWeights,
-            orientation = orientation,
-            rows = rows,
-            columns = columns,
-            horizontalGap = horizontalGap,
-            verticalGap = verticalGap,
-            skips = skips,
-            spans = spans,
-            paddingStart = paddingHorizontal,
-            paddingTop = paddingVertical,
-            paddingEnd = paddingHorizontal,
-            paddingBottom = paddingVertical,
-            flags = flags
-        )
-    }
-
-    /**
-     * Creates a Grid representation with a Grid Helper. Example: ConstraintLayout( ConstraintSet {
-     * val a = createRefFor("1") val b = createRefFor("2") val c = createRefFor("3") val d =
-     * createRefFor("4") val e = createRefFor("5") val f = createRefFor("6") val g =
-     * createRefFor("7") val h = createRefFor("8") val i = createRefFor("9") val j =
-     * createRefFor("0") val k = createRefFor("box") val weights = intArrayOf(3, 3, 2, 2) val flags
-     * = arrayOf("SubGridByColRow", "SpansRespectWidgetOrder") val g1 = createGrid( k, a, b, c, d,
-     * e, f, g, h, i, j, k, rows = 5, columns = 3, verticalGap = 25.dp, horizontalGap = 25.dp, skips
-     * = arrayOf(Skip(12, 1, 1)), spans = arrayOf(Span(0, 1, 3)), rowWeights = weights, paddingStart
-     * = 10.dp, paddingTop = 10.dp, paddingEnd = 10.dp, paddingBottom = 10.dp, flags = flags, )
-     * constrain(g1) { width = Dimension.matchParent height = Dimension.matchParent }, modifier =
-     * Modifier.fillMaxSize() ) { val numArray = arrayOf("1", "2", "3", "4", "5", "6", "7", "8",
-     * "9", "0") for (num in numArray) { Button( modifier = Modifier.layoutId(num).width(120.dp),
-     * onClick = {}, ) { Text(text = String.format("btn%s", num)) } } Box( modifier =
-     * Modifier.background(Color.Gray).layoutId("box"), Alignment.BottomEnd ) { Text("100", fontSize
-     * = 80.sp) } }
-     *
-     * @param elements [LayoutReference]s to be laid out by the Grid helper
-     * @param orientation 0 if horizontal and 1 if vertical
-     * @param rows sets the number of rows in Grid
-     * @param columns sets the number of columns in Grid
-     * @param verticalGap defines the gap between views in the y axis
-     * @param horizontalGap defines the gap between views in the x axis
-     * @param rowWeights defines the weight of each row
-     * @param columnWeights defines the weight of each column
-     * @param skips defines the positions in a Grid to be skipped the format: Skip(position, rows,
-     *   columns) position - the index of the starting position rows - the number of rows to skip
-     *   coloumns - the number of columns to skip
-     * @param spans defines the spanned area(s) in Grid the format: Span(position, rows, columns)
-     *   position - the index of the starting position rows - the number of rows to span coloumns -
-     *   the number of columns to span
-     * @param paddingStart sets paddingStart of the content
-     * @param paddingTop sets paddingTop of the content
-     * @param paddingEnd sets paddingEnd of the content
-     * @param paddingBottom sets paddingBottom of the content
-     * @param flags set different flags to be enabled (not case-sensitive), including
-     *   SubGridByColRow: reverse the width and height specification for spans/skips. Original -
-     *   Position:HeightxWidth; with the flag - Position:WidthxHeight SpansRespectWidgetOrder: spans
-     *   would respect the order of the widgets. Original - the widgets in the front of the widget
-     *   list would be assigned to the spanned area; with the flag - all the widges will be arranged
-     *   based on the given order. For example, for a layout with 1 row and 3 columns. If we have
-     *   two widgets: w1, w2 with a span as 1:1x2, the original layout would be [w2 w1 w1]. Since w1
-     *   is in the front of the list, it would be assigned to the spanned area. With the flag, the
-     *   layout would be [w1 w2 w2] that respects the order of the widget list.
-     */
-    fun createGrid(
-        vararg elements: LayoutReference,
-        orientation: Int = 0,
-        rows: Int = 0,
-        columns: Int = 0,
-        verticalGap: Dp = 0.dp,
-        horizontalGap: Dp = 0.dp,
-        rowWeights: IntArray = intArrayOf(),
-        columnWeights: IntArray = intArrayOf(),
-        skips: Array<Skip> = arrayOf(),
-        spans: Array<Span> = arrayOf(),
-        paddingStart: Dp = 0.dp,
-        paddingTop: Dp = 0.dp,
-        paddingEnd: Dp = 0.dp,
-        paddingBottom: Dp = 0.dp,
-        flags: Array<GridFlag> = arrayOf(),
+        flags: GridFlags = GridFlags.None,
     ): ConstrainedLayoutReference {
         val ref = ConstrainedLayoutReference(createHelperId())
         val elementArray = CLArray(charArrayOf())
-        val flagArray = CLArray(charArrayOf())
         elements.forEach { elementArray.add(CLString.from(it.id.toString())) }
-        val paddingArray =
-            CLArray(charArrayOf()).apply {
-                add(CLNumber(paddingStart.value))
-                add(CLNumber(paddingTop.value))
-                add(CLNumber(paddingEnd.value))
-                add(CLNumber(paddingBottom.value))
-            }
-        flags.forEach { flagArray.add(CLString.from(it.name)) }
         var strRowWeights = ""
         var strColumnWeights = ""
         if (rowWeights.size > 1) {
@@ -1051,17 +963,16 @@
         ref.asCLContainer().apply {
             put("contains", elementArray)
             putString("type", "grid")
-            putNumber("orientation", orientation.toFloat())
+            putNumber("orientation", if (isHorizontalArrangement) 0f else 1f)
             putNumber("rows", rows.toFloat())
             putNumber("columns", columns.toFloat())
-            putNumber("vGap", verticalGap.value)
-            putNumber("hGap", horizontalGap.value)
-            put("padding", paddingArray)
+            putNumber("vGap", verticalSpacing.value)
+            putNumber("hGap", horizontalSpacing.value)
             putString("rowWeights", strRowWeights)
             putString("columnWeights", strColumnWeights)
             putString("skips", strSkips)
             putString("spans", strSpans)
-            put("flags", flagArray)
+            putNumber("flags", flags.value.toFloat())
         }
 
         return ref
@@ -1332,10 +1243,7 @@
 
     override fun equals(other: Any?): Boolean {
         if (this === other) return true
-        if (javaClass != other?.javaClass) return false
-
-        other as LayoutReference
-
+        if (other !is LayoutReference) return false
         if (id != other.id) return false
 
         return true
@@ -1347,7 +1255,7 @@
 
     internal fun setHelperParams(helperParams: HelperParams) {
         // Use the class name to force one instance per implementation
-        helperParamsMap[helperParams.javaClass.simpleName] = helperParams
+        helperParams::class.simpleName?.let { helperParamsMap[it] = helperParams }
     }
 
     /**
@@ -1355,7 +1263,7 @@
      * type [T] has been set.
      */
     internal inline fun <reified T> getHelperParams(): T? where T : HelperParams {
-        return helperParamsMap[T::class.java.simpleName] as? T
+        return helperParamsMap[T::class.simpleName] as? T
     }
 }
 
@@ -1534,21 +1442,66 @@
 }
 
 /**
- * GridFlag defines the available flags of Grid SubGridByColRow: reverse the width and height
- * specification for spans/skips. Original - Position:HeightxWidth; with the flag -
- * Position:WidthxHeight SpansRespectWidgetOrder: spans would respect the order of the widgets.
- * Original - the widgets in the front of the widget list would be assigned to the spanned area;
- * with the flag - all the widges will be arranged based on the given order. For example, for a
- * layout with 1 row and 3 columns. If we have two widgets: w1, w2 with a span as 1:1x2, the
- * original layout would be [w2 w1 w1]. Since w1 is in the front of the list, it would be assigned
- * to the spanned area. With the flag, the layout would be [w1 w2 w2] that respects the order of the
- * widget list.
+ * Set of individual options that may change the Grid helper behavior.
+ *
+ * By default, the Grid helper places its [LayoutReference]s as given in the `elements` parameter.
+ * Following arrangement rules (skips, spans and orientation).
+ *
+ * However, when [isPlaceLayoutsOnSpansFirst] is `true`. The given [LayoutReference]s will be first
+ * placed on the cells occupied by the given `spans` array. Then, the remaining layouts are placed
+ * on the remaining cells following typical arrangement rules.
+ *
+ * For example, on a grid layout with 1 row and 3 columns, placing two widgets: w0, w1, with a span
+ * defined as `Span(position = 1, rows = 1, columns = 2)`. The grid layout by default would place
+ * them as `[w0 w1 w1]`. Whereas when [isPlaceLayoutsOnSpansFirst] is `true`, they'd be placed as
+ * `[w1 w0 w0]`.
+ *
+ * In some situations, [isPlaceLayoutsOnSpansFirst] can make it easier to match the desired layouts
+ * with the given spans on the Grid.
+ *
+ * @see ConstraintLayoutBaseScope.createGrid
  */
-@Immutable
-class GridFlag internal constructor(internal val name: String) {
+@JvmInline
+value class GridFlags private constructor(internal val value: Int) {
+    /**
+     * @param isPlaceLayoutsOnSpansFirst Whether to make it so that Layouts are first placed on
+     *   cells occupied by spans.
+     */
+    constructor(
+        isPlaceLayoutsOnSpansFirst: Boolean = false
+    ) : this((if (isPlaceLayoutsOnSpansFirst) 0 else GridCore.SPANS_RESPECT_WIDGET_ORDER))
+
+    @TestOnly // Only for tests, the additional flag is not needed when using the DSL
+    internal constructor(
+        isPlaceLayoutsOnSpansFirst: Boolean = false,
+        isSubGridByColRow: Boolean = false
+    ) : this(
+        (if (isPlaceLayoutsOnSpansFirst) 0 else GridCore.SPANS_RESPECT_WIDGET_ORDER) or
+            (if (isSubGridByColRow) GridCore.SUB_GRID_BY_COL_ROW else 0)
+    )
+
+    /**
+     * When true, the Grid helper will first place Layouts on cells occupied by spans, then fill the
+     * remaining cells following the typical arrangement rules.
+     */
+    val isPlaceLayoutsOnSpansFirst: Boolean
+        get() = value and (GridCore.SPANS_RESPECT_WIDGET_ORDER) == 0
+
+    override fun toString(): String =
+        "GridFlag(isPlaceLayoutsOnSpansFirst = $isPlaceLayoutsOnSpansFirst)"
+
     companion object {
-        val SpansRespectWidgetOrder = GridFlag("spansrespectwidgetorder")
-        val SubGridByColRow = GridFlag("subgridbycolrow")
+        /** All default behaviors apply. */
+        val None = GridFlags(isPlaceLayoutsOnSpansFirst = false)
+
+        /**
+         * Creates a [GridFlags] instance with `isPlaceLayoutsOnSpansFirst` as `true`.
+         *
+         * Making it so that when placing the layouts, they are first placed on cells occupied by
+         * spans, then, any remaining layouts are placed on the remaining cells following the
+         * typical arrangement rules.
+         */
+        val PlaceLayoutsOnSpansFirst = GridFlags(isPlaceLayoutsOnSpansFirst = true)
     }
 }
 
@@ -1603,10 +1556,17 @@
  * @constructor create a new Skip containing the position and size information of the skipped area
  */
 @JvmInline
-value class Skip(val description: String) {
-    constructor(position: Int, rows: Int, columns: Int) : this("$position:${rows}x$columns")
+value class Skip private constructor(val description: String) {
+    constructor(
+        @IntRange(from = 0) position: Int,
+        @IntRange(from = 1) rows: Int,
+        @IntRange(from = 1) columns: Int
+    ) : this("$position:${rows}x$columns")
 
-    constructor(position: Int, size: Int) : this("$position:$size")
+    constructor(
+        @IntRange(from = 0) position: Int,
+        @IntRange(from = 1) size: Int
+    ) : this("$position:$size")
 }
 
 /**
@@ -1620,7 +1580,14 @@
  */
 @JvmInline
 value class Span(val description: String) {
-    constructor(position: Int, rows: Int, columns: Int) : this("$position:${rows}x$columns")
+    constructor(
+        @IntRange(from = 0) position: Int,
+        @IntRange(from = 1) rows: Int,
+        @IntRange(from = 1) columns: Int
+    ) : this("$position:${rows}x$columns")
 
-    constructor(position: Int, size: Int) : this("$position:$size")
+    constructor(
+        @IntRange(from = 0) position: Int,
+        @IntRange(from = 1) size: Int
+    ) : this("$position:$size")
 }
diff --git a/constraintlayout/constraintlayout-core/api/1.1.0-beta01.txt b/constraintlayout/constraintlayout-core/api/1.1.0-beta01.txt
new file mode 100644
index 0000000..5be1d12
--- /dev/null
+++ b/constraintlayout/constraintlayout-core/api/1.1.0-beta01.txt
@@ -0,0 +1,3393 @@
+// Signature format: 4.0
+package androidx.constraintlayout.core {
+
+  public class ArrayLinkedVariables implements androidx.constraintlayout.core.ArrayRow.ArrayRowVariables {
+    method public void add(androidx.constraintlayout.core.SolverVariable!, float, boolean);
+    method public final void clear();
+    method public boolean contains(androidx.constraintlayout.core.SolverVariable!);
+    method public void display();
+    method public void divideByAmount(float);
+    method public final float get(androidx.constraintlayout.core.SolverVariable!);
+    method public int getCurrentSize();
+    method public int getHead();
+    method public final int getId(int);
+    method public final int getNextIndice(int);
+    method public final float getValue(int);
+    method public androidx.constraintlayout.core.SolverVariable! getVariable(int);
+    method public float getVariableValue(int);
+    method public int indexOf(androidx.constraintlayout.core.SolverVariable!);
+    method public void invert();
+    method public final void put(androidx.constraintlayout.core.SolverVariable!, float);
+    method public final float remove(androidx.constraintlayout.core.SolverVariable!, boolean);
+    method public int sizeInBytes();
+    method public float use(androidx.constraintlayout.core.ArrayRow!, boolean);
+    field protected final androidx.constraintlayout.core.Cache! mCache;
+  }
+
+  public class ArrayRow {
+    ctor public ArrayRow();
+    ctor public ArrayRow(androidx.constraintlayout.core.Cache!);
+    method public androidx.constraintlayout.core.ArrayRow! addError(androidx.constraintlayout.core.LinearSystem!, int);
+    method public void addError(androidx.constraintlayout.core.SolverVariable!);
+    method public void clear();
+    method public androidx.constraintlayout.core.ArrayRow! createRowDimensionRatio(androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, float);
+    method public androidx.constraintlayout.core.ArrayRow! createRowEqualDimension(float, float, float, androidx.constraintlayout.core.SolverVariable!, int, androidx.constraintlayout.core.SolverVariable!, int, androidx.constraintlayout.core.SolverVariable!, int, androidx.constraintlayout.core.SolverVariable!, int);
+    method public androidx.constraintlayout.core.ArrayRow! createRowEqualMatchDimensions(float, float, float, androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!);
+    method public androidx.constraintlayout.core.ArrayRow! createRowEquals(androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, int);
+    method public androidx.constraintlayout.core.ArrayRow! createRowEquals(androidx.constraintlayout.core.SolverVariable!, int);
+    method public androidx.constraintlayout.core.ArrayRow! createRowGreaterThan(androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, int);
+    method public androidx.constraintlayout.core.ArrayRow! createRowGreaterThan(androidx.constraintlayout.core.SolverVariable!, int, androidx.constraintlayout.core.SolverVariable!);
+    method public androidx.constraintlayout.core.ArrayRow! createRowLowerThan(androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, int);
+    method public androidx.constraintlayout.core.ArrayRow! createRowWithAngle(androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, float);
+    method public androidx.constraintlayout.core.SolverVariable! getKey();
+    method public androidx.constraintlayout.core.SolverVariable! getPivotCandidate(androidx.constraintlayout.core.LinearSystem!, boolean[]!);
+    method public void initFromRow(androidx.constraintlayout.core.LinearSystem.Row!);
+    method public boolean isEmpty();
+    method public androidx.constraintlayout.core.SolverVariable! pickPivot(androidx.constraintlayout.core.SolverVariable!);
+    method public void reset();
+    method public void updateFromFinalVariable(androidx.constraintlayout.core.LinearSystem!, androidx.constraintlayout.core.SolverVariable!, boolean);
+    method public void updateFromRow(androidx.constraintlayout.core.LinearSystem!, androidx.constraintlayout.core.ArrayRow!, boolean);
+    method public void updateFromSynonymVariable(androidx.constraintlayout.core.LinearSystem!, androidx.constraintlayout.core.SolverVariable!, boolean);
+    method public void updateFromSystem(androidx.constraintlayout.core.LinearSystem!);
+    field public androidx.constraintlayout.core.ArrayRow.ArrayRowVariables! variables;
+  }
+
+  public static interface ArrayRow.ArrayRowVariables {
+    method public void add(androidx.constraintlayout.core.SolverVariable!, float, boolean);
+    method public void clear();
+    method public boolean contains(androidx.constraintlayout.core.SolverVariable!);
+    method public void display();
+    method public void divideByAmount(float);
+    method public float get(androidx.constraintlayout.core.SolverVariable!);
+    method public int getCurrentSize();
+    method public androidx.constraintlayout.core.SolverVariable! getVariable(int);
+    method public float getVariableValue(int);
+    method public int indexOf(androidx.constraintlayout.core.SolverVariable!);
+    method public void invert();
+    method public void put(androidx.constraintlayout.core.SolverVariable!, float);
+    method public float remove(androidx.constraintlayout.core.SolverVariable!, boolean);
+    method public int sizeInBytes();
+    method public float use(androidx.constraintlayout.core.ArrayRow!, boolean);
+  }
+
+  public class Cache {
+    ctor public Cache();
+  }
+
+  public class GoalRow extends androidx.constraintlayout.core.ArrayRow {
+    ctor public GoalRow(androidx.constraintlayout.core.Cache!);
+  }
+
+  public class LinearSystem {
+    ctor public LinearSystem();
+    method public void addCenterPoint(androidx.constraintlayout.core.widgets.ConstraintWidget!, androidx.constraintlayout.core.widgets.ConstraintWidget!, float, int);
+    method public void addCentering(androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, int, float, androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, int, int);
+    method public void addConstraint(androidx.constraintlayout.core.ArrayRow!);
+    method public androidx.constraintlayout.core.ArrayRow! addEquality(androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, int, int);
+    method public void addEquality(androidx.constraintlayout.core.SolverVariable!, int);
+    method public void addGreaterBarrier(androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, int, boolean);
+    method public void addGreaterThan(androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, int, int);
+    method public void addLowerBarrier(androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, int, boolean);
+    method public void addLowerThan(androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, int, int);
+    method public void addRatio(androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, float, int);
+    method public void addSynonym(androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, int);
+    method public androidx.constraintlayout.core.SolverVariable! createErrorVariable(int, String!);
+    method public androidx.constraintlayout.core.SolverVariable! createExtraVariable();
+    method public androidx.constraintlayout.core.SolverVariable! createObjectVariable(Object!);
+    method public androidx.constraintlayout.core.ArrayRow! createRow();
+    method public static androidx.constraintlayout.core.ArrayRow! createRowDimensionPercent(androidx.constraintlayout.core.LinearSystem!, androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, float);
+    method public androidx.constraintlayout.core.SolverVariable! createSlackVariable();
+    method public void displayReadableRows();
+    method public void displayVariablesReadableRows();
+    method public void fillMetrics(androidx.constraintlayout.core.Metrics!);
+    method public androidx.constraintlayout.core.Cache! getCache();
+    method public int getMemoryUsed();
+    method public static androidx.constraintlayout.core.Metrics! getMetrics();
+    method public int getNumEquations();
+    method public int getNumVariables();
+    method public int getObjectVariableValue(Object!);
+    method public void minimize() throws java.lang.Exception;
+    method public void removeRow(androidx.constraintlayout.core.ArrayRow!);
+    method public void reset();
+    field public static long ARRAY_ROW_CREATION;
+    field public static final boolean DEBUG = false;
+    field public static final boolean FULL_DEBUG = false;
+    field public static long OPTIMIZED_ARRAY_ROW_CREATION;
+    field public static boolean OPTIMIZED_ENGINE;
+    field public static boolean SIMPLIFY_SYNONYMS;
+    field public static boolean SKIP_COLUMNS;
+    field public static boolean USE_BASIC_SYNONYMS;
+    field public static boolean USE_DEPENDENCY_ORDERING;
+    field public static boolean USE_SYNONYMS;
+    field public boolean graphOptimizer;
+    field public boolean hasSimpleDefinition;
+    field public boolean newgraphOptimizer;
+    field public static androidx.constraintlayout.core.Metrics! sMetrics;
+  }
+
+  public class Metrics {
+    ctor public Metrics();
+    method public void copy(androidx.constraintlayout.core.Metrics!);
+    method public void reset();
+    field public long additionalMeasures;
+    field public long bfs;
+    field public long constraints;
+    field public long determineGroups;
+    field public long errors;
+    field public long extravariables;
+    field public long fullySolved;
+    field public long graphOptimizer;
+    field public long graphSolved;
+    field public long grouping;
+    field public long infeasibleDetermineGroups;
+    field public long iterations;
+    field public long lastTableSize;
+    field public long layouts;
+    field public long linearSolved;
+    field public long mChildCount;
+    field public long mEquations;
+    field public long mMeasureCalls;
+    field public long mMeasureDuration;
+    field public int mNumberOfLayouts;
+    field public int mNumberOfMeasures;
+    field public long mSimpleEquations;
+    field public long mSolverPasses;
+    field public long mVariables;
+    field public long maxRows;
+    field public long maxTableSize;
+    field public long maxVariables;
+    field public long measuredMatchWidgets;
+    field public long measuredWidgets;
+    field public long measures;
+    field public long measuresLayoutDuration;
+    field public long measuresWidgetsDuration;
+    field public long measuresWrap;
+    field public long measuresWrapInfeasible;
+    field public long minimize;
+    field public long minimizeGoal;
+    field public long nonresolvedWidgets;
+    field public long optimize;
+    field public long pivots;
+    field public java.util.ArrayList<java.lang.String!>! problematicLayouts;
+    field public long resolutions;
+    field public long resolvedWidgets;
+    field public long simpleconstraints;
+    field public long slackvariables;
+    field public long tableSizeIncrease;
+    field public long variables;
+    field public long widgets;
+  }
+
+  public class PriorityGoalRow extends androidx.constraintlayout.core.ArrayRow {
+    ctor public PriorityGoalRow(androidx.constraintlayout.core.Cache!);
+  }
+
+  public class SolverVariable implements java.lang.Comparable<androidx.constraintlayout.core.SolverVariable!> {
+    ctor public SolverVariable(androidx.constraintlayout.core.SolverVariable.Type!, String!);
+    ctor public SolverVariable(String!, androidx.constraintlayout.core.SolverVariable.Type!);
+    method public final void addToRow(androidx.constraintlayout.core.ArrayRow!);
+    method public int compareTo(androidx.constraintlayout.core.SolverVariable!);
+    method public String! getName();
+    method public final void removeFromRow(androidx.constraintlayout.core.ArrayRow!);
+    method public void reset();
+    method public void setFinalValue(androidx.constraintlayout.core.LinearSystem!, float);
+    method public void setName(String!);
+    method public void setSynonym(androidx.constraintlayout.core.LinearSystem!, androidx.constraintlayout.core.SolverVariable!, float);
+    method public void setType(androidx.constraintlayout.core.SolverVariable.Type!, String!);
+    method public final void updateReferencesWithNewDefinition(androidx.constraintlayout.core.LinearSystem!, androidx.constraintlayout.core.ArrayRow!);
+    field public static final int STRENGTH_BARRIER = 6; // 0x6
+    field public static final int STRENGTH_CENTERING = 7; // 0x7
+    field public static final int STRENGTH_EQUALITY = 5; // 0x5
+    field public static final int STRENGTH_FIXED = 8; // 0x8
+    field public static final int STRENGTH_HIGH = 3; // 0x3
+    field public static final int STRENGTH_HIGHEST = 4; // 0x4
+    field public static final int STRENGTH_LOW = 1; // 0x1
+    field public static final int STRENGTH_MEDIUM = 2; // 0x2
+    field public static final int STRENGTH_NONE = 0; // 0x0
+    field public float computedValue;
+    field public int id;
+    field public boolean inGoal;
+    field public boolean isFinalValue;
+    field public int strength;
+    field public int usageInRowCount;
+  }
+
+  public enum SolverVariable.Type {
+    enum_constant public static final androidx.constraintlayout.core.SolverVariable.Type CONSTANT;
+    enum_constant public static final androidx.constraintlayout.core.SolverVariable.Type ERROR;
+    enum_constant public static final androidx.constraintlayout.core.SolverVariable.Type SLACK;
+    enum_constant public static final androidx.constraintlayout.core.SolverVariable.Type UNKNOWN;
+    enum_constant public static final androidx.constraintlayout.core.SolverVariable.Type UNRESTRICTED;
+  }
+
+  public class SolverVariableValues implements androidx.constraintlayout.core.ArrayRow.ArrayRowVariables {
+    method public void add(androidx.constraintlayout.core.SolverVariable!, float, boolean);
+    method public void clear();
+    method public boolean contains(androidx.constraintlayout.core.SolverVariable!);
+    method public void display();
+    method public void divideByAmount(float);
+    method public float get(androidx.constraintlayout.core.SolverVariable!);
+    method public int getCurrentSize();
+    method public androidx.constraintlayout.core.SolverVariable! getVariable(int);
+    method public float getVariableValue(int);
+    method public int indexOf(androidx.constraintlayout.core.SolverVariable!);
+    method public void invert();
+    method public void put(androidx.constraintlayout.core.SolverVariable!, float);
+    method public float remove(androidx.constraintlayout.core.SolverVariable!, boolean);
+    method public int sizeInBytes();
+    method public float use(androidx.constraintlayout.core.ArrayRow!, boolean);
+    field protected final androidx.constraintlayout.core.Cache! mCache;
+  }
+
+}
+
+package androidx.constraintlayout.core.dsl {
+
+  public class Barrier extends androidx.constraintlayout.core.dsl.Helper {
+    ctor public Barrier(String!);
+    ctor public Barrier(String!, String!);
+    method public androidx.constraintlayout.core.dsl.Barrier! addReference(androidx.constraintlayout.core.dsl.Ref!);
+    method public androidx.constraintlayout.core.dsl.Barrier! addReference(String!);
+    method public androidx.constraintlayout.core.dsl.Constraint.Side! getDirection();
+    method public int getMargin();
+    method public String! referencesToString();
+    method public void setDirection(androidx.constraintlayout.core.dsl.Constraint.Side!);
+    method public void setMargin(int);
+  }
+
+  public abstract class Chain extends androidx.constraintlayout.core.dsl.Helper {
+    ctor public Chain(String!);
+    method public androidx.constraintlayout.core.dsl.Chain! addReference(androidx.constraintlayout.core.dsl.Ref!);
+    method public androidx.constraintlayout.core.dsl.Chain! addReference(String!);
+    method public androidx.constraintlayout.core.dsl.Chain.Style! getStyle();
+    method public String! referencesToString();
+    method public void setStyle(androidx.constraintlayout.core.dsl.Chain.Style!);
+    field protected java.util.ArrayList<androidx.constraintlayout.core.dsl.Ref!>! references;
+    field protected static final java.util.Map<androidx.constraintlayout.core.dsl.Chain.Style!,java.lang.String!>! styleMap;
+  }
+
+  public class Chain.Anchor {
+    method public void build(StringBuilder!);
+    method public String! getId();
+  }
+
+  public enum Chain.Style {
+    enum_constant public static final androidx.constraintlayout.core.dsl.Chain.Style PACKED;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Chain.Style SPREAD;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Chain.Style SPREAD_INSIDE;
+  }
+
+  public class Constraint {
+    ctor public Constraint(String!);
+    method protected void append(StringBuilder!, String!, float);
+    method public String! convertStringArrayToString(String![]!);
+    method public androidx.constraintlayout.core.dsl.Constraint.VAnchor! getBaseline();
+    method public androidx.constraintlayout.core.dsl.Constraint.VAnchor! getBottom();
+    method public float getCircleAngle();
+    method public String! getCircleConstraint();
+    method public int getCircleRadius();
+    method public String! getDimensionRatio();
+    method public int getEditorAbsoluteX();
+    method public int getEditorAbsoluteY();
+    method public androidx.constraintlayout.core.dsl.Constraint.HAnchor! getEnd();
+    method public int getHeight();
+    method public androidx.constraintlayout.core.dsl.Constraint.Behaviour! getHeightDefault();
+    method public int getHeightMax();
+    method public int getHeightMin();
+    method public float getHeightPercent();
+    method public float getHorizontalBias();
+    method public androidx.constraintlayout.core.dsl.Constraint.ChainMode! getHorizontalChainStyle();
+    method public float getHorizontalWeight();
+    method public androidx.constraintlayout.core.dsl.Constraint.HAnchor! getLeft();
+    method public String![]! getReferenceIds();
+    method public androidx.constraintlayout.core.dsl.Constraint.HAnchor! getRight();
+    method public androidx.constraintlayout.core.dsl.Constraint.HAnchor! getStart();
+    method public androidx.constraintlayout.core.dsl.Constraint.VAnchor! getTop();
+    method public float getVerticalBias();
+    method public androidx.constraintlayout.core.dsl.Constraint.ChainMode! getVerticalChainStyle();
+    method public float getVerticalWeight();
+    method public int getWidth();
+    method public androidx.constraintlayout.core.dsl.Constraint.Behaviour! getWidthDefault();
+    method public int getWidthMax();
+    method public int getWidthMin();
+    method public float getWidthPercent();
+    method public boolean isConstrainedHeight();
+    method public boolean isConstrainedWidth();
+    method public void linkToBaseline(androidx.constraintlayout.core.dsl.Constraint.VAnchor!);
+    method public void linkToBaseline(androidx.constraintlayout.core.dsl.Constraint.VAnchor!, int);
+    method public void linkToBaseline(androidx.constraintlayout.core.dsl.Constraint.VAnchor!, int, int);
+    method public void linkToBottom(androidx.constraintlayout.core.dsl.Constraint.VAnchor!);
+    method public void linkToBottom(androidx.constraintlayout.core.dsl.Constraint.VAnchor!, int);
+    method public void linkToBottom(androidx.constraintlayout.core.dsl.Constraint.VAnchor!, int, int);
+    method public void linkToEnd(androidx.constraintlayout.core.dsl.Constraint.HAnchor!);
+    method public void linkToEnd(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int);
+    method public void linkToEnd(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int, int);
+    method public void linkToLeft(androidx.constraintlayout.core.dsl.Constraint.HAnchor!);
+    method public void linkToLeft(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int);
+    method public void linkToLeft(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int, int);
+    method public void linkToRight(androidx.constraintlayout.core.dsl.Constraint.HAnchor!);
+    method public void linkToRight(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int);
+    method public void linkToRight(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int, int);
+    method public void linkToStart(androidx.constraintlayout.core.dsl.Constraint.HAnchor!);
+    method public void linkToStart(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int);
+    method public void linkToStart(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int, int);
+    method public void linkToTop(androidx.constraintlayout.core.dsl.Constraint.VAnchor!);
+    method public void linkToTop(androidx.constraintlayout.core.dsl.Constraint.VAnchor!, int);
+    method public void linkToTop(androidx.constraintlayout.core.dsl.Constraint.VAnchor!, int, int);
+    method public void setCircleAngle(float);
+    method public void setCircleConstraint(String!);
+    method public void setCircleRadius(int);
+    method public void setConstrainedHeight(boolean);
+    method public void setConstrainedWidth(boolean);
+    method public void setDimensionRatio(String!);
+    method public void setEditorAbsoluteX(int);
+    method public void setEditorAbsoluteY(int);
+    method public void setHeight(int);
+    method public void setHeightDefault(androidx.constraintlayout.core.dsl.Constraint.Behaviour!);
+    method public void setHeightMax(int);
+    method public void setHeightMin(int);
+    method public void setHeightPercent(float);
+    method public void setHorizontalBias(float);
+    method public void setHorizontalChainStyle(androidx.constraintlayout.core.dsl.Constraint.ChainMode!);
+    method public void setHorizontalWeight(float);
+    method public void setReferenceIds(String![]!);
+    method public void setVerticalBias(float);
+    method public void setVerticalChainStyle(androidx.constraintlayout.core.dsl.Constraint.ChainMode!);
+    method public void setVerticalWeight(float);
+    method public void setWidth(int);
+    method public void setWidthDefault(androidx.constraintlayout.core.dsl.Constraint.Behaviour!);
+    method public void setWidthMax(int);
+    method public void setWidthMin(int);
+    method public void setWidthPercent(float);
+    field public static final androidx.constraintlayout.core.dsl.Constraint! PARENT;
+  }
+
+  public class Constraint.Anchor {
+    method public void build(StringBuilder!);
+    method public String! getId();
+  }
+
+  public enum Constraint.Behaviour {
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.Behaviour PERCENT;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.Behaviour RATIO;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.Behaviour RESOLVED;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.Behaviour SPREAD;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.Behaviour WRAP;
+  }
+
+  public enum Constraint.ChainMode {
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.ChainMode PACKED;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.ChainMode SPREAD;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.ChainMode SPREAD_INSIDE;
+  }
+
+  public class Constraint.HAnchor extends androidx.constraintlayout.core.dsl.Constraint.Anchor {
+  }
+
+  public enum Constraint.HSide {
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.HSide END;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.HSide LEFT;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.HSide RIGHT;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.HSide START;
+  }
+
+  public enum Constraint.Side {
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.Side BASELINE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.Side BOTTOM;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.Side END;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.Side LEFT;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.Side RIGHT;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.Side START;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.Side TOP;
+  }
+
+  public class Constraint.VAnchor extends androidx.constraintlayout.core.dsl.Constraint.Anchor {
+  }
+
+  public enum Constraint.VSide {
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.VSide BASELINE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.VSide BOTTOM;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.VSide TOP;
+  }
+
+  public class ConstraintSet {
+    ctor public ConstraintSet(String!);
+    method public void add(androidx.constraintlayout.core.dsl.Constraint!);
+    method public void add(androidx.constraintlayout.core.dsl.Helper!);
+  }
+
+  public abstract class Guideline extends androidx.constraintlayout.core.dsl.Helper {
+    method public int getEnd();
+    method public float getPercent();
+    method public int getStart();
+    method public void setEnd(int);
+    method public void setPercent(float);
+    method public void setStart(int);
+  }
+
+  public class HChain extends androidx.constraintlayout.core.dsl.Chain {
+    ctor public HChain(String!);
+    ctor public HChain(String!, String!);
+    method public androidx.constraintlayout.core.dsl.HChain.HAnchor! getEnd();
+    method public androidx.constraintlayout.core.dsl.HChain.HAnchor! getLeft();
+    method public androidx.constraintlayout.core.dsl.HChain.HAnchor! getRight();
+    method public androidx.constraintlayout.core.dsl.HChain.HAnchor! getStart();
+    method public void linkToEnd(androidx.constraintlayout.core.dsl.Constraint.HAnchor!);
+    method public void linkToEnd(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int);
+    method public void linkToEnd(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int, int);
+    method public void linkToLeft(androidx.constraintlayout.core.dsl.Constraint.HAnchor!);
+    method public void linkToLeft(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int);
+    method public void linkToLeft(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int, int);
+    method public void linkToRight(androidx.constraintlayout.core.dsl.Constraint.HAnchor!);
+    method public void linkToRight(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int);
+    method public void linkToRight(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int, int);
+    method public void linkToStart(androidx.constraintlayout.core.dsl.Constraint.HAnchor!);
+    method public void linkToStart(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int);
+    method public void linkToStart(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int, int);
+  }
+
+  public class HChain.HAnchor extends androidx.constraintlayout.core.dsl.Chain.Anchor {
+  }
+
+  public class Helper {
+    ctor public Helper(String!, androidx.constraintlayout.core.dsl.Helper.HelperType!);
+    ctor public Helper(String!, androidx.constraintlayout.core.dsl.Helper.HelperType!, String!);
+    method public void append(java.util.Map<java.lang.String!,java.lang.String!>!, StringBuilder!);
+    method public java.util.Map<java.lang.String!,java.lang.String!>! convertConfigToMap();
+    method public String! getConfig();
+    method public String! getId();
+    method public androidx.constraintlayout.core.dsl.Helper.HelperType! getType();
+    method public static void main(String![]!);
+    field protected String! config;
+    field protected java.util.Map<java.lang.String!,java.lang.String!>! configMap;
+    field protected final String! name;
+    field protected static final java.util.Map<androidx.constraintlayout.core.dsl.Constraint.Side!,java.lang.String!>! sideMap;
+    field protected androidx.constraintlayout.core.dsl.Helper.HelperType! type;
+    field protected static final java.util.Map<androidx.constraintlayout.core.dsl.Helper.Type!,java.lang.String!>! typeMap;
+  }
+
+  public static final class Helper.HelperType {
+    ctor public Helper.HelperType(String!);
+  }
+
+  public enum Helper.Type {
+    enum_constant public static final androidx.constraintlayout.core.dsl.Helper.Type BARRIER;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Helper.Type HORIZONTAL_CHAIN;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Helper.Type HORIZONTAL_GUIDELINE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Helper.Type VERTICAL_CHAIN;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Helper.Type VERTICAL_GUIDELINE;
+  }
+
+  public class KeyAttribute extends androidx.constraintlayout.core.dsl.Keys {
+    ctor public KeyAttribute(int, String!);
+    method protected void attributesToString(StringBuilder!);
+    method public float getAlpha();
+    method public androidx.constraintlayout.core.dsl.KeyAttribute.Fit! getCurveFit();
+    method public float getPivotX();
+    method public float getPivotY();
+    method public float getRotation();
+    method public float getRotationX();
+    method public float getRotationY();
+    method public float getScaleX();
+    method public float getScaleY();
+    method public String! getTarget();
+    method public String! getTransitionEasing();
+    method public float getTransitionPathRotate();
+    method public float getTranslationX();
+    method public float getTranslationY();
+    method public float getTranslationZ();
+    method public androidx.constraintlayout.core.dsl.KeyAttribute.Visibility! getVisibility();
+    method public void setAlpha(float);
+    method public void setCurveFit(androidx.constraintlayout.core.dsl.KeyAttribute.Fit!);
+    method public void setPivotX(float);
+    method public void setPivotY(float);
+    method public void setRotation(float);
+    method public void setRotationX(float);
+    method public void setRotationY(float);
+    method public void setScaleX(float);
+    method public void setScaleY(float);
+    method public void setTarget(String!);
+    method public void setTransitionEasing(String!);
+    method public void setTransitionPathRotate(float);
+    method public void setTranslationX(float);
+    method public void setTranslationY(float);
+    method public void setTranslationZ(float);
+    method public void setVisibility(androidx.constraintlayout.core.dsl.KeyAttribute.Visibility!);
+    field protected String! TYPE;
+  }
+
+  public enum KeyAttribute.Fit {
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyAttribute.Fit LINEAR;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyAttribute.Fit SPLINE;
+  }
+
+  public enum KeyAttribute.Visibility {
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyAttribute.Visibility GONE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyAttribute.Visibility INVISIBLE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyAttribute.Visibility VISIBLE;
+  }
+
+  public class KeyAttributes extends androidx.constraintlayout.core.dsl.Keys {
+    method protected void attributesToString(StringBuilder!);
+    method public float[]! getAlpha();
+    method public androidx.constraintlayout.core.dsl.KeyAttributes.Fit! getCurveFit();
+    method public float[]! getPivotX();
+    method public float[]! getPivotY();
+    method public float[]! getRotation();
+    method public float[]! getRotationX();
+    method public float[]! getRotationY();
+    method public float[]! getScaleX();
+    method public float[]! getScaleY();
+    method public String![]! getTarget();
+    method public String! getTransitionEasing();
+    method public float[]! getTransitionPathRotate();
+    method public float[]! getTranslationX();
+    method public float[]! getTranslationY();
+    method public float[]! getTranslationZ();
+    method public androidx.constraintlayout.core.dsl.KeyAttributes.Visibility![]! getVisibility();
+    method public void setAlpha(float...!);
+    method public void setCurveFit(androidx.constraintlayout.core.dsl.KeyAttributes.Fit!);
+    method public void setPivotX(float...!);
+    method public void setPivotY(float...!);
+    method public void setRotation(float...!);
+    method public void setRotationX(float...!);
+    method public void setRotationY(float...!);
+    method public void setScaleX(float[]!);
+    method public void setScaleY(float[]!);
+    method public void setTarget(String![]!);
+    method public void setTransitionEasing(String!);
+    method public void setTransitionPathRotate(float...!);
+    method public void setTranslationX(float[]!);
+    method public void setTranslationY(float[]!);
+    method public void setTranslationZ(float[]!);
+    method public void setVisibility(androidx.constraintlayout.core.dsl.KeyAttributes.Visibility!...!);
+    field protected String! TYPE;
+  }
+
+  public enum KeyAttributes.Fit {
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyAttributes.Fit LINEAR;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyAttributes.Fit SPLINE;
+  }
+
+  public enum KeyAttributes.Visibility {
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyAttributes.Visibility GONE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyAttributes.Visibility INVISIBLE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyAttributes.Visibility VISIBLE;
+  }
+
+  public class KeyCycle extends androidx.constraintlayout.core.dsl.KeyAttribute {
+    method public float getOffset();
+    method public float getPeriod();
+    method public float getPhase();
+    method public androidx.constraintlayout.core.dsl.KeyCycle.Wave! getShape();
+    method public void setOffset(float);
+    method public void setPeriod(float);
+    method public void setPhase(float);
+    method public void setShape(androidx.constraintlayout.core.dsl.KeyCycle.Wave!);
+  }
+
+  public enum KeyCycle.Wave {
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyCycle.Wave COS;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyCycle.Wave REVERSE_SAW;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyCycle.Wave SAW;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyCycle.Wave SIN;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyCycle.Wave SQUARE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyCycle.Wave TRIANGLE;
+  }
+
+  public class KeyCycles extends androidx.constraintlayout.core.dsl.KeyAttributes {
+    method public float[]! getWaveOffset();
+    method public float[]! getWavePeriod();
+    method public float[]! getWavePhase();
+    method public androidx.constraintlayout.core.dsl.KeyCycles.Wave! getWaveShape();
+    method public void setWaveOffset(float...!);
+    method public void setWavePeriod(float...!);
+    method public void setWavePhase(float...!);
+    method public void setWaveShape(androidx.constraintlayout.core.dsl.KeyCycles.Wave!);
+  }
+
+  public enum KeyCycles.Wave {
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyCycles.Wave COS;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyCycles.Wave REVERSE_SAW;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyCycles.Wave SAW;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyCycles.Wave SIN;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyCycles.Wave SQUARE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyCycles.Wave TRIANGLE;
+  }
+
+  public class KeyFrames {
+    ctor public KeyFrames();
+    method public void add(androidx.constraintlayout.core.dsl.Keys!);
+  }
+
+  public class KeyPosition extends androidx.constraintlayout.core.dsl.Keys {
+    ctor public KeyPosition(String!, int);
+    method public int getFrames();
+    method public float getPercentHeight();
+    method public float getPercentWidth();
+    method public float getPercentX();
+    method public float getPercentY();
+    method public androidx.constraintlayout.core.dsl.KeyPosition.Type! getPositionType();
+    method public String! getTarget();
+    method public String! getTransitionEasing();
+    method public void setFrames(int);
+    method public void setPercentHeight(float);
+    method public void setPercentWidth(float);
+    method public void setPercentX(float);
+    method public void setPercentY(float);
+    method public void setPositionType(androidx.constraintlayout.core.dsl.KeyPosition.Type!);
+    method public void setTarget(String!);
+    method public void setTransitionEasing(String!);
+  }
+
+  public enum KeyPosition.Type {
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyPosition.Type CARTESIAN;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyPosition.Type PATH;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyPosition.Type SCREEN;
+  }
+
+  public class KeyPositions extends androidx.constraintlayout.core.dsl.Keys {
+    ctor public KeyPositions(int, java.lang.String!...!);
+    method public int[]! getFrames();
+    method public float[]! getPercentHeight();
+    method public float[]! getPercentWidth();
+    method public float[]! getPercentX();
+    method public float[]! getPercentY();
+    method public androidx.constraintlayout.core.dsl.KeyPositions.Type! getPositionType();
+    method public String![]! getTarget();
+    method public String! getTransitionEasing();
+    method public void setFrames(int...!);
+    method public void setPercentHeight(float...!);
+    method public void setPercentWidth(float...!);
+    method public void setPercentX(float...!);
+    method public void setPercentY(float...!);
+    method public void setPositionType(androidx.constraintlayout.core.dsl.KeyPositions.Type!);
+    method public void setTransitionEasing(String!);
+  }
+
+  public enum KeyPositions.Type {
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyPositions.Type CARTESIAN;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyPositions.Type PATH;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyPositions.Type SCREEN;
+  }
+
+  public class Keys {
+    ctor public Keys();
+    method protected void append(StringBuilder!, String!, float);
+    method protected void append(StringBuilder!, String!, float[]!);
+    method protected void append(StringBuilder!, String!, int);
+    method protected void append(StringBuilder!, String!, String!);
+    method protected void append(StringBuilder!, String!, String![]!);
+    method protected String! unpack(String![]!);
+  }
+
+  public class MotionScene {
+    ctor public MotionScene();
+    method public void addConstraintSet(androidx.constraintlayout.core.dsl.ConstraintSet!);
+    method public void addTransition(androidx.constraintlayout.core.dsl.Transition!);
+  }
+
+  public class OnSwipe {
+    ctor public OnSwipe();
+    ctor public OnSwipe(String!, androidx.constraintlayout.core.dsl.OnSwipe.Side!, androidx.constraintlayout.core.dsl.OnSwipe.Drag!);
+    method public androidx.constraintlayout.core.dsl.OnSwipe.Mode! getAutoCompleteMode();
+    method public androidx.constraintlayout.core.dsl.OnSwipe.Drag! getDragDirection();
+    method public float getDragScale();
+    method public float getDragThreshold();
+    method public String! getLimitBoundsTo();
+    method public float getMaxAcceleration();
+    method public float getMaxVelocity();
+    method public androidx.constraintlayout.core.dsl.OnSwipe.TouchUp! getOnTouchUp();
+    method public String! getRotationCenterId();
+    method public androidx.constraintlayout.core.dsl.OnSwipe.Boundary! getSpringBoundary();
+    method public float getSpringDamping();
+    method public float getSpringMass();
+    method public float getSpringStiffness();
+    method public float getSpringStopThreshold();
+    method public String! getTouchAnchorId();
+    method public androidx.constraintlayout.core.dsl.OnSwipe.Side! getTouchAnchorSide();
+    method public void setAutoCompleteMode(androidx.constraintlayout.core.dsl.OnSwipe.Mode!);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setDragDirection(androidx.constraintlayout.core.dsl.OnSwipe.Drag!);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setDragScale(int);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setDragThreshold(int);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setLimitBoundsTo(String!);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setMaxAcceleration(int);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setMaxVelocity(int);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setOnTouchUp(androidx.constraintlayout.core.dsl.OnSwipe.TouchUp!);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setRotateCenter(String!);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setSpringBoundary(androidx.constraintlayout.core.dsl.OnSwipe.Boundary!);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setSpringDamping(float);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setSpringMass(float);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setSpringStiffness(float);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setSpringStopThreshold(float);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setTouchAnchorId(String!);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setTouchAnchorSide(androidx.constraintlayout.core.dsl.OnSwipe.Side!);
+    field public static final int FLAG_DISABLE_POST_SCROLL = 1; // 0x1
+    field public static final int FLAG_DISABLE_SCROLL = 2; // 0x2
+  }
+
+  public enum OnSwipe.Boundary {
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Boundary BOUNCE_BOTH;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Boundary BOUNCE_END;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Boundary BOUNCE_START;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Boundary OVERSHOOT;
+  }
+
+  public enum OnSwipe.Drag {
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Drag ANTICLOCKWISE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Drag CLOCKWISE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Drag DOWN;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Drag END;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Drag LEFT;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Drag RIGHT;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Drag START;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Drag UP;
+  }
+
+  public enum OnSwipe.Mode {
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Mode SPRING;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Mode VELOCITY;
+  }
+
+  public enum OnSwipe.Side {
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Side BOTTOM;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Side END;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Side LEFT;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Side MIDDLE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Side RIGHT;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Side START;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Side TOP;
+  }
+
+  public enum OnSwipe.TouchUp {
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.TouchUp AUTOCOMPLETE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.TouchUp DECELERATE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.TouchUp DECELERATE_COMPLETE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.TouchUp NEVER_COMPLETE_END;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.TouchUp NEVER_COMPLETE_START;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.TouchUp STOP;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.TouchUp TO_END;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.TouchUp TO_START;
+  }
+
+  public class Ref {
+    method public static void addStringToReferences(String!, java.util.ArrayList<androidx.constraintlayout.core.dsl.Ref!>!);
+    method public String! getId();
+    method public float getPostMargin();
+    method public float getPreMargin();
+    method public float getWeight();
+    method public static float parseFloat(Object!);
+    method public static androidx.constraintlayout.core.dsl.Ref! parseStringToRef(String!);
+    method public void setId(String!);
+    method public void setPostMargin(float);
+    method public void setPreMargin(float);
+    method public void setWeight(float);
+  }
+
+  public class Transition {
+    ctor public Transition(String!, String!);
+    ctor public Transition(String!, String!, String!);
+    method public String! getId();
+    method public void setDuration(int);
+    method public void setFrom(String!);
+    method public void setId(String!);
+    method public void setKeyFrames(androidx.constraintlayout.core.dsl.Keys!);
+    method public void setOnSwipe(androidx.constraintlayout.core.dsl.OnSwipe!);
+    method public void setStagger(float);
+    method public void setTo(String!);
+  }
+
+  public class VChain extends androidx.constraintlayout.core.dsl.Chain {
+    ctor public VChain(String!);
+    ctor public VChain(String!, String!);
+    method public androidx.constraintlayout.core.dsl.VChain.VAnchor! getBaseline();
+    method public androidx.constraintlayout.core.dsl.VChain.VAnchor! getBottom();
+    method public androidx.constraintlayout.core.dsl.VChain.VAnchor! getTop();
+    method public void linkToBaseline(androidx.constraintlayout.core.dsl.Constraint.VAnchor!);
+    method public void linkToBaseline(androidx.constraintlayout.core.dsl.Constraint.VAnchor!, int);
+    method public void linkToBaseline(androidx.constraintlayout.core.dsl.Constraint.VAnchor!, int, int);
+    method public void linkToBottom(androidx.constraintlayout.core.dsl.Constraint.VAnchor!);
+    method public void linkToBottom(androidx.constraintlayout.core.dsl.Constraint.VAnchor!, int);
+    method public void linkToBottom(androidx.constraintlayout.core.dsl.Constraint.VAnchor!, int, int);
+    method public void linkToTop(androidx.constraintlayout.core.dsl.Constraint.VAnchor!);
+    method public void linkToTop(androidx.constraintlayout.core.dsl.Constraint.VAnchor!, int);
+    method public void linkToTop(androidx.constraintlayout.core.dsl.Constraint.VAnchor!, int, int);
+  }
+
+  public class VChain.VAnchor extends androidx.constraintlayout.core.dsl.Chain.Anchor {
+  }
+
+  public class VGuideline extends androidx.constraintlayout.core.dsl.Guideline {
+    ctor public VGuideline(String!);
+    ctor public VGuideline(String!, String!);
+  }
+
+}
+
+package androidx.constraintlayout.core.motion {
+
+  public class CustomAttribute {
+    ctor public CustomAttribute(androidx.constraintlayout.core.motion.CustomAttribute!, Object!);
+    ctor public CustomAttribute(String!, androidx.constraintlayout.core.motion.CustomAttribute.AttributeType!);
+    ctor public CustomAttribute(String!, androidx.constraintlayout.core.motion.CustomAttribute.AttributeType!, Object!, boolean);
+    method public boolean diff(androidx.constraintlayout.core.motion.CustomAttribute!);
+    method public androidx.constraintlayout.core.motion.CustomAttribute.AttributeType! getType();
+    method public float getValueToInterpolate();
+    method public void getValuesToInterpolate(float[]!);
+    method public static int hsvToRgb(float, float, float);
+    method public boolean isContinuous();
+    method public int numberOfInterpolatedValues();
+    method public void setColorValue(int);
+    method public void setFloatValue(float);
+    method public void setIntValue(int);
+    method public void setStringValue(String!);
+    method public void setValue(float[]!);
+    method public void setValue(Object!);
+  }
+
+  public enum CustomAttribute.AttributeType {
+    enum_constant public static final androidx.constraintlayout.core.motion.CustomAttribute.AttributeType BOOLEAN_TYPE;
+    enum_constant public static final androidx.constraintlayout.core.motion.CustomAttribute.AttributeType COLOR_DRAWABLE_TYPE;
+    enum_constant public static final androidx.constraintlayout.core.motion.CustomAttribute.AttributeType COLOR_TYPE;
+    enum_constant public static final androidx.constraintlayout.core.motion.CustomAttribute.AttributeType DIMENSION_TYPE;
+    enum_constant public static final androidx.constraintlayout.core.motion.CustomAttribute.AttributeType FLOAT_TYPE;
+    enum_constant public static final androidx.constraintlayout.core.motion.CustomAttribute.AttributeType INT_TYPE;
+    enum_constant public static final androidx.constraintlayout.core.motion.CustomAttribute.AttributeType REFERENCE_TYPE;
+    enum_constant public static final androidx.constraintlayout.core.motion.CustomAttribute.AttributeType STRING_TYPE;
+  }
+
+  public class CustomVariable {
+    ctor public CustomVariable(androidx.constraintlayout.core.motion.CustomVariable!);
+    ctor public CustomVariable(androidx.constraintlayout.core.motion.CustomVariable!, Object!);
+    ctor public CustomVariable(String!, int);
+    ctor public CustomVariable(String!, int, boolean);
+    ctor public CustomVariable(String!, int, float);
+    ctor public CustomVariable(String!, int, int);
+    ctor public CustomVariable(String!, int, Object!);
+    ctor public CustomVariable(String!, int, String!);
+    method public void applyToWidget(androidx.constraintlayout.core.motion.MotionWidget!);
+    method public static String! colorString(int);
+    method public androidx.constraintlayout.core.motion.CustomVariable! copy();
+    method public boolean diff(androidx.constraintlayout.core.motion.CustomVariable!);
+    method public boolean getBooleanValue();
+    method public int getColorValue();
+    method public float getFloatValue();
+    method public int getIntegerValue();
+    method public int getInterpolatedColor(float[]!);
+    method public String! getName();
+    method public String! getStringValue();
+    method public int getType();
+    method public float getValueToInterpolate();
+    method public void getValuesToInterpolate(float[]!);
+    method public static int hsvToRgb(float, float, float);
+    method public boolean isContinuous();
+    method public int numberOfInterpolatedValues();
+    method public static int rgbaTocColor(float, float, float, float);
+    method public void setBooleanValue(boolean);
+    method public void setFloatValue(float);
+    method public void setIntValue(int);
+    method public void setInterpolatedValue(androidx.constraintlayout.core.motion.MotionWidget!, float[]!);
+    method public void setStringValue(String!);
+    method public void setValue(float[]!);
+    method public void setValue(Object!);
+  }
+
+  public class Motion implements androidx.constraintlayout.core.motion.utils.TypedValues {
+    ctor public Motion(androidx.constraintlayout.core.motion.MotionWidget!);
+    method public void addKey(androidx.constraintlayout.core.motion.key.MotionKey!);
+    method public int buildKeyFrames(float[]!, int[]!, int[]!);
+    method public void buildPath(float[]!, int);
+    method public void buildRect(float, float[]!, int);
+    method public String! getAnimateRelativeTo();
+    method public void getCenter(double, float[]!, float[]!);
+    method public float getCenterX();
+    method public float getCenterY();
+    method public void getDpDt(float, float, float, float[]!);
+    method public int getDrawPath();
+    method public float getFinalHeight();
+    method public float getFinalWidth();
+    method public float getFinalX();
+    method public float getFinalY();
+    method public int getId(String!);
+    method public androidx.constraintlayout.core.motion.MotionPaths! getKeyFrame(int);
+    method public int getKeyFrameInfo(int, int[]!);
+    method public int getKeyFramePositions(int[]!, float[]!);
+    method public float getMotionStagger();
+    method public float getStartHeight();
+    method public float getStartWidth();
+    method public float getStartX();
+    method public float getStartY();
+    method public int getTransformPivotTarget();
+    method public androidx.constraintlayout.core.motion.MotionWidget! getView();
+    method public boolean interpolate(androidx.constraintlayout.core.motion.MotionWidget!, float, long, androidx.constraintlayout.core.motion.utils.KeyCache!);
+    method public void setDrawPath(int);
+    method public void setEnd(androidx.constraintlayout.core.motion.MotionWidget!);
+    method public void setIdString(String!);
+    method public void setPathMotionArc(int);
+    method public void setStaggerOffset(float);
+    method public void setStaggerScale(float);
+    method public void setStart(androidx.constraintlayout.core.motion.MotionWidget!);
+    method public void setStartState(androidx.constraintlayout.core.motion.utils.ViewState!, androidx.constraintlayout.core.motion.MotionWidget!, int, int, int);
+    method public void setTransformPivotTarget(int);
+    method public boolean setValue(int, boolean);
+    method public boolean setValue(int, float);
+    method public boolean setValue(int, int);
+    method public boolean setValue(int, String!);
+    method public void setView(androidx.constraintlayout.core.motion.MotionWidget!);
+    method public void setup(int, int, float, long);
+    method public void setupRelative(androidx.constraintlayout.core.motion.Motion!);
+    field public static final int DRAW_PATH_AS_CONFIGURED = 4; // 0x4
+    field public static final int DRAW_PATH_BASIC = 1; // 0x1
+    field public static final int DRAW_PATH_CARTESIAN = 3; // 0x3
+    field public static final int DRAW_PATH_NONE = 0; // 0x0
+    field public static final int DRAW_PATH_RECTANGLE = 5; // 0x5
+    field public static final int DRAW_PATH_RELATIVE = 2; // 0x2
+    field public static final int DRAW_PATH_SCREEN = 6; // 0x6
+    field public static final int HORIZONTAL_PATH_X = 2; // 0x2
+    field public static final int HORIZONTAL_PATH_Y = 3; // 0x3
+    field public static final int PATH_PERCENT = 0; // 0x0
+    field public static final int PATH_PERPENDICULAR = 1; // 0x1
+    field public static final int ROTATION_LEFT = 2; // 0x2
+    field public static final int ROTATION_RIGHT = 1; // 0x1
+    field public static final int VERTICAL_PATH_X = 4; // 0x4
+    field public static final int VERTICAL_PATH_Y = 5; // 0x5
+    field public String! mId;
+  }
+
+  public class MotionPaths implements java.lang.Comparable<androidx.constraintlayout.core.motion.MotionPaths!> {
+    ctor public MotionPaths();
+    ctor public MotionPaths(int, int, androidx.constraintlayout.core.motion.key.MotionKeyPosition!, androidx.constraintlayout.core.motion.MotionPaths!, androidx.constraintlayout.core.motion.MotionPaths!);
+    method public void applyParameters(androidx.constraintlayout.core.motion.MotionWidget!);
+    method public int compareTo(androidx.constraintlayout.core.motion.MotionPaths!);
+    method public void configureRelativeTo(androidx.constraintlayout.core.motion.Motion!);
+    method public void setupRelative(androidx.constraintlayout.core.motion.Motion!, androidx.constraintlayout.core.motion.MotionPaths!);
+    field public static final int CARTESIAN = 0; // 0x0
+    field public static final boolean DEBUG = false;
+    field public static final boolean OLD_WAY = false;
+    field public static final int PERPENDICULAR = 1; // 0x1
+    field public static final int SCREEN = 2; // 0x2
+    field public static final String TAG = "MotionPaths";
+    field public String! mId;
+  }
+
+  public class MotionWidget implements androidx.constraintlayout.core.motion.utils.TypedValues {
+    ctor public MotionWidget();
+    ctor public MotionWidget(androidx.constraintlayout.core.state.WidgetFrame!);
+    method public androidx.constraintlayout.core.motion.MotionWidget! findViewById(int);
+    method public float getAlpha();
+    method public int getBottom();
+    method public androidx.constraintlayout.core.motion.CustomVariable! getCustomAttribute(String!);
+    method public java.util.Set<java.lang.String!>! getCustomAttributeNames();
+    method public int getHeight();
+    method public int getId(String!);
+    method public int getLeft();
+    method public String! getName();
+    method public androidx.constraintlayout.core.motion.MotionWidget! getParent();
+    method public float getPivotX();
+    method public float getPivotY();
+    method public int getRight();
+    method public float getRotationX();
+    method public float getRotationY();
+    method public float getRotationZ();
+    method public float getScaleX();
+    method public float getScaleY();
+    method public int getTop();
+    method public float getTranslationX();
+    method public float getTranslationY();
+    method public float getTranslationZ();
+    method public float getValueAttributes(int);
+    method public int getVisibility();
+    method public androidx.constraintlayout.core.state.WidgetFrame! getWidgetFrame();
+    method public int getWidth();
+    method public int getX();
+    method public int getY();
+    method public void layout(int, int, int, int);
+    method public void setBounds(int, int, int, int);
+    method public void setCustomAttribute(String!, int, boolean);
+    method public void setCustomAttribute(String!, int, float);
+    method public void setCustomAttribute(String!, int, int);
+    method public void setCustomAttribute(String!, int, String!);
+    method public void setInterpolatedValue(androidx.constraintlayout.core.motion.CustomAttribute!, float[]!);
+    method public void setPivotX(float);
+    method public void setPivotY(float);
+    method public void setRotationX(float);
+    method public void setRotationY(float);
+    method public void setRotationZ(float);
+    method public void setScaleX(float);
+    method public void setScaleY(float);
+    method public void setTranslationX(float);
+    method public void setTranslationY(float);
+    method public void setTranslationZ(float);
+    method public boolean setValue(int, boolean);
+    method public boolean setValue(int, float);
+    method public boolean setValue(int, int);
+    method public boolean setValue(int, String!);
+    method public boolean setValueAttributes(int, float);
+    method public boolean setValueMotion(int, float);
+    method public boolean setValueMotion(int, int);
+    method public boolean setValueMotion(int, String!);
+    method public void setVisibility(int);
+    method public void updateMotion(androidx.constraintlayout.core.motion.utils.TypedValues!);
+    field public static final int FILL_PARENT = -1; // 0xffffffff
+    field public static final int GONE_UNSET = -2147483648; // 0x80000000
+    field public static final int INVISIBLE = 0; // 0x0
+    field public static final int MATCH_CONSTRAINT = 0; // 0x0
+    field public static final int MATCH_CONSTRAINT_WRAP = 1; // 0x1
+    field public static final int MATCH_PARENT = -1; // 0xffffffff
+    field public static final int PARENT_ID = 0; // 0x0
+    field public static final int ROTATE_LEFT_OF_PORTRATE = 4; // 0x4
+    field public static final int ROTATE_NONE = 0; // 0x0
+    field public static final int ROTATE_PORTRATE_OF_LEFT = 2; // 0x2
+    field public static final int ROTATE_PORTRATE_OF_RIGHT = 1; // 0x1
+    field public static final int ROTATE_RIGHT_OF_PORTRATE = 3; // 0x3
+    field public static final int UNSET = -1; // 0xffffffff
+    field public static final int VISIBILITY_MODE_IGNORE = 1; // 0x1
+    field public static final int VISIBILITY_MODE_NORMAL = 0; // 0x0
+    field public static final int VISIBLE = 4; // 0x4
+    field public static final int WRAP_CONTENT = -2; // 0xfffffffe
+  }
+
+  public static class MotionWidget.Motion {
+    ctor public MotionWidget.Motion();
+    field public int mAnimateCircleAngleTo;
+    field public String! mAnimateRelativeTo;
+    field public int mDrawPath;
+    field public float mMotionStagger;
+    field public int mPathMotionArc;
+    field public float mPathRotate;
+    field public int mPolarRelativeTo;
+    field public int mQuantizeInterpolatorID;
+    field public String! mQuantizeInterpolatorString;
+    field public int mQuantizeInterpolatorType;
+    field public float mQuantizeMotionPhase;
+    field public int mQuantizeMotionSteps;
+    field public String! mTransitionEasing;
+  }
+
+  public static class MotionWidget.PropertySet {
+    ctor public MotionWidget.PropertySet();
+    field public float alpha;
+    field public float mProgress;
+    field public int mVisibilityMode;
+    field public int visibility;
+  }
+
+}
+
+package androidx.constraintlayout.core.motion.key {
+
+  public class MotionConstraintSet {
+    ctor public MotionConstraintSet();
+    field public static final int ROTATE_LEFT_OF_PORTRATE = 4; // 0x4
+    field public static final int ROTATE_NONE = 0; // 0x0
+    field public static final int ROTATE_PORTRATE_OF_LEFT = 2; // 0x2
+    field public static final int ROTATE_PORTRATE_OF_RIGHT = 1; // 0x1
+    field public static final int ROTATE_RIGHT_OF_PORTRATE = 3; // 0x3
+    field public String! mIdString;
+    field public int mRotate;
+  }
+
+  public abstract class MotionKey implements androidx.constraintlayout.core.motion.utils.TypedValues {
+    ctor public MotionKey();
+    method public abstract void addValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.core.motion.utils.SplineSet!>!);
+    method public abstract androidx.constraintlayout.core.motion.key.MotionKey! clone();
+    method public androidx.constraintlayout.core.motion.key.MotionKey! copy(androidx.constraintlayout.core.motion.key.MotionKey!);
+    method public abstract void getAttributeNames(java.util.HashSet<java.lang.String!>!);
+    method public int getFramePosition();
+    method public void setCustomAttribute(String!, int, boolean);
+    method public void setCustomAttribute(String!, int, float);
+    method public void setCustomAttribute(String!, int, int);
+    method public void setCustomAttribute(String!, int, String!);
+    method public void setFramePosition(int);
+    method public void setInterpolation(java.util.HashMap<java.lang.String!,java.lang.Integer!>!);
+    method public boolean setValue(int, boolean);
+    method public boolean setValue(int, float);
+    method public boolean setValue(int, int);
+    method public boolean setValue(int, String!);
+    method public androidx.constraintlayout.core.motion.key.MotionKey! setViewId(int);
+    field public static final String ALPHA = "alpha";
+    field public static final String CUSTOM = "CUSTOM";
+    field public static final String ELEVATION = "elevation";
+    field public static final String ROTATION = "rotationZ";
+    field public static final String ROTATION_X = "rotationX";
+    field public static final String SCALE_X = "scaleX";
+    field public static final String SCALE_Y = "scaleY";
+    field public static final String TRANSITION_PATH_ROTATE = "transitionPathRotate";
+    field public static final String TRANSLATION_X = "translationX";
+    field public static final String TRANSLATION_Y = "translationY";
+    field public static int UNSET;
+    field public static final String VISIBILITY = "visibility";
+    field public java.util.HashMap<java.lang.String!,androidx.constraintlayout.core.motion.CustomVariable!>! mCustom;
+    field public int mFramePosition;
+    field public int mType;
+  }
+
+  public class MotionKeyAttributes extends androidx.constraintlayout.core.motion.key.MotionKey {
+    ctor public MotionKeyAttributes();
+    method public void addValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.core.motion.utils.SplineSet!>!);
+    method public androidx.constraintlayout.core.motion.key.MotionKey! clone();
+    method public void getAttributeNames(java.util.HashSet<java.lang.String!>!);
+    method public int getCurveFit();
+    method public int getId(String!);
+    method public void printAttributes();
+    field public static final int KEY_TYPE = 1; // 0x1
+  }
+
+  public class MotionKeyCycle extends androidx.constraintlayout.core.motion.key.MotionKey {
+    ctor public MotionKeyCycle();
+    method public void addCycleValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.core.motion.utils.KeyCycleOscillator!>!);
+    method public void addValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.core.motion.utils.SplineSet!>!);
+    method public androidx.constraintlayout.core.motion.key.MotionKey! clone();
+    method public void dump();
+    method public void getAttributeNames(java.util.HashSet<java.lang.String!>!);
+    method public int getId(String!);
+    method public float getValue(String!);
+    method public void printAttributes();
+    field public static final int KEY_TYPE = 4; // 0x4
+    field public static final int SHAPE_BOUNCE = 6; // 0x6
+    field public static final int SHAPE_COS_WAVE = 5; // 0x5
+    field public static final int SHAPE_REVERSE_SAW_WAVE = 4; // 0x4
+    field public static final int SHAPE_SAW_WAVE = 3; // 0x3
+    field public static final int SHAPE_SIN_WAVE = 0; // 0x0
+    field public static final int SHAPE_SQUARE_WAVE = 1; // 0x1
+    field public static final int SHAPE_TRIANGLE_WAVE = 2; // 0x2
+    field public static final String WAVE_OFFSET = "waveOffset";
+    field public static final String WAVE_PERIOD = "wavePeriod";
+    field public static final String WAVE_PHASE = "wavePhase";
+    field public static final String WAVE_SHAPE = "waveShape";
+  }
+
+  public class MotionKeyPosition extends androidx.constraintlayout.core.motion.key.MotionKey {
+    ctor public MotionKeyPosition();
+    method public void addValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.core.motion.utils.SplineSet!>!);
+    method public androidx.constraintlayout.core.motion.key.MotionKey! clone();
+    method public void getAttributeNames(java.util.HashSet<java.lang.String!>!);
+    method public int getId(String!);
+    method public boolean intersects(int, int, androidx.constraintlayout.core.motion.utils.FloatRect!, androidx.constraintlayout.core.motion.utils.FloatRect!, float, float);
+    method public void positionAttributes(androidx.constraintlayout.core.motion.MotionWidget!, androidx.constraintlayout.core.motion.utils.FloatRect!, androidx.constraintlayout.core.motion.utils.FloatRect!, float, float, String![]!, float[]!);
+    field protected static final float SELECTION_SLOPE = 20.0f;
+    field public static final int TYPE_CARTESIAN = 0; // 0x0
+    field public static final int TYPE_PATH = 1; // 0x1
+    field public static final int TYPE_SCREEN = 2; // 0x2
+    field public float mAltPercentX;
+    field public float mAltPercentY;
+    field public int mCurveFit;
+    field public int mDrawPath;
+    field public int mPathMotionArc;
+    field public float mPercentHeight;
+    field public float mPercentWidth;
+    field public float mPercentX;
+    field public float mPercentY;
+    field public int mPositionType;
+    field public String! mTransitionEasing;
+  }
+
+  public class MotionKeyTimeCycle extends androidx.constraintlayout.core.motion.key.MotionKey {
+    ctor public MotionKeyTimeCycle();
+    method public void addTimeValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.core.motion.utils.TimeCycleSplineSet!>!);
+    method public void addValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.core.motion.utils.SplineSet!>!);
+    method public androidx.constraintlayout.core.motion.key.MotionKey! clone();
+    method public androidx.constraintlayout.core.motion.key.MotionKeyTimeCycle! copy(androidx.constraintlayout.core.motion.key.MotionKey!);
+    method public void getAttributeNames(java.util.HashSet<java.lang.String!>!);
+    method public int getId(String!);
+    field public static final int KEY_TYPE = 3; // 0x3
+  }
+
+  public class MotionKeyTrigger extends androidx.constraintlayout.core.motion.key.MotionKey {
+    ctor public MotionKeyTrigger();
+    method public void addValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.core.motion.utils.SplineSet!>!);
+    method public androidx.constraintlayout.core.motion.key.MotionKey! clone();
+    method public void conditionallyFire(float, androidx.constraintlayout.core.motion.MotionWidget!);
+    method public androidx.constraintlayout.core.motion.key.MotionKeyTrigger! copy(androidx.constraintlayout.core.motion.key.MotionKey!);
+    method public void getAttributeNames(java.util.HashSet<java.lang.String!>!);
+    method public int getId(String!);
+    field public static final String CROSS = "CROSS";
+    field public static final int KEY_TYPE = 5; // 0x5
+    field public static final String NEGATIVE_CROSS = "negativeCross";
+    field public static final String POSITIVE_CROSS = "positiveCross";
+    field public static final String POST_LAYOUT = "postLayout";
+    field public static final String TRIGGER_COLLISION_ID = "triggerCollisionId";
+    field public static final String TRIGGER_COLLISION_VIEW = "triggerCollisionView";
+    field public static final String TRIGGER_ID = "triggerID";
+    field public static final String TRIGGER_RECEIVER = "triggerReceiver";
+    field public static final String TRIGGER_SLACK = "triggerSlack";
+    field public static final int TYPE_CROSS = 312; // 0x138
+    field public static final int TYPE_NEGATIVE_CROSS = 310; // 0x136
+    field public static final int TYPE_POSITIVE_CROSS = 309; // 0x135
+    field public static final int TYPE_POST_LAYOUT = 304; // 0x130
+    field public static final int TYPE_TRIGGER_COLLISION_ID = 307; // 0x133
+    field public static final int TYPE_TRIGGER_COLLISION_VIEW = 306; // 0x132
+    field public static final int TYPE_TRIGGER_ID = 308; // 0x134
+    field public static final int TYPE_TRIGGER_RECEIVER = 311; // 0x137
+    field public static final int TYPE_TRIGGER_SLACK = 305; // 0x131
+    field public static final int TYPE_VIEW_TRANSITION_ON_CROSS = 301; // 0x12d
+    field public static final int TYPE_VIEW_TRANSITION_ON_NEGATIVE_CROSS = 303; // 0x12f
+    field public static final int TYPE_VIEW_TRANSITION_ON_POSITIVE_CROSS = 302; // 0x12e
+    field public static final String VIEW_TRANSITION_ON_CROSS = "viewTransitionOnCross";
+    field public static final String VIEW_TRANSITION_ON_NEGATIVE_CROSS = "viewTransitionOnNegativeCross";
+    field public static final String VIEW_TRANSITION_ON_POSITIVE_CROSS = "viewTransitionOnPositiveCross";
+  }
+
+}
+
+package androidx.constraintlayout.core.motion.parse {
+
+  public class KeyParser {
+    ctor public KeyParser();
+    method public static void main(String![]!);
+    method public static androidx.constraintlayout.core.motion.utils.TypedBundle! parseAttributes(String!);
+  }
+
+}
+
+package androidx.constraintlayout.core.motion.utils {
+
+  public class ArcCurveFit extends androidx.constraintlayout.core.motion.utils.CurveFit {
+    ctor public ArcCurveFit(int[]!, double[]!, double[]![]!);
+    method public void getPos(double, double[]!);
+    method public void getPos(double, float[]!);
+    method public double getPos(double, int);
+    method public void getSlope(double, double[]!);
+    method public double getSlope(double, int);
+    method public double[]! getTimePoints();
+    field public static final int ARC_ABOVE = 5; // 0x5
+    field public static final int ARC_BELOW = 4; // 0x4
+    field public static final int ARC_START_FLIP = 3; // 0x3
+    field public static final int ARC_START_HORIZONTAL = 2; // 0x2
+    field public static final int ARC_START_LINEAR = 0; // 0x0
+    field public static final int ARC_START_VERTICAL = 1; // 0x1
+  }
+
+  public abstract class CurveFit {
+    ctor public CurveFit();
+    method public static androidx.constraintlayout.core.motion.utils.CurveFit! get(int, double[]!, double[]![]!);
+    method public static androidx.constraintlayout.core.motion.utils.CurveFit! getArc(int[]!, double[]!, double[]![]!);
+    method public abstract void getPos(double, double[]!);
+    method public abstract void getPos(double, float[]!);
+    method public abstract double getPos(double, int);
+    method public abstract void getSlope(double, double[]!);
+    method public abstract double getSlope(double, int);
+    method public abstract double[]! getTimePoints();
+    field public static final int CONSTANT = 2; // 0x2
+    field public static final int LINEAR = 1; // 0x1
+    field public static final int SPLINE = 0; // 0x0
+  }
+
+  public interface DifferentialInterpolator {
+    method public float getInterpolation(float);
+    method public float getVelocity();
+  }
+
+  public class Easing {
+    ctor public Easing();
+    method public double get(double);
+    method public double getDiff(double);
+    method public static androidx.constraintlayout.core.motion.utils.Easing! getInterpolator(String!);
+    field public static String![]! NAMED_EASING;
+  }
+
+  public class FloatRect {
+    ctor public FloatRect();
+    method public final float centerX();
+    method public final float centerY();
+    field public float bottom;
+    field public float left;
+    field public float right;
+    field public float top;
+  }
+
+  public class HyperSpline {
+    ctor public HyperSpline();
+    ctor public HyperSpline(double[]![]!);
+    method public double approxLength(androidx.constraintlayout.core.motion.utils.HyperSpline.Cubic![]!);
+    method public void getPos(double, double[]!);
+    method public void getPos(double, float[]!);
+    method public double getPos(double, int);
+    method public void getVelocity(double, double[]!);
+    method public void setup(double[]![]!);
+  }
+
+  public static class HyperSpline.Cubic {
+    ctor public HyperSpline.Cubic(double, double, double, double);
+    method public double eval(double);
+    method public double vel(double);
+  }
+
+  public class KeyCache {
+    ctor public KeyCache();
+    method public float getFloatValue(Object!, String!, int);
+    method public void setFloatValue(Object!, String!, int, float);
+  }
+
+  public abstract class KeyCycleOscillator {
+    ctor public KeyCycleOscillator();
+    method public float get(float);
+    method public androidx.constraintlayout.core.motion.utils.CurveFit! getCurveFit();
+    method public float getSlope(float);
+    method public static androidx.constraintlayout.core.motion.utils.KeyCycleOscillator! makeWidgetCycle(String!);
+    method protected void setCustom(Object!);
+    method public void setPoint(int, int, String!, int, float, float, float, float);
+    method public void setPoint(int, int, String!, int, float, float, float, float, Object!);
+    method public void setProperty(androidx.constraintlayout.core.motion.MotionWidget!, float);
+    method public void setType(String!);
+    method public void setup(float);
+    method public boolean variesByPath();
+    field public int mVariesBy;
+  }
+
+  public static class KeyCycleOscillator.PathRotateSet extends androidx.constraintlayout.core.motion.utils.KeyCycleOscillator {
+    ctor public KeyCycleOscillator.PathRotateSet(String!);
+    method public void setPathRotate(androidx.constraintlayout.core.motion.MotionWidget!, float, double, double);
+  }
+
+  public class KeyFrameArray {
+    ctor public KeyFrameArray();
+  }
+
+  public static class KeyFrameArray.CustomArray {
+    ctor public KeyFrameArray.CustomArray();
+    method public void append(int, androidx.constraintlayout.core.motion.CustomAttribute!);
+    method public void clear();
+    method public void dump();
+    method public int keyAt(int);
+    method public void remove(int);
+    method public int size();
+    method public androidx.constraintlayout.core.motion.CustomAttribute! valueAt(int);
+  }
+
+  public static class KeyFrameArray.CustomVar {
+    ctor public KeyFrameArray.CustomVar();
+    method public void append(int, androidx.constraintlayout.core.motion.CustomVariable!);
+    method public void clear();
+    method public void dump();
+    method public int keyAt(int);
+    method public void remove(int);
+    method public int size();
+    method public androidx.constraintlayout.core.motion.CustomVariable! valueAt(int);
+  }
+
+  public class LinearCurveFit extends androidx.constraintlayout.core.motion.utils.CurveFit {
+    ctor public LinearCurveFit(double[]!, double[]![]!);
+    method public void getPos(double, double[]!);
+    method public void getPos(double, float[]!);
+    method public double getPos(double, int);
+    method public void getSlope(double, double[]!);
+    method public double getSlope(double, int);
+    method public double[]! getTimePoints();
+  }
+
+  public class MonotonicCurveFit extends androidx.constraintlayout.core.motion.utils.CurveFit {
+    ctor public MonotonicCurveFit(double[]!, double[]![]!);
+    method public static androidx.constraintlayout.core.motion.utils.MonotonicCurveFit! buildWave(String!);
+    method public void getPos(double, double[]!);
+    method public void getPos(double, float[]!);
+    method public double getPos(double, int);
+    method public void getSlope(double, double[]!);
+    method public double getSlope(double, int);
+    method public double[]! getTimePoints();
+  }
+
+  public class Oscillator {
+    ctor public Oscillator();
+    method public void addPoint(double, float);
+    method public double getSlope(double, double, double);
+    method public double getValue(double, double);
+    method public void normalize();
+    method public void setType(int, String!);
+    field public static final int BOUNCE = 6; // 0x6
+    field public static final int COS_WAVE = 5; // 0x5
+    field public static final int CUSTOM = 7; // 0x7
+    field public static final int REVERSE_SAW_WAVE = 4; // 0x4
+    field public static final int SAW_WAVE = 3; // 0x3
+    field public static final int SIN_WAVE = 0; // 0x0
+    field public static final int SQUARE_WAVE = 1; // 0x1
+    field public static String! TAG;
+    field public static final int TRIANGLE_WAVE = 2; // 0x2
+  }
+
+  public class Rect {
+    ctor public Rect();
+    method public int height();
+    method public int width();
+    field public int bottom;
+    field public int left;
+    field public int right;
+    field public int top;
+  }
+
+  public class Schlick extends androidx.constraintlayout.core.motion.utils.Easing {
+  }
+
+  public abstract class SplineSet {
+    ctor public SplineSet();
+    method public float get(float);
+    method public androidx.constraintlayout.core.motion.utils.CurveFit! getCurveFit();
+    method public float getSlope(float);
+    method public static androidx.constraintlayout.core.motion.utils.SplineSet! makeCustomSpline(String!, androidx.constraintlayout.core.motion.utils.KeyFrameArray.CustomArray!);
+    method public static androidx.constraintlayout.core.motion.utils.SplineSet! makeCustomSplineSet(String!, androidx.constraintlayout.core.motion.utils.KeyFrameArray.CustomVar!);
+    method public static androidx.constraintlayout.core.motion.utils.SplineSet! makeSpline(String!, long);
+    method public void setPoint(int, float);
+    method public void setProperty(androidx.constraintlayout.core.motion.utils.TypedValues!, float);
+    method public void setType(String!);
+    method public void setup(int);
+    field protected androidx.constraintlayout.core.motion.utils.CurveFit! mCurveFit;
+    field protected int[]! mTimePoints;
+    field protected float[]! mValues;
+  }
+
+  public static class SplineSet.CustomSet extends androidx.constraintlayout.core.motion.utils.SplineSet {
+    ctor public SplineSet.CustomSet(String!, androidx.constraintlayout.core.motion.utils.KeyFrameArray.CustomArray!);
+    method public void setPoint(int, androidx.constraintlayout.core.motion.CustomAttribute!);
+    method public void setProperty(androidx.constraintlayout.core.state.WidgetFrame!, float);
+  }
+
+  public static class SplineSet.CustomSpline extends androidx.constraintlayout.core.motion.utils.SplineSet {
+    ctor public SplineSet.CustomSpline(String!, androidx.constraintlayout.core.motion.utils.KeyFrameArray.CustomVar!);
+    method public void setPoint(int, androidx.constraintlayout.core.motion.CustomVariable!);
+    method public void setProperty(androidx.constraintlayout.core.motion.MotionWidget!, float);
+  }
+
+  public class SpringStopEngine implements androidx.constraintlayout.core.motion.utils.StopEngine {
+    ctor public SpringStopEngine();
+    method public String! debug(String!, float);
+    method public float getAcceleration();
+    method public float getInterpolation(float);
+    method public float getVelocity();
+    method public float getVelocity(float);
+    method public boolean isStopped();
+    method public void springConfig(float, float, float, float, float, float, float, int);
+  }
+
+  public class StepCurve extends androidx.constraintlayout.core.motion.utils.Easing {
+  }
+
+  public interface StopEngine {
+    method public String! debug(String!, float);
+    method public float getInterpolation(float);
+    method public float getVelocity();
+    method public float getVelocity(float);
+    method public boolean isStopped();
+  }
+
+  public class StopLogicEngine implements androidx.constraintlayout.core.motion.utils.StopEngine {
+    ctor public StopLogicEngine();
+    method public void config(float, float, float, float, float, float);
+    method public String! debug(String!, float);
+    method public float getInterpolation(float);
+    method public float getVelocity();
+    method public float getVelocity(float);
+    method public boolean isStopped();
+  }
+
+  public static class StopLogicEngine.Decelerate implements androidx.constraintlayout.core.motion.utils.StopEngine {
+    ctor public StopLogicEngine.Decelerate();
+    method public void config(float, float, float);
+    method public String! debug(String!, float);
+    method public float getInterpolation(float);
+    method public float getVelocity();
+    method public float getVelocity(float);
+    method public boolean isStopped();
+  }
+
+  public abstract class TimeCycleSplineSet {
+    ctor public TimeCycleSplineSet();
+    method protected float calcWave(float);
+    method public androidx.constraintlayout.core.motion.utils.CurveFit! getCurveFit();
+    method public void setPoint(int, float, float, int, float);
+    method protected void setStartTime(long);
+    method public void setType(String!);
+    method public void setup(int);
+    field protected static final int CURVE_OFFSET = 2; // 0x2
+    field protected static final int CURVE_PERIOD = 1; // 0x1
+    field protected static final int CURVE_VALUE = 0; // 0x0
+    field protected float[]! mCache;
+    field protected boolean mContinue;
+    field protected int mCount;
+    field protected androidx.constraintlayout.core.motion.utils.CurveFit! mCurveFit;
+    field protected float mLastCycle;
+    field protected long mLastTime;
+    field protected int[]! mTimePoints;
+    field protected String! mType;
+    field protected float[]![]! mValues;
+    field protected int mWaveShape;
+    field protected static float sVal2PI;
+  }
+
+  public static class TimeCycleSplineSet.CustomSet extends androidx.constraintlayout.core.motion.utils.TimeCycleSplineSet {
+    ctor public TimeCycleSplineSet.CustomSet(String!, androidx.constraintlayout.core.motion.utils.KeyFrameArray.CustomArray!);
+    method public void setPoint(int, androidx.constraintlayout.core.motion.CustomAttribute!, float, int, float);
+    method public boolean setProperty(androidx.constraintlayout.core.motion.MotionWidget!, float, long, androidx.constraintlayout.core.motion.utils.KeyCache!);
+  }
+
+  public static class TimeCycleSplineSet.CustomVarSet extends androidx.constraintlayout.core.motion.utils.TimeCycleSplineSet {
+    ctor public TimeCycleSplineSet.CustomVarSet(String!, androidx.constraintlayout.core.motion.utils.KeyFrameArray.CustomVar!);
+    method public void setPoint(int, androidx.constraintlayout.core.motion.CustomVariable!, float, int, float);
+    method public boolean setProperty(androidx.constraintlayout.core.motion.MotionWidget!, float, long, androidx.constraintlayout.core.motion.utils.KeyCache!);
+  }
+
+  protected static class TimeCycleSplineSet.Sort {
+    ctor protected TimeCycleSplineSet.Sort();
+  }
+
+  public class TypedBundle {
+    ctor public TypedBundle();
+    method public void add(int, boolean);
+    method public void add(int, float);
+    method public void add(int, int);
+    method public void add(int, String!);
+    method public void addIfNotNull(int, String!);
+    method public void applyDelta(androidx.constraintlayout.core.motion.utils.TypedBundle!);
+    method public void applyDelta(androidx.constraintlayout.core.motion.utils.TypedValues!);
+    method public void clear();
+    method public int getInteger(int);
+  }
+
+  public interface TypedValues {
+    method public int getId(String!);
+    method public boolean setValue(int, boolean);
+    method public boolean setValue(int, float);
+    method public boolean setValue(int, int);
+    method public boolean setValue(int, String!);
+    field public static final int BOOLEAN_MASK = 1; // 0x1
+    field public static final int FLOAT_MASK = 4; // 0x4
+    field public static final int INT_MASK = 2; // 0x2
+    field public static final int STRING_MASK = 8; // 0x8
+    field public static final String S_CUSTOM = "CUSTOM";
+    field public static final int TYPE_FRAME_POSITION = 100; // 0x64
+    field public static final int TYPE_TARGET = 101; // 0x65
+  }
+
+  public static interface TypedValues.AttributesType {
+    method public static int getId(String!);
+    method public static int getType(int);
+    field public static final String![]! KEY_WORDS;
+    field public static final String NAME = "KeyAttributes";
+    field public static final String S_ALPHA = "alpha";
+    field public static final String S_CURVE_FIT = "curveFit";
+    field public static final String S_CUSTOM = "CUSTOM";
+    field public static final String S_EASING = "easing";
+    field public static final String S_ELEVATION = "elevation";
+    field public static final String S_FRAME = "frame";
+    field public static final String S_PATH_ROTATE = "pathRotate";
+    field public static final String S_PIVOT_TARGET = "pivotTarget";
+    field public static final String S_PIVOT_X = "pivotX";
+    field public static final String S_PIVOT_Y = "pivotY";
+    field public static final String S_PROGRESS = "progress";
+    field public static final String S_ROTATION_X = "rotationX";
+    field public static final String S_ROTATION_Y = "rotationY";
+    field public static final String S_ROTATION_Z = "rotationZ";
+    field public static final String S_SCALE_X = "scaleX";
+    field public static final String S_SCALE_Y = "scaleY";
+    field public static final String S_TARGET = "target";
+    field public static final String S_TRANSLATION_X = "translationX";
+    field public static final String S_TRANSLATION_Y = "translationY";
+    field public static final String S_TRANSLATION_Z = "translationZ";
+    field public static final String S_VISIBILITY = "visibility";
+    field public static final int TYPE_ALPHA = 303; // 0x12f
+    field public static final int TYPE_CURVE_FIT = 301; // 0x12d
+    field public static final int TYPE_EASING = 317; // 0x13d
+    field public static final int TYPE_ELEVATION = 307; // 0x133
+    field public static final int TYPE_PATH_ROTATE = 316; // 0x13c
+    field public static final int TYPE_PIVOT_TARGET = 318; // 0x13e
+    field public static final int TYPE_PIVOT_X = 313; // 0x139
+    field public static final int TYPE_PIVOT_Y = 314; // 0x13a
+    field public static final int TYPE_PROGRESS = 315; // 0x13b
+    field public static final int TYPE_ROTATION_X = 308; // 0x134
+    field public static final int TYPE_ROTATION_Y = 309; // 0x135
+    field public static final int TYPE_ROTATION_Z = 310; // 0x136
+    field public static final int TYPE_SCALE_X = 311; // 0x137
+    field public static final int TYPE_SCALE_Y = 312; // 0x138
+    field public static final int TYPE_TRANSLATION_X = 304; // 0x130
+    field public static final int TYPE_TRANSLATION_Y = 305; // 0x131
+    field public static final int TYPE_TRANSLATION_Z = 306; // 0x132
+    field public static final int TYPE_VISIBILITY = 302; // 0x12e
+  }
+
+  public static interface TypedValues.Custom {
+    method public static int getId(String!);
+    field public static final String![]! KEY_WORDS;
+    field public static final String NAME = "Custom";
+    field public static final String S_BOOLEAN = "boolean";
+    field public static final String S_COLOR = "color";
+    field public static final String S_DIMENSION = "dimension";
+    field public static final String S_FLOAT = "float";
+    field public static final String S_INT = "integer";
+    field public static final String S_REFERENCE = "reference";
+    field public static final String S_STRING = "string";
+    field public static final int TYPE_BOOLEAN = 904; // 0x388
+    field public static final int TYPE_COLOR = 902; // 0x386
+    field public static final int TYPE_DIMENSION = 905; // 0x389
+    field public static final int TYPE_FLOAT = 901; // 0x385
+    field public static final int TYPE_INT = 900; // 0x384
+    field public static final int TYPE_REFERENCE = 906; // 0x38a
+    field public static final int TYPE_STRING = 903; // 0x387
+  }
+
+  public static interface TypedValues.CycleType {
+    method public static int getId(String!);
+    method public static int getType(int);
+    field public static final String![]! KEY_WORDS;
+    field public static final String NAME = "KeyCycle";
+    field public static final String S_ALPHA = "alpha";
+    field public static final String S_CURVE_FIT = "curveFit";
+    field public static final String S_CUSTOM_WAVE_SHAPE = "customWave";
+    field public static final String S_EASING = "easing";
+    field public static final String S_ELEVATION = "elevation";
+    field public static final String S_PATH_ROTATE = "pathRotate";
+    field public static final String S_PIVOT_X = "pivotX";
+    field public static final String S_PIVOT_Y = "pivotY";
+    field public static final String S_PROGRESS = "progress";
+    field public static final String S_ROTATION_X = "rotationX";
+    field public static final String S_ROTATION_Y = "rotationY";
+    field public static final String S_ROTATION_Z = "rotationZ";
+    field public static final String S_SCALE_X = "scaleX";
+    field public static final String S_SCALE_Y = "scaleY";
+    field public static final String S_TRANSLATION_X = "translationX";
+    field public static final String S_TRANSLATION_Y = "translationY";
+    field public static final String S_TRANSLATION_Z = "translationZ";
+    field public static final String S_VISIBILITY = "visibility";
+    field public static final String S_WAVE_OFFSET = "offset";
+    field public static final String S_WAVE_PERIOD = "period";
+    field public static final String S_WAVE_PHASE = "phase";
+    field public static final String S_WAVE_SHAPE = "waveShape";
+    field public static final int TYPE_ALPHA = 403; // 0x193
+    field public static final int TYPE_CURVE_FIT = 401; // 0x191
+    field public static final int TYPE_CUSTOM_WAVE_SHAPE = 422; // 0x1a6
+    field public static final int TYPE_EASING = 420; // 0x1a4
+    field public static final int TYPE_ELEVATION = 307; // 0x133
+    field public static final int TYPE_PATH_ROTATE = 416; // 0x1a0
+    field public static final int TYPE_PIVOT_X = 313; // 0x139
+    field public static final int TYPE_PIVOT_Y = 314; // 0x13a
+    field public static final int TYPE_PROGRESS = 315; // 0x13b
+    field public static final int TYPE_ROTATION_X = 308; // 0x134
+    field public static final int TYPE_ROTATION_Y = 309; // 0x135
+    field public static final int TYPE_ROTATION_Z = 310; // 0x136
+    field public static final int TYPE_SCALE_X = 311; // 0x137
+    field public static final int TYPE_SCALE_Y = 312; // 0x138
+    field public static final int TYPE_TRANSLATION_X = 304; // 0x130
+    field public static final int TYPE_TRANSLATION_Y = 305; // 0x131
+    field public static final int TYPE_TRANSLATION_Z = 306; // 0x132
+    field public static final int TYPE_VISIBILITY = 402; // 0x192
+    field public static final int TYPE_WAVE_OFFSET = 424; // 0x1a8
+    field public static final int TYPE_WAVE_PERIOD = 423; // 0x1a7
+    field public static final int TYPE_WAVE_PHASE = 425; // 0x1a9
+    field public static final int TYPE_WAVE_SHAPE = 421; // 0x1a5
+  }
+
+  public static interface TypedValues.MotionScene {
+    method public static int getId(String!);
+    method public static int getType(int);
+    field public static final String![]! KEY_WORDS;
+    field public static final String NAME = "MotionScene";
+    field public static final String S_DEFAULT_DURATION = "defaultDuration";
+    field public static final String S_LAYOUT_DURING_TRANSITION = "layoutDuringTransition";
+    field public static final int TYPE_DEFAULT_DURATION = 600; // 0x258
+    field public static final int TYPE_LAYOUT_DURING_TRANSITION = 601; // 0x259
+  }
+
+  public static interface TypedValues.MotionType {
+    method public static int getId(String!);
+    field public static final String![]! KEY_WORDS;
+    field public static final String NAME = "Motion";
+    field public static final String S_ANIMATE_CIRCLEANGLE_TO = "AnimateCircleAngleTo";
+    field public static final String S_ANIMATE_RELATIVE_TO = "AnimateRelativeTo";
+    field public static final String S_DRAW_PATH = "DrawPath";
+    field public static final String S_EASING = "TransitionEasing";
+    field public static final String S_PATHMOTION_ARC = "PathMotionArc";
+    field public static final String S_PATH_ROTATE = "PathRotate";
+    field public static final String S_POLAR_RELATIVETO = "PolarRelativeTo";
+    field public static final String S_QUANTIZE_INTERPOLATOR = "QuantizeInterpolator";
+    field public static final String S_QUANTIZE_INTERPOLATOR_ID = "QuantizeInterpolatorID";
+    field public static final String S_QUANTIZE_INTERPOLATOR_TYPE = "QuantizeInterpolatorType";
+    field public static final String S_QUANTIZE_MOTIONSTEPS = "QuantizeMotionSteps";
+    field public static final String S_QUANTIZE_MOTION_PHASE = "QuantizeMotionPhase";
+    field public static final String S_STAGGER = "Stagger";
+    field public static final int TYPE_ANIMATE_CIRCLEANGLE_TO = 606; // 0x25e
+    field public static final int TYPE_ANIMATE_RELATIVE_TO = 605; // 0x25d
+    field public static final int TYPE_DRAW_PATH = 608; // 0x260
+    field public static final int TYPE_EASING = 603; // 0x25b
+    field public static final int TYPE_PATHMOTION_ARC = 607; // 0x25f
+    field public static final int TYPE_PATH_ROTATE = 601; // 0x259
+    field public static final int TYPE_POLAR_RELATIVETO = 609; // 0x261
+    field public static final int TYPE_QUANTIZE_INTERPOLATOR = 604; // 0x25c
+    field public static final int TYPE_QUANTIZE_INTERPOLATOR_ID = 612; // 0x264
+    field public static final int TYPE_QUANTIZE_INTERPOLATOR_TYPE = 611; // 0x263
+    field public static final int TYPE_QUANTIZE_MOTIONSTEPS = 610; // 0x262
+    field public static final int TYPE_QUANTIZE_MOTION_PHASE = 602; // 0x25a
+    field public static final int TYPE_STAGGER = 600; // 0x258
+  }
+
+  public static interface TypedValues.OnSwipe {
+    field public static final String AUTOCOMPLETE_MODE = "autocompletemode";
+    field public static final String![]! AUTOCOMPLETE_MODE_ENUM;
+    field public static final String DRAG_DIRECTION = "dragdirection";
+    field public static final String DRAG_SCALE = "dragscale";
+    field public static final String DRAG_THRESHOLD = "dragthreshold";
+    field public static final String LIMIT_BOUNDS_TO = "limitboundsto";
+    field public static final String MAX_ACCELERATION = "maxacceleration";
+    field public static final String MAX_VELOCITY = "maxvelocity";
+    field public static final String MOVE_WHEN_SCROLLAT_TOP = "movewhenscrollattop";
+    field public static final String NESTED_SCROLL_FLAGS = "nestedscrollflags";
+    field public static final String![]! NESTED_SCROLL_FLAGS_ENUM;
+    field public static final String ON_TOUCH_UP = "ontouchup";
+    field public static final String![]! ON_TOUCH_UP_ENUM;
+    field public static final String ROTATION_CENTER_ID = "rotationcenterid";
+    field public static final String SPRINGS_TOP_THRESHOLD = "springstopthreshold";
+    field public static final String SPRING_BOUNDARY = "springboundary";
+    field public static final String![]! SPRING_BOUNDARY_ENUM;
+    field public static final String SPRING_DAMPING = "springdamping";
+    field public static final String SPRING_MASS = "springmass";
+    field public static final String SPRING_STIFFNESS = "springstiffness";
+    field public static final String TOUCH_ANCHOR_ID = "touchanchorid";
+    field public static final String TOUCH_ANCHOR_SIDE = "touchanchorside";
+    field public static final String TOUCH_REGION_ID = "touchregionid";
+  }
+
+  public static interface TypedValues.PositionType {
+    method public static int getId(String!);
+    method public static int getType(int);
+    field public static final String![]! KEY_WORDS;
+    field public static final String NAME = "KeyPosition";
+    field public static final String S_DRAWPATH = "drawPath";
+    field public static final String S_PERCENT_HEIGHT = "percentHeight";
+    field public static final String S_PERCENT_WIDTH = "percentWidth";
+    field public static final String S_PERCENT_X = "percentX";
+    field public static final String S_PERCENT_Y = "percentY";
+    field public static final String S_SIZE_PERCENT = "sizePercent";
+    field public static final String S_TRANSITION_EASING = "transitionEasing";
+    field public static final int TYPE_CURVE_FIT = 508; // 0x1fc
+    field public static final int TYPE_DRAWPATH = 502; // 0x1f6
+    field public static final int TYPE_PATH_MOTION_ARC = 509; // 0x1fd
+    field public static final int TYPE_PERCENT_HEIGHT = 504; // 0x1f8
+    field public static final int TYPE_PERCENT_WIDTH = 503; // 0x1f7
+    field public static final int TYPE_PERCENT_X = 506; // 0x1fa
+    field public static final int TYPE_PERCENT_Y = 507; // 0x1fb
+    field public static final int TYPE_POSITION_TYPE = 510; // 0x1fe
+    field public static final int TYPE_SIZE_PERCENT = 505; // 0x1f9
+    field public static final int TYPE_TRANSITION_EASING = 501; // 0x1f5
+  }
+
+  public static interface TypedValues.TransitionType {
+    method public static int getId(String!);
+    method public static int getType(int);
+    field public static final String![]! KEY_WORDS;
+    field public static final String NAME = "Transitions";
+    field public static final String S_AUTO_TRANSITION = "autoTransition";
+    field public static final String S_DURATION = "duration";
+    field public static final String S_FROM = "from";
+    field public static final String S_INTERPOLATOR = "motionInterpolator";
+    field public static final String S_PATH_MOTION_ARC = "pathMotionArc";
+    field public static final String S_STAGGERED = "staggered";
+    field public static final String S_TO = "to";
+    field public static final String S_TRANSITION_FLAGS = "transitionFlags";
+    field public static final int TYPE_AUTO_TRANSITION = 704; // 0x2c0
+    field public static final int TYPE_DURATION = 700; // 0x2bc
+    field public static final int TYPE_FROM = 701; // 0x2bd
+    field public static final int TYPE_INTERPOLATOR = 705; // 0x2c1
+    field public static final int TYPE_PATH_MOTION_ARC = 509; // 0x1fd
+    field public static final int TYPE_STAGGERED = 706; // 0x2c2
+    field public static final int TYPE_TO = 702; // 0x2be
+    field public static final int TYPE_TRANSITION_FLAGS = 707; // 0x2c3
+  }
+
+  public static interface TypedValues.TriggerType {
+    method public static int getId(String!);
+    field public static final String CROSS = "CROSS";
+    field public static final String![]! KEY_WORDS;
+    field public static final String NAME = "KeyTrigger";
+    field public static final String NEGATIVE_CROSS = "negativeCross";
+    field public static final String POSITIVE_CROSS = "positiveCross";
+    field public static final String POST_LAYOUT = "postLayout";
+    field public static final String TRIGGER_COLLISION_ID = "triggerCollisionId";
+    field public static final String TRIGGER_COLLISION_VIEW = "triggerCollisionView";
+    field public static final String TRIGGER_ID = "triggerID";
+    field public static final String TRIGGER_RECEIVER = "triggerReceiver";
+    field public static final String TRIGGER_SLACK = "triggerSlack";
+    field public static final int TYPE_CROSS = 312; // 0x138
+    field public static final int TYPE_NEGATIVE_CROSS = 310; // 0x136
+    field public static final int TYPE_POSITIVE_CROSS = 309; // 0x135
+    field public static final int TYPE_POST_LAYOUT = 304; // 0x130
+    field public static final int TYPE_TRIGGER_COLLISION_ID = 307; // 0x133
+    field public static final int TYPE_TRIGGER_COLLISION_VIEW = 306; // 0x132
+    field public static final int TYPE_TRIGGER_ID = 308; // 0x134
+    field public static final int TYPE_TRIGGER_RECEIVER = 311; // 0x137
+    field public static final int TYPE_TRIGGER_SLACK = 305; // 0x131
+    field public static final int TYPE_VIEW_TRANSITION_ON_CROSS = 301; // 0x12d
+    field public static final int TYPE_VIEW_TRANSITION_ON_NEGATIVE_CROSS = 303; // 0x12f
+    field public static final int TYPE_VIEW_TRANSITION_ON_POSITIVE_CROSS = 302; // 0x12e
+    field public static final String VIEW_TRANSITION_ON_CROSS = "viewTransitionOnCross";
+    field public static final String VIEW_TRANSITION_ON_NEGATIVE_CROSS = "viewTransitionOnNegativeCross";
+    field public static final String VIEW_TRANSITION_ON_POSITIVE_CROSS = "viewTransitionOnPositiveCross";
+  }
+
+  public class Utils {
+    ctor public Utils();
+    method public int getInterpolatedColor(float[]!);
+    method public static void log(String!);
+    method public static void log(String!, String!);
+    method public static void logStack(String!, int);
+    method public static void loge(String!, String!);
+    method public static int rgbaTocColor(float, float, float, float);
+    method public static void setDebugHandle(androidx.constraintlayout.core.motion.utils.Utils.DebugHandle!);
+    method public static void socketSend(String!);
+  }
+
+  public static interface Utils.DebugHandle {
+    method public void message(String!);
+  }
+
+  public class VelocityMatrix {
+    ctor public VelocityMatrix();
+    method public void applyTransform(float, float, int, int, float[]!);
+    method public void clear();
+    method public void setRotationVelocity(androidx.constraintlayout.core.motion.utils.KeyCycleOscillator!, float);
+    method public void setRotationVelocity(androidx.constraintlayout.core.motion.utils.SplineSet!, float);
+    method public void setScaleVelocity(androidx.constraintlayout.core.motion.utils.KeyCycleOscillator!, androidx.constraintlayout.core.motion.utils.KeyCycleOscillator!, float);
+    method public void setScaleVelocity(androidx.constraintlayout.core.motion.utils.SplineSet!, androidx.constraintlayout.core.motion.utils.SplineSet!, float);
+    method public void setTranslationVelocity(androidx.constraintlayout.core.motion.utils.KeyCycleOscillator!, androidx.constraintlayout.core.motion.utils.KeyCycleOscillator!, float);
+    method public void setTranslationVelocity(androidx.constraintlayout.core.motion.utils.SplineSet!, androidx.constraintlayout.core.motion.utils.SplineSet!, float);
+  }
+
+  public class ViewState {
+    ctor public ViewState();
+    method public void getState(androidx.constraintlayout.core.motion.MotionWidget!);
+    method public int height();
+    method public int width();
+    field public int bottom;
+    field public int left;
+    field public int right;
+    field public float rotation;
+    field public int top;
+  }
+
+}
+
+package androidx.constraintlayout.core.parser {
+
+  public class CLArray extends androidx.constraintlayout.core.parser.CLContainer {
+    ctor public CLArray(char[]!);
+    method public static androidx.constraintlayout.core.parser.CLElement! allocate(char[]!);
+  }
+
+  public class CLContainer extends androidx.constraintlayout.core.parser.CLElement {
+    ctor public CLContainer(char[]!);
+    method public void add(androidx.constraintlayout.core.parser.CLElement!);
+    method public static androidx.constraintlayout.core.parser.CLElement! allocate(char[]!);
+    method public void clear();
+    method public androidx.constraintlayout.core.parser.CLContainer clone();
+    method public androidx.constraintlayout.core.parser.CLElement! get(int) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public androidx.constraintlayout.core.parser.CLElement! get(String!) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public androidx.constraintlayout.core.parser.CLArray! getArray(int) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public androidx.constraintlayout.core.parser.CLArray! getArray(String!) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public androidx.constraintlayout.core.parser.CLArray! getArrayOrCreate(String!);
+    method public androidx.constraintlayout.core.parser.CLArray! getArrayOrNull(String!);
+    method public boolean getBoolean(int) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public boolean getBoolean(String!) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public float getFloat(int) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public float getFloat(String!) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public float getFloatOrNaN(String!);
+    method public int getInt(int) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public int getInt(String!) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public androidx.constraintlayout.core.parser.CLObject! getObject(int) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public androidx.constraintlayout.core.parser.CLObject! getObject(String!) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public androidx.constraintlayout.core.parser.CLObject! getObjectOrNull(String!);
+    method public androidx.constraintlayout.core.parser.CLElement! getOrNull(int);
+    method public androidx.constraintlayout.core.parser.CLElement! getOrNull(String!);
+    method public String! getString(int) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public String! getString(String!) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public String! getStringOrNull(int);
+    method public String! getStringOrNull(String!);
+    method public boolean has(String!);
+    method public java.util.ArrayList<java.lang.String!>! names();
+    method public void put(String!, androidx.constraintlayout.core.parser.CLElement!);
+    method public void putNumber(String!, float);
+    method public void putString(String!, String!);
+    method public void remove(String!);
+    method public int size();
+  }
+
+  public class CLElement implements java.lang.Cloneable {
+    ctor public CLElement(char[]!);
+    method protected void addIndent(StringBuilder!, int);
+    method public androidx.constraintlayout.core.parser.CLElement clone();
+    method public String! content();
+    method public androidx.constraintlayout.core.parser.CLElement! getContainer();
+    method protected String! getDebugName();
+    method public long getEnd();
+    method public float getFloat();
+    method public int getInt();
+    method public int getLine();
+    method public long getStart();
+    method protected String! getStrClass();
+    method public boolean hasContent();
+    method public boolean isDone();
+    method public boolean isStarted();
+    method public boolean notStarted();
+    method public void setContainer(androidx.constraintlayout.core.parser.CLContainer!);
+    method public void setEnd(long);
+    method public void setLine(int);
+    method public void setStart(long);
+    method protected String! toFormattedJSON(int, int);
+    method protected String! toJSON();
+    field protected androidx.constraintlayout.core.parser.CLContainer! mContainer;
+    field protected long mEnd;
+    field protected long mStart;
+    field protected static int sBaseIndent;
+    field protected static int sMaxLine;
+  }
+
+  public class CLKey extends androidx.constraintlayout.core.parser.CLContainer {
+    ctor public CLKey(char[]!);
+    method public static androidx.constraintlayout.core.parser.CLElement! allocate(char[]!);
+    method public static androidx.constraintlayout.core.parser.CLElement! allocate(String!, androidx.constraintlayout.core.parser.CLElement!);
+    method public String! getName();
+    method public androidx.constraintlayout.core.parser.CLElement! getValue();
+    method public void set(androidx.constraintlayout.core.parser.CLElement!);
+  }
+
+  public class CLNumber extends androidx.constraintlayout.core.parser.CLElement {
+    ctor public CLNumber(char[]!);
+    ctor public CLNumber(float);
+    method public static androidx.constraintlayout.core.parser.CLElement! allocate(char[]!);
+    method public boolean isInt();
+    method public void putValue(float);
+  }
+
+  public class CLObject extends androidx.constraintlayout.core.parser.CLContainer implements java.lang.Iterable<androidx.constraintlayout.core.parser.CLKey!> {
+    ctor public CLObject(char[]!);
+    method public static androidx.constraintlayout.core.parser.CLObject! allocate(char[]!);
+    method public androidx.constraintlayout.core.parser.CLObject clone();
+    method public java.util.Iterator<androidx.constraintlayout.core.parser.CLKey!>! iterator();
+    method public String! toFormattedJSON();
+    method public String! toFormattedJSON(int, int);
+    method public String! toJSON();
+  }
+
+  public class CLParser {
+    ctor public CLParser(String!);
+    method public androidx.constraintlayout.core.parser.CLObject! parse() throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public static androidx.constraintlayout.core.parser.CLObject! parse(String!) throws androidx.constraintlayout.core.parser.CLParsingException;
+  }
+
+  public class CLParsingException extends java.lang.Exception {
+    ctor public CLParsingException(String!, androidx.constraintlayout.core.parser.CLElement!);
+    method public String! reason();
+  }
+
+  public class CLString extends androidx.constraintlayout.core.parser.CLElement {
+    ctor public CLString(char[]!);
+    method public static androidx.constraintlayout.core.parser.CLElement! allocate(char[]!);
+    method public static androidx.constraintlayout.core.parser.CLString from(String);
+  }
+
+  public class CLToken extends androidx.constraintlayout.core.parser.CLElement {
+    ctor public CLToken(char[]!);
+    method public static androidx.constraintlayout.core.parser.CLElement! allocate(char[]!);
+    method public boolean getBoolean() throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public androidx.constraintlayout.core.parser.CLToken.Type! getType();
+    method public boolean isNull() throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public boolean validate(char, long);
+  }
+
+}
+
+package androidx.constraintlayout.core.state {
+
+  public class ConstraintReference implements androidx.constraintlayout.core.state.Reference {
+    ctor public ConstraintReference(androidx.constraintlayout.core.state.State!);
+    method public void addCustomColor(String!, int);
+    method public void addCustomFloat(String!, float);
+    method public androidx.constraintlayout.core.state.ConstraintReference! alpha(float);
+    method public void apply();
+    method public void applyWidgetConstraints();
+    method public androidx.constraintlayout.core.state.ConstraintReference! baseline();
+    method public androidx.constraintlayout.core.state.ConstraintReference! baselineToBaseline(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! baselineToBottom(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! baselineToTop(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! bias(float);
+    method public androidx.constraintlayout.core.state.ConstraintReference! bottom();
+    method public androidx.constraintlayout.core.state.ConstraintReference! bottomToBottom(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! bottomToTop(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! centerHorizontally(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! centerVertically(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! circularConstraint(Object!, float, float);
+    method public androidx.constraintlayout.core.state.ConstraintReference! clear();
+    method public androidx.constraintlayout.core.state.ConstraintReference! clearAll();
+    method public androidx.constraintlayout.core.state.ConstraintReference! clearHorizontal();
+    method public androidx.constraintlayout.core.state.ConstraintReference! clearVertical();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! createConstraintWidget();
+    method public androidx.constraintlayout.core.state.ConstraintReference! end();
+    method public androidx.constraintlayout.core.state.ConstraintReference! endToEnd(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! endToStart(Object!);
+    method public float getAlpha();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getConstraintWidget();
+    method public androidx.constraintlayout.core.state.helpers.Facade! getFacade();
+    method public androidx.constraintlayout.core.state.Dimension! getHeight();
+    method public int getHorizontalChainStyle();
+    method public float getHorizontalChainWeight();
+    method public Object! getKey();
+    method public float getPivotX();
+    method public float getPivotY();
+    method public float getRotationX();
+    method public float getRotationY();
+    method public float getRotationZ();
+    method public float getScaleX();
+    method public float getScaleY();
+    method public String! getTag();
+    method public float getTranslationX();
+    method public float getTranslationY();
+    method public float getTranslationZ();
+    method public int getVerticalChainStyle(int);
+    method public float getVerticalChainWeight();
+    method public Object! getView();
+    method public androidx.constraintlayout.core.state.Dimension! getWidth();
+    method public androidx.constraintlayout.core.state.ConstraintReference! height(androidx.constraintlayout.core.state.Dimension!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! horizontalBias(float);
+    method public androidx.constraintlayout.core.state.ConstraintReference! left();
+    method public androidx.constraintlayout.core.state.ConstraintReference! leftToLeft(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! leftToRight(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! margin(int);
+    method public androidx.constraintlayout.core.state.ConstraintReference! margin(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! marginGone(int);
+    method public androidx.constraintlayout.core.state.ConstraintReference! marginGone(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! pivotX(float);
+    method public androidx.constraintlayout.core.state.ConstraintReference! pivotY(float);
+    method public androidx.constraintlayout.core.state.ConstraintReference! right();
+    method public androidx.constraintlayout.core.state.ConstraintReference! rightToLeft(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! rightToRight(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! rotationX(float);
+    method public androidx.constraintlayout.core.state.ConstraintReference! rotationY(float);
+    method public androidx.constraintlayout.core.state.ConstraintReference! rotationZ(float);
+    method public androidx.constraintlayout.core.state.ConstraintReference! scaleX(float);
+    method public androidx.constraintlayout.core.state.ConstraintReference! scaleY(float);
+    method public void setConstraintWidget(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public void setFacade(androidx.constraintlayout.core.state.helpers.Facade!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! setHeight(androidx.constraintlayout.core.state.Dimension!);
+    method public void setHorizontalChainStyle(int);
+    method public void setHorizontalChainWeight(float);
+    method public void setKey(Object!);
+    method public void setTag(String!);
+    method public void setVerticalChainStyle(int);
+    method public void setVerticalChainWeight(float);
+    method public void setView(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! setWidth(androidx.constraintlayout.core.state.Dimension!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! start();
+    method public androidx.constraintlayout.core.state.ConstraintReference! startToEnd(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! startToStart(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! top();
+    method public androidx.constraintlayout.core.state.ConstraintReference! topToBottom(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! topToTop(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! translationX(float);
+    method public androidx.constraintlayout.core.state.ConstraintReference! translationY(float);
+    method public androidx.constraintlayout.core.state.ConstraintReference! translationZ(float);
+    method public void validate() throws java.lang.Exception;
+    method public androidx.constraintlayout.core.state.ConstraintReference! verticalBias(float);
+    method public androidx.constraintlayout.core.state.ConstraintReference! visibility(int);
+    method public androidx.constraintlayout.core.state.ConstraintReference! width(androidx.constraintlayout.core.state.Dimension!);
+    field protected Object! mBottomToBottom;
+    field protected Object! mBottomToTop;
+    field protected Object! mEndToEnd;
+    field protected Object! mEndToStart;
+    field protected float mHorizontalBias;
+    field protected Object! mLeftToLeft;
+    field protected Object! mLeftToRight;
+    field protected int mMarginBottom;
+    field protected int mMarginBottomGone;
+    field protected int mMarginEnd;
+    field protected int mMarginEndGone;
+    field protected int mMarginLeft;
+    field protected int mMarginLeftGone;
+    field protected int mMarginRight;
+    field protected int mMarginRightGone;
+    field protected int mMarginStart;
+    field protected int mMarginStartGone;
+    field protected int mMarginTop;
+    field protected int mMarginTopGone;
+    field protected Object! mRightToLeft;
+    field protected Object! mRightToRight;
+    field protected Object! mStartToEnd;
+    field protected Object! mStartToStart;
+    field protected Object! mTopToBottom;
+    field protected Object! mTopToTop;
+    field protected float mVerticalBias;
+  }
+
+  public static interface ConstraintReference.ConstraintReferenceFactory {
+    method public androidx.constraintlayout.core.state.ConstraintReference! create(androidx.constraintlayout.core.state.State!);
+  }
+
+  public class ConstraintSetParser {
+    ctor public ConstraintSetParser();
+    method public static void parseDesignElementsJSON(String!, java.util.ArrayList<androidx.constraintlayout.core.state.ConstraintSetParser.DesignElement!>!) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public static void parseJSON(String!, androidx.constraintlayout.core.state.State!, androidx.constraintlayout.core.state.ConstraintSetParser.LayoutVariables!) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public static void parseJSON(String!, androidx.constraintlayout.core.state.Transition!, int);
+    method public static void parseMotionSceneJSON(androidx.constraintlayout.core.state.CoreMotionScene!, String!);
+  }
+
+  public static class ConstraintSetParser.DesignElement {
+    method public String! getId();
+    method public java.util.HashMap<java.lang.String!,java.lang.String!>! getParams();
+    method public String! getType();
+  }
+
+  public static class ConstraintSetParser.LayoutVariables {
+    ctor public ConstraintSetParser.LayoutVariables();
+    method public void putOverride(String!, float);
+  }
+
+  public enum ConstraintSetParser.MotionLayoutDebugFlags {
+    enum_constant public static final androidx.constraintlayout.core.state.ConstraintSetParser.MotionLayoutDebugFlags NONE;
+    enum_constant public static final androidx.constraintlayout.core.state.ConstraintSetParser.MotionLayoutDebugFlags SHOW_ALL;
+    enum_constant public static final androidx.constraintlayout.core.state.ConstraintSetParser.MotionLayoutDebugFlags UNKNOWN;
+  }
+
+  public interface CoreMotionScene {
+    method public String! getConstraintSet(int);
+    method public String! getConstraintSet(String!);
+    method public String! getTransition(String!);
+    method public void setConstraintSetContent(String!, String!);
+    method public void setDebugName(String!);
+    method public void setTransitionContent(String!, String!);
+  }
+
+  public interface CorePixelDp {
+    method public float toPixels(float);
+  }
+
+  public class Dimension {
+    method public void apply(androidx.constraintlayout.core.state.State!, androidx.constraintlayout.core.widgets.ConstraintWidget!, int);
+    method public static androidx.constraintlayout.core.state.Dimension! createFixed(int);
+    method public static androidx.constraintlayout.core.state.Dimension! createFixed(Object!);
+    method public static androidx.constraintlayout.core.state.Dimension! createParent();
+    method public static androidx.constraintlayout.core.state.Dimension! createPercent(Object!, float);
+    method public static androidx.constraintlayout.core.state.Dimension! createRatio(String!);
+    method public static androidx.constraintlayout.core.state.Dimension! createSpread();
+    method public static androidx.constraintlayout.core.state.Dimension! createSuggested(int);
+    method public static androidx.constraintlayout.core.state.Dimension! createSuggested(Object!);
+    method public static androidx.constraintlayout.core.state.Dimension! createWrap();
+    method public boolean equalsFixedValue(int);
+    method public androidx.constraintlayout.core.state.Dimension! fixed(int);
+    method public androidx.constraintlayout.core.state.Dimension! fixed(Object!);
+    method public androidx.constraintlayout.core.state.Dimension! max(int);
+    method public androidx.constraintlayout.core.state.Dimension! max(Object!);
+    method public androidx.constraintlayout.core.state.Dimension! min(int);
+    method public androidx.constraintlayout.core.state.Dimension! min(Object!);
+    method public androidx.constraintlayout.core.state.Dimension! percent(Object!, float);
+    method public androidx.constraintlayout.core.state.Dimension! ratio(String!);
+    method public androidx.constraintlayout.core.state.Dimension! suggested(int);
+    method public androidx.constraintlayout.core.state.Dimension! suggested(Object!);
+    field public static final Object! FIXED_DIMENSION;
+    field public static final Object! PARENT_DIMENSION;
+    field public static final Object! PERCENT_DIMENSION;
+    field public static final Object! RATIO_DIMENSION;
+    field public static final Object! SPREAD_DIMENSION;
+    field public static final Object! WRAP_DIMENSION;
+  }
+
+  public enum Dimension.Type {
+    enum_constant public static final androidx.constraintlayout.core.state.Dimension.Type FIXED;
+    enum_constant public static final androidx.constraintlayout.core.state.Dimension.Type MATCH_CONSTRAINT;
+    enum_constant public static final androidx.constraintlayout.core.state.Dimension.Type MATCH_PARENT;
+    enum_constant public static final androidx.constraintlayout.core.state.Dimension.Type WRAP;
+  }
+
+  public class HelperReference extends androidx.constraintlayout.core.state.ConstraintReference implements androidx.constraintlayout.core.state.helpers.Facade {
+    ctor public HelperReference(androidx.constraintlayout.core.state.State!, androidx.constraintlayout.core.state.State.Helper!);
+    method public androidx.constraintlayout.core.state.HelperReference! add(java.lang.Object!...!);
+    method public void applyBase();
+    method public androidx.constraintlayout.core.widgets.HelperWidget! getHelperWidget();
+    method public androidx.constraintlayout.core.state.State.Helper! getType();
+    method public void setHelperWidget(androidx.constraintlayout.core.widgets.HelperWidget!);
+    field protected final androidx.constraintlayout.core.state.State! mHelperState;
+    field protected java.util.ArrayList<java.lang.Object!>! mReferences;
+  }
+
+  public interface Interpolator {
+    method public float getInterpolation(float);
+  }
+
+  public interface Reference {
+    method public void apply();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getConstraintWidget();
+    method public androidx.constraintlayout.core.state.helpers.Facade! getFacade();
+    method public Object! getKey();
+    method public void setConstraintWidget(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public void setKey(Object!);
+  }
+
+  public class Registry {
+    ctor public Registry();
+    method public String! currentContent(String!);
+    method public String! currentLayoutInformation(String!);
+    method public static androidx.constraintlayout.core.state.Registry! getInstance();
+    method public long getLastModified(String!);
+    method public java.util.Set<java.lang.String!>! getLayoutList();
+    method public void register(String!, androidx.constraintlayout.core.state.RegistryCallback!);
+    method public void setDrawDebug(String!, int);
+    method public void setLayoutInformationMode(String!, int);
+    method public void unregister(String!, androidx.constraintlayout.core.state.RegistryCallback!);
+    method public void updateContent(String!, String!);
+    method public void updateDimensions(String!, int, int);
+    method public void updateProgress(String!, float);
+  }
+
+  public interface RegistryCallback {
+    method public String! currentLayoutInformation();
+    method public String! currentMotionScene();
+    method public long getLastModified();
+    method public void onDimensions(int, int);
+    method public void onNewMotionScene(String!);
+    method public void onProgress(float);
+    method public void setDrawDebug(int);
+    method public void setLayoutInformationMode(int);
+  }
+
+  public class State {
+    ctor public State();
+    method public void apply(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!);
+    method public androidx.constraintlayout.core.state.helpers.BarrierReference! barrier(Object!, androidx.constraintlayout.core.state.State.Direction!);
+    method public void baselineNeededFor(Object!);
+    method public androidx.constraintlayout.core.state.helpers.AlignHorizontallyReference! centerHorizontally(java.lang.Object!...!);
+    method public androidx.constraintlayout.core.state.helpers.AlignVerticallyReference! centerVertically(java.lang.Object!...!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! constraints(Object!);
+    method public int convertDimension(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! createConstraintReference(Object!);
+    method public void directMapping();
+    method public androidx.constraintlayout.core.state.helpers.FlowReference! getFlow(Object!, boolean);
+    method public androidx.constraintlayout.core.state.helpers.GridReference getGrid(Object, String);
+    method public androidx.constraintlayout.core.state.helpers.FlowReference! getHorizontalFlow();
+    method public androidx.constraintlayout.core.state.helpers.FlowReference! getHorizontalFlow(java.lang.Object!...!);
+    method public java.util.ArrayList<java.lang.String!>! getIdsForTag(String!);
+    method public androidx.constraintlayout.core.state.helpers.FlowReference! getVerticalFlow();
+    method public androidx.constraintlayout.core.state.helpers.FlowReference! getVerticalFlow(java.lang.Object!...!);
+    method public androidx.constraintlayout.core.state.helpers.GuidelineReference! guideline(Object!, int);
+    method public androidx.constraintlayout.core.state.State! height(androidx.constraintlayout.core.state.Dimension!);
+    method public androidx.constraintlayout.core.state.HelperReference! helper(Object!, androidx.constraintlayout.core.state.State.Helper!);
+    method public androidx.constraintlayout.core.state.helpers.HorizontalChainReference! horizontalChain();
+    method public androidx.constraintlayout.core.state.helpers.HorizontalChainReference! horizontalChain(java.lang.Object!...!);
+    method public androidx.constraintlayout.core.state.helpers.GuidelineReference! horizontalGuideline(Object!);
+    method public boolean isBaselineNeeded(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method @Deprecated public boolean isLtr();
+    method public boolean isRtl();
+    method public void map(Object!, Object!);
+    method public void reset();
+    method public boolean sameFixedHeight(int);
+    method public boolean sameFixedWidth(int);
+    method public void setDpToPixel(androidx.constraintlayout.core.state.CorePixelDp!);
+    method public androidx.constraintlayout.core.state.State! setHeight(androidx.constraintlayout.core.state.Dimension!);
+    method @Deprecated public void setLtr(boolean);
+    method public void setRtl(boolean);
+    method public void setTag(String!, String!);
+    method public androidx.constraintlayout.core.state.State! setWidth(androidx.constraintlayout.core.state.Dimension!);
+    method public androidx.constraintlayout.core.state.helpers.VerticalChainReference! verticalChain();
+    method public androidx.constraintlayout.core.state.helpers.VerticalChainReference! verticalChain(java.lang.Object!...!);
+    method public androidx.constraintlayout.core.state.helpers.GuidelineReference! verticalGuideline(Object!);
+    method public androidx.constraintlayout.core.state.State! width(androidx.constraintlayout.core.state.Dimension!);
+    field public static final Integer PARENT;
+    field protected java.util.HashMap<java.lang.Object!,androidx.constraintlayout.core.state.HelperReference!>! mHelperReferences;
+    field public final androidx.constraintlayout.core.state.ConstraintReference! mParent;
+    field protected java.util.HashMap<java.lang.Object!,androidx.constraintlayout.core.state.Reference!>! mReferences;
+  }
+
+  public enum State.Chain {
+    method public static androidx.constraintlayout.core.state.State.Chain! getChainByString(String!);
+    method public static int getValueByString(String!);
+    enum_constant public static final androidx.constraintlayout.core.state.State.Chain PACKED;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Chain SPREAD;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Chain SPREAD_INSIDE;
+    field public static java.util.Map<java.lang.String!,androidx.constraintlayout.core.state.State.Chain!>! chainMap;
+    field public static java.util.Map<java.lang.String!,java.lang.Integer!>! valueMap;
+  }
+
+  public enum State.Constraint {
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint BASELINE_TO_BASELINE;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint BASELINE_TO_BOTTOM;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint BASELINE_TO_TOP;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint BOTTOM_TO_BASELINE;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint BOTTOM_TO_BOTTOM;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint BOTTOM_TO_TOP;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint CENTER_HORIZONTALLY;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint CENTER_VERTICALLY;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint CIRCULAR_CONSTRAINT;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint END_TO_END;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint END_TO_START;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint LEFT_TO_LEFT;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint LEFT_TO_RIGHT;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint RIGHT_TO_LEFT;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint RIGHT_TO_RIGHT;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint START_TO_END;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint START_TO_START;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint TOP_TO_BASELINE;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint TOP_TO_BOTTOM;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint TOP_TO_TOP;
+  }
+
+  public enum State.Direction {
+    enum_constant public static final androidx.constraintlayout.core.state.State.Direction BOTTOM;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Direction END;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Direction LEFT;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Direction RIGHT;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Direction START;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Direction TOP;
+  }
+
+  public enum State.Helper {
+    enum_constant public static final androidx.constraintlayout.core.state.State.Helper ALIGN_HORIZONTALLY;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Helper ALIGN_VERTICALLY;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Helper BARRIER;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Helper COLUMN;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Helper FLOW;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Helper GRID;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Helper HORIZONTAL_CHAIN;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Helper HORIZONTAL_FLOW;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Helper LAYER;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Helper ROW;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Helper VERTICAL_CHAIN;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Helper VERTICAL_FLOW;
+  }
+
+  public enum State.Wrap {
+    method public static androidx.constraintlayout.core.state.State.Wrap! getChainByString(String!);
+    method public static int getValueByString(String!);
+    enum_constant public static final androidx.constraintlayout.core.state.State.Wrap ALIGNED;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Wrap CHAIN;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Wrap NONE;
+    field public static java.util.Map<java.lang.String!,java.lang.Integer!>! valueMap;
+    field public static java.util.Map<java.lang.String!,androidx.constraintlayout.core.state.State.Wrap!>! wrapMap;
+  }
+
+  public class Transition implements androidx.constraintlayout.core.motion.utils.TypedValues {
+    ctor public Transition(androidx.constraintlayout.core.state.CorePixelDp);
+    method public void addCustomColor(int, String!, String!, int);
+    method public void addCustomFloat(int, String!, String!, float);
+    method public void addKeyAttribute(String!, androidx.constraintlayout.core.motion.utils.TypedBundle!);
+    method public void addKeyAttribute(String!, androidx.constraintlayout.core.motion.utils.TypedBundle!, androidx.constraintlayout.core.motion.CustomVariable![]!);
+    method public void addKeyCycle(String!, androidx.constraintlayout.core.motion.utils.TypedBundle!);
+    method public void addKeyPosition(String!, androidx.constraintlayout.core.motion.utils.TypedBundle!);
+    method public void addKeyPosition(String!, int, int, float, float);
+    method public void calcStagger();
+    method public void clear();
+    method public boolean contains(String!);
+    method public float dragToProgress(float, int, int, float, float);
+    method public void fillKeyPositions(androidx.constraintlayout.core.state.WidgetFrame!, float[]!, float[]!, float[]!);
+    method public androidx.constraintlayout.core.state.Transition.KeyPosition! findNextPosition(String!, int);
+    method public androidx.constraintlayout.core.state.Transition.KeyPosition! findPreviousPosition(String!, int);
+    method public int getAutoTransition();
+    method public androidx.constraintlayout.core.state.WidgetFrame! getEnd(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public androidx.constraintlayout.core.state.WidgetFrame! getEnd(String!);
+    method public int getId(String!);
+    method public androidx.constraintlayout.core.state.WidgetFrame! getInterpolated(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public androidx.constraintlayout.core.state.WidgetFrame! getInterpolated(String!);
+    method public int getInterpolatedHeight();
+    method public int getInterpolatedWidth();
+    method public androidx.constraintlayout.core.state.Interpolator! getInterpolator();
+    method public static androidx.constraintlayout.core.state.Interpolator! getInterpolator(int, String!);
+    method public int getKeyFrames(String!, float[]!, int[]!, int[]!);
+    method public androidx.constraintlayout.core.motion.Motion! getMotion(String!);
+    method public int getNumberKeyPositions(androidx.constraintlayout.core.state.WidgetFrame!);
+    method public float[]! getPath(String!);
+    method public androidx.constraintlayout.core.state.WidgetFrame! getStart(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public androidx.constraintlayout.core.state.WidgetFrame! getStart(String!);
+    method public float getTouchUpProgress(long);
+    method public androidx.constraintlayout.core.state.Transition.WidgetState! getWidgetState(String!, androidx.constraintlayout.core.widgets.ConstraintWidget!, int);
+    method public boolean hasOnSwipe();
+    method public boolean hasPositionKeyframes();
+    method public void interpolate(int, int, float);
+    method public boolean isEmpty();
+    method public boolean isTouchNotDone(float);
+    method public void setTouchUp(float, long, float, float);
+    method public void setTransitionProperties(androidx.constraintlayout.core.motion.utils.TypedBundle!);
+    method public boolean setValue(int, boolean);
+    method public boolean setValue(int, float);
+    method public boolean setValue(int, int);
+    method public boolean setValue(int, String!);
+    method public void updateFrom(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!, int);
+    field public static final int END = 1; // 0x1
+    field public static final int INTERPOLATED = 2; // 0x2
+    field public static final int START = 0; // 0x0
+  }
+
+  public static class Transition.WidgetState {
+    ctor public Transition.WidgetState();
+    method public androidx.constraintlayout.core.state.WidgetFrame! getFrame(int);
+    method public void interpolate(int, int, float, androidx.constraintlayout.core.state.Transition!);
+    method public void setKeyAttribute(androidx.constraintlayout.core.motion.utils.TypedBundle!);
+    method public void setKeyAttribute(androidx.constraintlayout.core.motion.utils.TypedBundle!, androidx.constraintlayout.core.motion.CustomVariable![]!);
+    method public void setKeyCycle(androidx.constraintlayout.core.motion.utils.TypedBundle!);
+    method public void setKeyPosition(androidx.constraintlayout.core.motion.utils.TypedBundle!);
+    method public void setPathRelative(androidx.constraintlayout.core.state.Transition.WidgetState!);
+    method public void update(androidx.constraintlayout.core.widgets.ConstraintWidget!, int);
+  }
+
+  public class TransitionParser {
+    ctor public TransitionParser();
+    method @Deprecated public static void parse(androidx.constraintlayout.core.parser.CLObject!, androidx.constraintlayout.core.state.Transition!, androidx.constraintlayout.core.state.CorePixelDp!) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public static void parseKeyFrames(androidx.constraintlayout.core.parser.CLObject!, androidx.constraintlayout.core.state.Transition!) throws androidx.constraintlayout.core.parser.CLParsingException;
+  }
+
+  public class WidgetFrame {
+    ctor public WidgetFrame();
+    ctor public WidgetFrame(androidx.constraintlayout.core.state.WidgetFrame!);
+    ctor public WidgetFrame(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public void addCustomColor(String!, int);
+    method public void addCustomFloat(String!, float);
+    method public float centerX();
+    method public float centerY();
+    method public boolean containsCustom(String);
+    method public androidx.constraintlayout.core.motion.CustomVariable! getCustomAttribute(String!);
+    method public java.util.Set<java.lang.String!>! getCustomAttributeNames();
+    method public int getCustomColor(String!);
+    method public float getCustomFloat(String!);
+    method public String! getId();
+    method public androidx.constraintlayout.core.motion.utils.TypedBundle! getMotionProperties();
+    method public int height();
+    method public static void interpolate(int, int, androidx.constraintlayout.core.state.WidgetFrame!, androidx.constraintlayout.core.state.WidgetFrame!, androidx.constraintlayout.core.state.WidgetFrame!, androidx.constraintlayout.core.state.Transition!, float);
+    method public boolean isDefaultTransform();
+    method public StringBuilder! serialize(StringBuilder!);
+    method public StringBuilder! serialize(StringBuilder!, boolean);
+    method public void setCustomAttribute(String!, int, boolean);
+    method public void setCustomAttribute(String!, int, float);
+    method public void setCustomAttribute(String!, int, int);
+    method public void setCustomAttribute(String!, int, String!);
+    method public void setCustomValue(androidx.constraintlayout.core.motion.CustomAttribute!, float[]!);
+    method public boolean setValue(String!, androidx.constraintlayout.core.parser.CLElement!) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public androidx.constraintlayout.core.state.WidgetFrame! update();
+    method public androidx.constraintlayout.core.state.WidgetFrame! update(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public void updateAttributes(androidx.constraintlayout.core.state.WidgetFrame!);
+    method public int width();
+    field public float alpha;
+    field public int bottom;
+    field public float interpolatedPos;
+    field public int left;
+    field public String! name;
+    field public static float phone_orientation;
+    field public float pivotX;
+    field public float pivotY;
+    field public int right;
+    field public float rotationX;
+    field public float rotationY;
+    field public float rotationZ;
+    field public float scaleX;
+    field public float scaleY;
+    field public int top;
+    field public float translationX;
+    field public float translationY;
+    field public float translationZ;
+    field public int visibility;
+    field public androidx.constraintlayout.core.widgets.ConstraintWidget! widget;
+  }
+
+}
+
+package androidx.constraintlayout.core.state.helpers {
+
+  public class AlignHorizontallyReference extends androidx.constraintlayout.core.state.HelperReference {
+    ctor public AlignHorizontallyReference(androidx.constraintlayout.core.state.State!);
+  }
+
+  public class AlignVerticallyReference extends androidx.constraintlayout.core.state.HelperReference {
+    ctor public AlignVerticallyReference(androidx.constraintlayout.core.state.State!);
+  }
+
+  public class BarrierReference extends androidx.constraintlayout.core.state.HelperReference {
+    ctor public BarrierReference(androidx.constraintlayout.core.state.State!);
+    method public void setBarrierDirection(androidx.constraintlayout.core.state.State.Direction!);
+  }
+
+  public class ChainReference extends androidx.constraintlayout.core.state.HelperReference {
+    ctor public ChainReference(androidx.constraintlayout.core.state.State, androidx.constraintlayout.core.state.State.Helper);
+    method public void addChainElement(String, float, float, float);
+    method public androidx.constraintlayout.core.state.helpers.ChainReference bias(float);
+    method public float getBias();
+    method protected float getPostMargin(String);
+    method protected float getPreMargin(String);
+    method public androidx.constraintlayout.core.state.State.Chain getStyle();
+    method protected float getWeight(String);
+    method public androidx.constraintlayout.core.state.helpers.ChainReference style(androidx.constraintlayout.core.state.State.Chain);
+    field protected float mBias;
+    field @Deprecated protected java.util.HashMap<java.lang.String!,java.lang.Float!> mMapPostMargin;
+    field @Deprecated protected java.util.HashMap<java.lang.String!,java.lang.Float!> mMapPreMargin;
+    field @Deprecated protected java.util.HashMap<java.lang.String!,java.lang.Float!> mMapWeights;
+    field protected androidx.constraintlayout.core.state.State.Chain mStyle;
+  }
+
+  public interface Facade {
+    method public void apply();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getConstraintWidget();
+  }
+
+  public class FlowReference extends androidx.constraintlayout.core.state.HelperReference {
+    ctor public FlowReference(androidx.constraintlayout.core.state.State!, androidx.constraintlayout.core.state.State.Helper!);
+    method public void addFlowElement(String!, float, float, float);
+    method public float getFirstHorizontalBias();
+    method public int getFirstHorizontalStyle();
+    method public float getFirstVerticalBias();
+    method public int getFirstVerticalStyle();
+    method public int getHorizontalAlign();
+    method public float getHorizontalBias();
+    method public int getHorizontalGap();
+    method public int getHorizontalStyle();
+    method public float getLastHorizontalBias();
+    method public int getLastHorizontalStyle();
+    method public float getLastVerticalBias();
+    method public int getLastVerticalStyle();
+    method public int getMaxElementsWrap();
+    method public int getOrientation();
+    method public int getPaddingBottom();
+    method public int getPaddingLeft();
+    method public int getPaddingRight();
+    method public int getPaddingTop();
+    method protected float getPostMargin(String!);
+    method protected float getPreMargin(String!);
+    method public int getVerticalAlign();
+    method public float getVerticalBias();
+    method public int getVerticalGap();
+    method public int getVerticalStyle();
+    method protected float getWeight(String!);
+    method public int getWrapMode();
+    method public void setFirstHorizontalBias(float);
+    method public void setFirstHorizontalStyle(int);
+    method public void setFirstVerticalBias(float);
+    method public void setFirstVerticalStyle(int);
+    method public void setHorizontalAlign(int);
+    method public void setHorizontalGap(int);
+    method public void setHorizontalStyle(int);
+    method public void setLastHorizontalBias(float);
+    method public void setLastHorizontalStyle(int);
+    method public void setLastVerticalBias(float);
+    method public void setLastVerticalStyle(int);
+    method public void setMaxElementsWrap(int);
+    method public void setOrientation(int);
+    method public void setPaddingBottom(int);
+    method public void setPaddingLeft(int);
+    method public void setPaddingRight(int);
+    method public void setPaddingTop(int);
+    method public void setVerticalAlign(int);
+    method public void setVerticalGap(int);
+    method public void setVerticalStyle(int);
+    method public void setWrapMode(int);
+    field protected float mFirstHorizontalBias;
+    field protected int mFirstHorizontalStyle;
+    field protected float mFirstVerticalBias;
+    field protected int mFirstVerticalStyle;
+    field protected androidx.constraintlayout.core.widgets.Flow! mFlow;
+    field protected int mHorizontalAlign;
+    field protected int mHorizontalGap;
+    field protected int mHorizontalStyle;
+    field protected float mLastHorizontalBias;
+    field protected int mLastHorizontalStyle;
+    field protected float mLastVerticalBias;
+    field protected int mLastVerticalStyle;
+    field protected java.util.HashMap<java.lang.String!,java.lang.Float!>! mMapPostMargin;
+    field protected java.util.HashMap<java.lang.String!,java.lang.Float!>! mMapPreMargin;
+    field protected java.util.HashMap<java.lang.String!,java.lang.Float!>! mMapWeights;
+    field protected int mMaxElementsWrap;
+    field protected int mOrientation;
+    field protected int mPaddingBottom;
+    field protected int mPaddingLeft;
+    field protected int mPaddingRight;
+    field protected int mPaddingTop;
+    field protected int mVerticalAlign;
+    field protected int mVerticalGap;
+    field protected int mVerticalStyle;
+    field protected int mWrapMode;
+  }
+
+  public class GridReference extends androidx.constraintlayout.core.state.HelperReference {
+    ctor public GridReference(androidx.constraintlayout.core.state.State, androidx.constraintlayout.core.state.State.Helper);
+    method public String? getColumnWeights();
+    method public int getColumnsSet();
+    method public int getFlags();
+    method public float getHorizontalGaps();
+    method public int getOrientation();
+    method public int getPaddingBottom();
+    method public int getPaddingEnd();
+    method public int getPaddingStart();
+    method public int getPaddingTop();
+    method public String? getRowWeights();
+    method public int getRowsSet();
+    method public String? getSkips();
+    method public String? getSpans();
+    method public float getVerticalGaps();
+    method public void setColumnWeights(String);
+    method public void setColumnsSet(int);
+    method public void setFlags(int);
+    method public void setFlags(String);
+    method public void setHorizontalGaps(float);
+    method public void setOrientation(int);
+    method public void setPaddingBottom(int);
+    method public void setPaddingEnd(int);
+    method public void setPaddingStart(int);
+    method public void setPaddingTop(int);
+    method public void setRowWeights(String);
+    method public void setRowsSet(int);
+    method public void setSkips(String);
+    method public void setSpans(String);
+    method public void setVerticalGaps(float);
+  }
+
+  public class GuidelineReference implements androidx.constraintlayout.core.state.helpers.Facade androidx.constraintlayout.core.state.Reference {
+    ctor public GuidelineReference(androidx.constraintlayout.core.state.State!);
+    method public void apply();
+    method public androidx.constraintlayout.core.state.helpers.GuidelineReference! end(Object!);
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getConstraintWidget();
+    method public androidx.constraintlayout.core.state.helpers.Facade! getFacade();
+    method public Object! getKey();
+    method public int getOrientation();
+    method public androidx.constraintlayout.core.state.helpers.GuidelineReference! percent(float);
+    method public void setConstraintWidget(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public void setKey(Object!);
+    method public void setOrientation(int);
+    method public androidx.constraintlayout.core.state.helpers.GuidelineReference! start(Object!);
+  }
+
+  public class HorizontalChainReference extends androidx.constraintlayout.core.state.helpers.ChainReference {
+    ctor public HorizontalChainReference(androidx.constraintlayout.core.state.State!);
+  }
+
+  public class VerticalChainReference extends androidx.constraintlayout.core.state.helpers.ChainReference {
+    ctor public VerticalChainReference(androidx.constraintlayout.core.state.State!);
+  }
+
+}
+
+package androidx.constraintlayout.core.utils {
+
+  public class GridCore extends androidx.constraintlayout.core.widgets.VirtualLayout {
+    ctor public GridCore();
+    ctor public GridCore(int, int);
+    method public String? getColumnWeights();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidgetContainer? getContainer();
+    method public int getFlags();
+    method public float getHorizontalGaps();
+    method public int getOrientation();
+    method public String? getRowWeights();
+    method public float getVerticalGaps();
+    method public void setColumnWeights(String);
+    method public void setColumns(int);
+    method public void setContainer(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer);
+    method public void setFlags(int);
+    method public void setHorizontalGaps(float);
+    method public void setOrientation(int);
+    method public void setRowWeights(String);
+    method public void setRows(int);
+    method public void setSkips(String);
+    method public void setSpans(CharSequence);
+    method public void setVerticalGaps(float);
+    field public static final int HORIZONTAL = 0; // 0x0
+    field public static final int SPANS_RESPECT_WIDGET_ORDER = 2; // 0x2
+    field public static final int SUB_GRID_BY_COL_ROW = 1; // 0x1
+    field public static final int VERTICAL = 1; // 0x1
+  }
+
+  public class GridEngine {
+    ctor public GridEngine();
+    ctor public GridEngine(int, int);
+    ctor public GridEngine(int, int, int);
+    method public int bottomOfWidget(int);
+    method public int leftOfWidget(int);
+    method public int rightOfWidget(int);
+    method public void setColumns(int);
+    method public void setNumWidgets(int);
+    method public void setOrientation(int);
+    method public void setRows(int);
+    method public void setSkips(String!);
+    method public void setSpans(CharSequence!);
+    method public void setup();
+    method public int topOfWidget(int);
+    field public static final int HORIZONTAL = 0; // 0x0
+    field public static final int VERTICAL = 1; // 0x1
+  }
+
+}
+
+package androidx.constraintlayout.core.widgets {
+
+  public class Barrier extends androidx.constraintlayout.core.widgets.HelperWidget {
+    ctor public Barrier();
+    ctor public Barrier(String!);
+    method public boolean allSolved();
+    method @Deprecated public boolean allowsGoneWidget();
+    method public boolean getAllowsGoneWidget();
+    method public int getBarrierType();
+    method public int getMargin();
+    method public int getOrientation();
+    method protected void markWidgets();
+    method public void setAllowsGoneWidget(boolean);
+    method public void setBarrierType(int);
+    method public void setMargin(int);
+    field public static final int BOTTOM = 3; // 0x3
+    field public static final int LEFT = 0; // 0x0
+    field public static final int RIGHT = 1; // 0x1
+    field public static final int TOP = 2; // 0x2
+  }
+
+  public class Chain {
+    ctor public Chain();
+    method public static void applyChainConstraints(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!, androidx.constraintlayout.core.LinearSystem!, java.util.ArrayList<androidx.constraintlayout.core.widgets.ConstraintWidget!>!, int);
+    field public static final boolean USE_CHAIN_OPTIMIZATION = false;
+  }
+
+  public class ChainHead {
+    ctor public ChainHead(androidx.constraintlayout.core.widgets.ConstraintWidget!, int, boolean);
+    method public void define();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getFirst();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getFirstMatchConstraintWidget();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getFirstVisibleWidget();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getHead();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getLast();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getLastMatchConstraintWidget();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getLastVisibleWidget();
+    method public float getTotalWeight();
+    field protected androidx.constraintlayout.core.widgets.ConstraintWidget! mFirst;
+    field protected androidx.constraintlayout.core.widgets.ConstraintWidget! mFirstMatchConstraintWidget;
+    field protected androidx.constraintlayout.core.widgets.ConstraintWidget! mFirstVisibleWidget;
+    field protected boolean mHasComplexMatchWeights;
+    field protected boolean mHasDefinedWeights;
+    field protected boolean mHasRatio;
+    field protected boolean mHasUndefinedWeights;
+    field protected androidx.constraintlayout.core.widgets.ConstraintWidget! mHead;
+    field protected androidx.constraintlayout.core.widgets.ConstraintWidget! mLast;
+    field protected androidx.constraintlayout.core.widgets.ConstraintWidget! mLastMatchConstraintWidget;
+    field protected androidx.constraintlayout.core.widgets.ConstraintWidget! mLastVisibleWidget;
+    field protected float mTotalWeight;
+    field protected java.util.ArrayList<androidx.constraintlayout.core.widgets.ConstraintWidget!>! mWeightedMatchConstraintsWidgets;
+    field protected int mWidgetsCount;
+    field protected int mWidgetsMatchCount;
+  }
+
+  public class ConstraintAnchor {
+    ctor public ConstraintAnchor(androidx.constraintlayout.core.widgets.ConstraintWidget!, androidx.constraintlayout.core.widgets.ConstraintAnchor.Type!);
+    method public boolean connect(androidx.constraintlayout.core.widgets.ConstraintAnchor!, int);
+    method public boolean connect(androidx.constraintlayout.core.widgets.ConstraintAnchor!, int, int, boolean);
+    method public void copyFrom(androidx.constraintlayout.core.widgets.ConstraintAnchor!, java.util.HashMap<androidx.constraintlayout.core.widgets.ConstraintWidget!,androidx.constraintlayout.core.widgets.ConstraintWidget!>!);
+    method public void findDependents(int, java.util.ArrayList<androidx.constraintlayout.core.widgets.analyzer.WidgetGroup!>!, androidx.constraintlayout.core.widgets.analyzer.WidgetGroup!);
+    method public java.util.HashSet<androidx.constraintlayout.core.widgets.ConstraintAnchor!>! getDependents();
+    method public int getFinalValue();
+    method public int getMargin();
+    method public final androidx.constraintlayout.core.widgets.ConstraintAnchor! getOpposite();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getOwner();
+    method public androidx.constraintlayout.core.SolverVariable! getSolverVariable();
+    method public androidx.constraintlayout.core.widgets.ConstraintAnchor! getTarget();
+    method public androidx.constraintlayout.core.widgets.ConstraintAnchor.Type! getType();
+    method public boolean hasCenteredDependents();
+    method public boolean hasDependents();
+    method public boolean hasFinalValue();
+    method public boolean isConnected();
+    method public boolean isConnectionAllowed(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public boolean isConnectionAllowed(androidx.constraintlayout.core.widgets.ConstraintWidget!, androidx.constraintlayout.core.widgets.ConstraintAnchor!);
+    method public boolean isSideAnchor();
+    method public boolean isSimilarDimensionConnection(androidx.constraintlayout.core.widgets.ConstraintAnchor!);
+    method public boolean isValidConnection(androidx.constraintlayout.core.widgets.ConstraintAnchor!);
+    method public boolean isVerticalAnchor();
+    method public void reset();
+    method public void resetFinalResolution();
+    method public void resetSolverVariable(androidx.constraintlayout.core.Cache!);
+    method public void setFinalValue(int);
+    method public void setGoneMargin(int);
+    method public void setMargin(int);
+    field public int mMargin;
+    field public final androidx.constraintlayout.core.widgets.ConstraintWidget! mOwner;
+    field public androidx.constraintlayout.core.widgets.ConstraintAnchor! mTarget;
+    field public final androidx.constraintlayout.core.widgets.ConstraintAnchor.Type! mType;
+  }
+
+  public enum ConstraintAnchor.Type {
+    enum_constant public static final androidx.constraintlayout.core.widgets.ConstraintAnchor.Type BASELINE;
+    enum_constant public static final androidx.constraintlayout.core.widgets.ConstraintAnchor.Type BOTTOM;
+    enum_constant public static final androidx.constraintlayout.core.widgets.ConstraintAnchor.Type CENTER;
+    enum_constant public static final androidx.constraintlayout.core.widgets.ConstraintAnchor.Type CENTER_X;
+    enum_constant public static final androidx.constraintlayout.core.widgets.ConstraintAnchor.Type CENTER_Y;
+    enum_constant public static final androidx.constraintlayout.core.widgets.ConstraintAnchor.Type LEFT;
+    enum_constant public static final androidx.constraintlayout.core.widgets.ConstraintAnchor.Type NONE;
+    enum_constant public static final androidx.constraintlayout.core.widgets.ConstraintAnchor.Type RIGHT;
+    enum_constant public static final androidx.constraintlayout.core.widgets.ConstraintAnchor.Type TOP;
+  }
+
+  public class ConstraintWidget {
+    ctor public ConstraintWidget();
+    ctor public ConstraintWidget(int, int);
+    ctor public ConstraintWidget(int, int, int, int);
+    ctor public ConstraintWidget(String!);
+    ctor public ConstraintWidget(String!, int, int);
+    ctor public ConstraintWidget(String!, int, int, int, int);
+    method public void addChildrenToSolverByDependency(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!, androidx.constraintlayout.core.LinearSystem!, java.util.HashSet<androidx.constraintlayout.core.widgets.ConstraintWidget!>!, int, boolean);
+    method public void addToSolver(androidx.constraintlayout.core.LinearSystem!, boolean);
+    method public boolean allowedInBarrier();
+    method public void connect(androidx.constraintlayout.core.widgets.ConstraintAnchor!, androidx.constraintlayout.core.widgets.ConstraintAnchor!, int);
+    method public void connect(androidx.constraintlayout.core.widgets.ConstraintAnchor.Type!, androidx.constraintlayout.core.widgets.ConstraintWidget!, androidx.constraintlayout.core.widgets.ConstraintAnchor.Type!);
+    method public void connect(androidx.constraintlayout.core.widgets.ConstraintAnchor.Type!, androidx.constraintlayout.core.widgets.ConstraintWidget!, androidx.constraintlayout.core.widgets.ConstraintAnchor.Type!, int);
+    method public void connectCircularConstraint(androidx.constraintlayout.core.widgets.ConstraintWidget!, float, int);
+    method public void copy(androidx.constraintlayout.core.widgets.ConstraintWidget!, java.util.HashMap<androidx.constraintlayout.core.widgets.ConstraintWidget!,androidx.constraintlayout.core.widgets.ConstraintWidget!>!);
+    method public void createObjectVariables(androidx.constraintlayout.core.LinearSystem!);
+    method public void ensureMeasureRequested();
+    method public void ensureWidgetRuns();
+    method public androidx.constraintlayout.core.widgets.ConstraintAnchor! getAnchor(androidx.constraintlayout.core.widgets.ConstraintAnchor.Type!);
+    method public java.util.ArrayList<androidx.constraintlayout.core.widgets.ConstraintAnchor!>! getAnchors();
+    method public int getBaselineDistance();
+    method public float getBiasPercent(int);
+    method public int getBottom();
+    method public Object! getCompanionWidget();
+    method public int getContainerItemSkip();
+    method public String! getDebugName();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour! getDimensionBehaviour(int);
+    method public float getDimensionRatio();
+    method public int getDimensionRatioSide();
+    method public boolean getHasBaseline();
+    method public int getHeight();
+    method public float getHorizontalBiasPercent();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getHorizontalChainControlWidget();
+    method public int getHorizontalChainStyle();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour! getHorizontalDimensionBehaviour();
+    method public int getHorizontalMargin();
+    method public int getLastHorizontalMeasureSpec();
+    method public int getLastVerticalMeasureSpec();
+    method public int getLeft();
+    method public int getLength(int);
+    method public int getMaxHeight();
+    method public int getMaxWidth();
+    method public int getMinHeight();
+    method public int getMinWidth();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getNextChainMember(int);
+    method public int getOptimizerWrapHeight();
+    method public int getOptimizerWrapWidth();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getParent();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getPreviousChainMember(int);
+    method public int getRight();
+    method protected int getRootX();
+    method protected int getRootY();
+    method public androidx.constraintlayout.core.widgets.analyzer.WidgetRun! getRun(int);
+    method public void getSceneString(StringBuilder!);
+    method public int getTop();
+    method public String! getType();
+    method public float getVerticalBiasPercent();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getVerticalChainControlWidget();
+    method public int getVerticalChainStyle();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour! getVerticalDimensionBehaviour();
+    method public int getVerticalMargin();
+    method public int getVisibility();
+    method public int getWidth();
+    method public int getWrapBehaviorInParent();
+    method public int getX();
+    method public int getY();
+    method public boolean hasBaseline();
+    method public boolean hasDanglingDimension(int);
+    method public boolean hasDependencies();
+    method public boolean hasDimensionOverride();
+    method public boolean hasResolvedTargets(int, int);
+    method public void immediateConnect(androidx.constraintlayout.core.widgets.ConstraintAnchor.Type!, androidx.constraintlayout.core.widgets.ConstraintWidget!, androidx.constraintlayout.core.widgets.ConstraintAnchor.Type!, int, int);
+    method public boolean isAnimated();
+    method public boolean isHeightWrapContent();
+    method public boolean isHorizontalSolvingPassDone();
+    method public boolean isInBarrier(int);
+    method public boolean isInHorizontalChain();
+    method public boolean isInPlaceholder();
+    method public boolean isInVerticalChain();
+    method public boolean isInVirtualLayout();
+    method public boolean isMeasureRequested();
+    method public boolean isResolvedHorizontally();
+    method public boolean isResolvedVertically();
+    method public boolean isRoot();
+    method public boolean isSpreadHeight();
+    method public boolean isSpreadWidth();
+    method public boolean isVerticalSolvingPassDone();
+    method public boolean isWidthWrapContent();
+    method public void markHorizontalSolvingPassDone();
+    method public void markVerticalSolvingPassDone();
+    method public boolean oppositeDimensionDependsOn(int);
+    method public boolean oppositeDimensionsTied();
+    method public void reset();
+    method public void resetAllConstraints();
+    method public void resetAnchor(androidx.constraintlayout.core.widgets.ConstraintAnchor!);
+    method public void resetAnchors();
+    method public void resetFinalResolution();
+    method public void resetSolverVariables(androidx.constraintlayout.core.Cache!);
+    method public void resetSolvingPassFlag();
+    method public StringBuilder! serialize(StringBuilder!);
+    method public void setAnimated(boolean);
+    method public void setBaselineDistance(int);
+    method public void setCompanionWidget(Object!);
+    method public void setContainerItemSkip(int);
+    method public void setDebugName(String!);
+    method public void setDebugSolverName(androidx.constraintlayout.core.LinearSystem!, String!);
+    method public void setDimension(int, int);
+    method public void setDimensionRatio(float, int);
+    method public void setDimensionRatio(String!);
+    method public void setFinalBaseline(int);
+    method public void setFinalFrame(int, int, int, int, int, int);
+    method public void setFinalHorizontal(int, int);
+    method public void setFinalLeft(int);
+    method public void setFinalTop(int);
+    method public void setFinalVertical(int, int);
+    method public void setFrame(int, int, int);
+    method public void setFrame(int, int, int, int);
+    method public void setGoneMargin(androidx.constraintlayout.core.widgets.ConstraintAnchor.Type!, int);
+    method public void setHasBaseline(boolean);
+    method public void setHeight(int);
+    method public void setHeightWrapContent(boolean);
+    method public void setHorizontalBiasPercent(float);
+    method public void setHorizontalChainStyle(int);
+    method public void setHorizontalDimension(int, int);
+    method public void setHorizontalDimensionBehaviour(androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour!);
+    method public void setHorizontalMatchStyle(int, int, int, float);
+    method public void setHorizontalWeight(float);
+    method protected void setInBarrier(int, boolean);
+    method public void setInPlaceholder(boolean);
+    method public void setInVirtualLayout(boolean);
+    method public void setLastMeasureSpec(int, int);
+    method public void setLength(int, int);
+    method public void setMaxHeight(int);
+    method public void setMaxWidth(int);
+    method public void setMeasureRequested(boolean);
+    method public void setMinHeight(int);
+    method public void setMinWidth(int);
+    method public void setOffset(int, int);
+    method public void setOrigin(int, int);
+    method public void setParent(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public void setType(String!);
+    method public void setVerticalBiasPercent(float);
+    method public void setVerticalChainStyle(int);
+    method public void setVerticalDimension(int, int);
+    method public void setVerticalDimensionBehaviour(androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour!);
+    method public void setVerticalMatchStyle(int, int, int, float);
+    method public void setVerticalWeight(float);
+    method public void setVisibility(int);
+    method public void setWidth(int);
+    method public void setWidthWrapContent(boolean);
+    method public void setWrapBehaviorInParent(int);
+    method public void setX(int);
+    method public void setY(int);
+    method public void setupDimensionRatio(boolean, boolean, boolean, boolean);
+    method public void updateFromRuns(boolean, boolean);
+    method public void updateFromSolver(androidx.constraintlayout.core.LinearSystem!, boolean);
+    field public static final int ANCHOR_BASELINE = 4; // 0x4
+    field public static final int ANCHOR_BOTTOM = 3; // 0x3
+    field public static final int ANCHOR_LEFT = 0; // 0x0
+    field public static final int ANCHOR_RIGHT = 1; // 0x1
+    field public static final int ANCHOR_TOP = 2; // 0x2
+    field public static final int BOTH = 2; // 0x2
+    field public static final int CHAIN_PACKED = 2; // 0x2
+    field public static final int CHAIN_SPREAD = 0; // 0x0
+    field public static final int CHAIN_SPREAD_INSIDE = 1; // 0x1
+    field public static float DEFAULT_BIAS;
+    field protected static final int DIRECT = 2; // 0x2
+    field public static final int GONE = 8; // 0x8
+    field public static final int HORIZONTAL = 0; // 0x0
+    field public static final int INVISIBLE = 4; // 0x4
+    field public static final int MATCH_CONSTRAINT_PERCENT = 2; // 0x2
+    field public static final int MATCH_CONSTRAINT_RATIO = 3; // 0x3
+    field public static final int MATCH_CONSTRAINT_RATIO_RESOLVED = 4; // 0x4
+    field public static final int MATCH_CONSTRAINT_SPREAD = 0; // 0x0
+    field public static final int MATCH_CONSTRAINT_WRAP = 1; // 0x1
+    field protected static final int SOLVER = 1; // 0x1
+    field public static final int UNKNOWN = -1; // 0xffffffff
+    field public static final int VERTICAL = 1; // 0x1
+    field public static final int VISIBLE = 0; // 0x0
+    field public static final int WRAP_BEHAVIOR_HORIZONTAL_ONLY = 1; // 0x1
+    field public static final int WRAP_BEHAVIOR_INCLUDED = 0; // 0x0
+    field public static final int WRAP_BEHAVIOR_SKIPPED = 3; // 0x3
+    field public static final int WRAP_BEHAVIOR_VERTICAL_ONLY = 2; // 0x2
+    field public androidx.constraintlayout.core.state.WidgetFrame! frame;
+    field public androidx.constraintlayout.core.widgets.analyzer.ChainRun! horizontalChainRun;
+    field public int horizontalGroup;
+    field public boolean[]! isTerminalWidget;
+    field protected java.util.ArrayList<androidx.constraintlayout.core.widgets.ConstraintAnchor!>! mAnchors;
+    field public androidx.constraintlayout.core.widgets.ConstraintAnchor! mBaseline;
+    field public androidx.constraintlayout.core.widgets.ConstraintAnchor! mBottom;
+    field public androidx.constraintlayout.core.widgets.ConstraintAnchor! mCenter;
+    field public float mCircleConstraintAngle;
+    field public float mDimensionRatio;
+    field protected int mDimensionRatioSide;
+    field public int mHorizontalResolution;
+    field public androidx.constraintlayout.core.widgets.analyzer.HorizontalWidgetRun! mHorizontalRun;
+    field public boolean mIsHeightWrapContent;
+    field public boolean mIsWidthWrapContent;
+    field public androidx.constraintlayout.core.widgets.ConstraintAnchor! mLeft;
+    field public androidx.constraintlayout.core.widgets.ConstraintAnchor![]! mListAnchors;
+    field public androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour![]! mListDimensionBehaviors;
+    field protected androidx.constraintlayout.core.widgets.ConstraintWidget![]! mListNextMatchConstraintsWidget;
+    field public int mMatchConstraintDefaultHeight;
+    field public int mMatchConstraintDefaultWidth;
+    field public int mMatchConstraintMaxHeight;
+    field public int mMatchConstraintMaxWidth;
+    field public int mMatchConstraintMinHeight;
+    field public int mMatchConstraintMinWidth;
+    field public float mMatchConstraintPercentHeight;
+    field public float mMatchConstraintPercentWidth;
+    field protected int mMinHeight;
+    field protected int mMinWidth;
+    field protected androidx.constraintlayout.core.widgets.ConstraintWidget![]! mNextChainWidget;
+    field protected int mOffsetX;
+    field protected int mOffsetY;
+    field public androidx.constraintlayout.core.widgets.ConstraintWidget! mParent;
+    field public int[]! mResolvedMatchConstraintDefault;
+    field public androidx.constraintlayout.core.widgets.ConstraintAnchor! mRight;
+    field public androidx.constraintlayout.core.widgets.ConstraintAnchor! mTop;
+    field public int mVerticalResolution;
+    field public androidx.constraintlayout.core.widgets.analyzer.VerticalWidgetRun! mVerticalRun;
+    field public float[]! mWeight;
+    field protected int mX;
+    field protected int mY;
+    field public boolean measured;
+    field public androidx.constraintlayout.core.widgets.analyzer.WidgetRun![]! run;
+    field public String! stringId;
+    field public androidx.constraintlayout.core.widgets.analyzer.ChainRun! verticalChainRun;
+    field public int verticalGroup;
+  }
+
+  public enum ConstraintWidget.DimensionBehaviour {
+    enum_constant public static final androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour FIXED;
+    enum_constant public static final androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour MATCH_CONSTRAINT;
+    enum_constant public static final androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour MATCH_PARENT;
+    enum_constant public static final androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour WRAP_CONTENT;
+  }
+
+  public class ConstraintWidgetContainer extends androidx.constraintlayout.core.widgets.WidgetContainer {
+    ctor public ConstraintWidgetContainer();
+    ctor public ConstraintWidgetContainer(int, int);
+    ctor public ConstraintWidgetContainer(int, int, int, int);
+    ctor public ConstraintWidgetContainer(String!, int, int);
+    method public boolean addChildrenToSolver(androidx.constraintlayout.core.LinearSystem!);
+    method public void addHorizontalWrapMaxVariable(androidx.constraintlayout.core.widgets.ConstraintAnchor!);
+    method public void addHorizontalWrapMinVariable(androidx.constraintlayout.core.widgets.ConstraintAnchor!);
+    method public void defineTerminalWidgets();
+    method public boolean directMeasure(boolean);
+    method public boolean directMeasureSetup(boolean);
+    method public boolean directMeasureWithOrientation(boolean, int);
+    method public void fillMetrics(androidx.constraintlayout.core.Metrics!);
+    method public java.util.ArrayList<androidx.constraintlayout.core.widgets.Guideline!>! getHorizontalGuidelines();
+    method public androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.Measurer! getMeasurer();
+    method public int getOptimizationLevel();
+    method public androidx.constraintlayout.core.LinearSystem! getSystem();
+    method public java.util.ArrayList<androidx.constraintlayout.core.widgets.Guideline!>! getVerticalGuidelines();
+    method public boolean handlesInternalConstraints();
+    method public void invalidateGraph();
+    method public void invalidateMeasures();
+    method public boolean isHeightMeasuredTooSmall();
+    method public boolean isRtl();
+    method public boolean isWidthMeasuredTooSmall();
+    method public static boolean measure(int, androidx.constraintlayout.core.widgets.ConstraintWidget!, androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.Measurer!, androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.Measure!, int);
+    method public long measure(int, int, int, int, int, int, int, int, int);
+    method public boolean optimizeFor(int);
+    method public void setMeasurer(androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.Measurer!);
+    method public void setOptimizationLevel(int);
+    method public void setPadding(int, int, int, int);
+    method public void setPass(int);
+    method public void setRtl(boolean);
+    method public boolean updateChildrenFromSolver(androidx.constraintlayout.core.LinearSystem!, boolean[]!);
+    method public void updateHierarchy();
+    field public androidx.constraintlayout.core.widgets.analyzer.DependencyGraph! mDependencyGraph;
+    field public boolean mGroupsWrapOptimized;
+    field public int mHorizontalChainsSize;
+    field public boolean mHorizontalWrapOptimized;
+    field public androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.Measure! mMeasure;
+    field protected androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.Measurer! mMeasurer;
+    field public androidx.constraintlayout.core.Metrics! mMetrics;
+    field public boolean mSkipSolver;
+    field protected androidx.constraintlayout.core.LinearSystem! mSystem;
+    field public int mVerticalChainsSize;
+    field public boolean mVerticalWrapOptimized;
+    field public int mWrapFixedHeight;
+    field public int mWrapFixedWidth;
+  }
+
+  public class Flow extends androidx.constraintlayout.core.widgets.VirtualLayout {
+    ctor public Flow();
+    method public float getMaxElementsWrap();
+    method public void setFirstHorizontalBias(float);
+    method public void setFirstHorizontalStyle(int);
+    method public void setFirstVerticalBias(float);
+    method public void setFirstVerticalStyle(int);
+    method public void setHorizontalAlign(int);
+    method public void setHorizontalBias(float);
+    method public void setHorizontalGap(int);
+    method public void setHorizontalStyle(int);
+    method public void setLastHorizontalBias(float);
+    method public void setLastHorizontalStyle(int);
+    method public void setLastVerticalBias(float);
+    method public void setLastVerticalStyle(int);
+    method public void setMaxElementsWrap(int);
+    method public void setOrientation(int);
+    method public void setVerticalAlign(int);
+    method public void setVerticalBias(float);
+    method public void setVerticalGap(int);
+    method public void setVerticalStyle(int);
+    method public void setWrapMode(int);
+    field public static final int HORIZONTAL_ALIGN_CENTER = 2; // 0x2
+    field public static final int HORIZONTAL_ALIGN_END = 1; // 0x1
+    field public static final int HORIZONTAL_ALIGN_START = 0; // 0x0
+    field public static final int VERTICAL_ALIGN_BASELINE = 3; // 0x3
+    field public static final int VERTICAL_ALIGN_BOTTOM = 1; // 0x1
+    field public static final int VERTICAL_ALIGN_CENTER = 2; // 0x2
+    field public static final int VERTICAL_ALIGN_TOP = 0; // 0x0
+    field public static final int WRAP_ALIGNED = 2; // 0x2
+    field public static final int WRAP_CHAIN = 1; // 0x1
+    field public static final int WRAP_CHAIN_NEW = 3; // 0x3
+    field public static final int WRAP_NONE = 0; // 0x0
+  }
+
+  public class Guideline extends androidx.constraintlayout.core.widgets.ConstraintWidget {
+    ctor public Guideline();
+    method public void cyclePosition();
+    method public androidx.constraintlayout.core.widgets.ConstraintAnchor! getAnchor();
+    method public int getMinimumPosition();
+    method public int getOrientation();
+    method public int getRelativeBegin();
+    method public int getRelativeBehaviour();
+    method public int getRelativeEnd();
+    method public float getRelativePercent();
+    method public boolean isPercent();
+    method public void setFinalValue(int);
+    method public void setGuideBegin(int);
+    method public void setGuideEnd(int);
+    method public void setGuidePercent(float);
+    method public void setGuidePercent(int);
+    method public void setMinimumPosition(int);
+    method public void setOrientation(int);
+    field public static final int HORIZONTAL = 0; // 0x0
+    field public static final int RELATIVE_BEGIN = 1; // 0x1
+    field public static final int RELATIVE_END = 2; // 0x2
+    field public static final int RELATIVE_PERCENT = 0; // 0x0
+    field public static final int RELATIVE_UNKNOWN = -1; // 0xffffffff
+    field public static final int VERTICAL = 1; // 0x1
+    field protected boolean mGuidelineUseRtl;
+    field protected int mRelativeBegin;
+    field protected int mRelativeEnd;
+    field protected float mRelativePercent;
+  }
+
+  public interface Helper {
+    method public void add(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public void removeAllIds();
+    method public void updateConstraints(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!);
+  }
+
+  public class HelperWidget extends androidx.constraintlayout.core.widgets.ConstraintWidget implements androidx.constraintlayout.core.widgets.Helper {
+    ctor public HelperWidget();
+    method public void add(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public void addDependents(java.util.ArrayList<androidx.constraintlayout.core.widgets.analyzer.WidgetGroup!>!, int, androidx.constraintlayout.core.widgets.analyzer.WidgetGroup!);
+    method public int findGroupInDependents(int);
+    method public void removeAllIds();
+    method public void updateConstraints(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!);
+    field public androidx.constraintlayout.core.widgets.ConstraintWidget![]! mWidgets;
+    field public int mWidgetsCount;
+  }
+
+  public class Optimizer {
+    ctor public Optimizer();
+    method public static final boolean enabled(int, int);
+    field public static final int OPTIMIZATION_BARRIER = 2; // 0x2
+    field public static final int OPTIMIZATION_CACHE_MEASURES = 256; // 0x100
+    field public static final int OPTIMIZATION_CHAIN = 4; // 0x4
+    field public static final int OPTIMIZATION_DEPENDENCY_ORDERING = 512; // 0x200
+    field public static final int OPTIMIZATION_DIMENSIONS = 8; // 0x8
+    field public static final int OPTIMIZATION_DIRECT = 1; // 0x1
+    field public static final int OPTIMIZATION_GRAPH = 64; // 0x40
+    field public static final int OPTIMIZATION_GRAPH_WRAP = 128; // 0x80
+    field public static final int OPTIMIZATION_GROUPING = 1024; // 0x400
+    field public static final int OPTIMIZATION_GROUPS = 32; // 0x20
+    field public static final int OPTIMIZATION_NONE = 0; // 0x0
+    field public static final int OPTIMIZATION_RATIO = 16; // 0x10
+    field public static final int OPTIMIZATION_STANDARD = 257; // 0x101
+  }
+
+  public class Placeholder extends androidx.constraintlayout.core.widgets.VirtualLayout {
+    ctor public Placeholder();
+  }
+
+  public class Rectangle {
+    ctor public Rectangle();
+    method public boolean contains(int, int);
+    method public int getCenterX();
+    method public int getCenterY();
+    method public void setBounds(int, int, int, int);
+    field public int height;
+    field public int width;
+    field public int x;
+    field public int y;
+  }
+
+  public class VirtualLayout extends androidx.constraintlayout.core.widgets.HelperWidget {
+    ctor public VirtualLayout();
+    method public void applyRtl(boolean);
+    method public void captureWidgets();
+    method public boolean contains(java.util.HashSet<androidx.constraintlayout.core.widgets.ConstraintWidget!>!);
+    method public int getMeasuredHeight();
+    method public int getMeasuredWidth();
+    method public int getPaddingBottom();
+    method public int getPaddingLeft();
+    method public int getPaddingRight();
+    method public int getPaddingTop();
+    method protected void measure(androidx.constraintlayout.core.widgets.ConstraintWidget!, androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour!, int, androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour!, int);
+    method public void measure(int, int, int, int);
+    method protected boolean measureChildren();
+    method public boolean needSolverPass();
+    method protected void needsCallbackFromSolver(boolean);
+    method public void setMeasure(int, int);
+    method public void setPadding(int);
+    method public void setPaddingBottom(int);
+    method public void setPaddingEnd(int);
+    method public void setPaddingLeft(int);
+    method public void setPaddingRight(int);
+    method public void setPaddingStart(int);
+    method public void setPaddingTop(int);
+    field protected androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.Measure! mMeasure;
+  }
+
+  public class WidgetContainer extends androidx.constraintlayout.core.widgets.ConstraintWidget {
+    ctor public WidgetContainer();
+    ctor public WidgetContainer(int, int);
+    ctor public WidgetContainer(int, int, int, int);
+    method public void add(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public void add(androidx.constraintlayout.core.widgets.ConstraintWidget!...!);
+    method public java.util.ArrayList<androidx.constraintlayout.core.widgets.ConstraintWidget!>! getChildren();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidgetContainer! getRootConstraintContainer();
+    method public void layout();
+    method public void remove(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public void removeAllChildren();
+    field public java.util.ArrayList<androidx.constraintlayout.core.widgets.ConstraintWidget!>! mChildren;
+  }
+
+}
+
+package androidx.constraintlayout.core.widgets.analyzer {
+
+  public class BasicMeasure {
+    ctor public BasicMeasure(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!);
+    method public long solverMeasure(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!, int, int, int, int, int, int, int, int, int);
+    method public void updateHierarchy(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!);
+    field public static final int AT_MOST = -2147483648; // 0x80000000
+    field public static final int EXACTLY = 1073741824; // 0x40000000
+    field public static final int FIXED = -3; // 0xfffffffd
+    field public static final int MATCH_PARENT = -1; // 0xffffffff
+    field public static final int UNSPECIFIED = 0; // 0x0
+    field public static final int WRAP_CONTENT = -2; // 0xfffffffe
+  }
+
+  public static class BasicMeasure.Measure {
+    ctor public BasicMeasure.Measure();
+    field public static int SELF_DIMENSIONS;
+    field public static int TRY_GIVEN_DIMENSIONS;
+    field public static int USE_GIVEN_DIMENSIONS;
+    field public androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour! horizontalBehavior;
+    field public int horizontalDimension;
+    field public int measureStrategy;
+    field public int measuredBaseline;
+    field public boolean measuredHasBaseline;
+    field public int measuredHeight;
+    field public boolean measuredNeedsSolverPass;
+    field public int measuredWidth;
+    field public androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour! verticalBehavior;
+    field public int verticalDimension;
+  }
+
+  public static interface BasicMeasure.Measurer {
+    method public void didMeasures();
+    method public void measure(androidx.constraintlayout.core.widgets.ConstraintWidget!, androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.Measure!);
+  }
+
+  public class ChainRun extends androidx.constraintlayout.core.widgets.analyzer.WidgetRun {
+    ctor public ChainRun(androidx.constraintlayout.core.widgets.ConstraintWidget!, int);
+    method public void applyToWidget();
+  }
+
+  public interface Dependency {
+    method public void update(androidx.constraintlayout.core.widgets.analyzer.Dependency!);
+  }
+
+  public class DependencyGraph {
+    ctor public DependencyGraph(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!);
+    method public void buildGraph();
+    method public void buildGraph(java.util.ArrayList<androidx.constraintlayout.core.widgets.analyzer.WidgetRun!>!);
+    method public void defineTerminalWidgets(androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour!, androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour!);
+    method public boolean directMeasure(boolean);
+    method public boolean directMeasureSetup(boolean);
+    method public boolean directMeasureWithOrientation(boolean, int);
+    method public void invalidateGraph();
+    method public void invalidateMeasures();
+    method public void measureWidgets();
+    method public void setMeasurer(androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.Measurer!);
+  }
+
+  public class DependencyNode implements androidx.constraintlayout.core.widgets.analyzer.Dependency {
+    ctor public DependencyNode(androidx.constraintlayout.core.widgets.analyzer.WidgetRun!);
+    method public void addDependency(androidx.constraintlayout.core.widgets.analyzer.Dependency!);
+    method public void clear();
+    method public String! name();
+    method public void resolve(int);
+    method public void update(androidx.constraintlayout.core.widgets.analyzer.Dependency!);
+    field public boolean delegateToWidgetRun;
+    field public boolean readyToSolve;
+    field public boolean resolved;
+    field public androidx.constraintlayout.core.widgets.analyzer.Dependency! updateDelegate;
+    field public int value;
+  }
+
+  public class Direct {
+    ctor public Direct();
+    method public static String! ls(int);
+    method public static boolean solveChain(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!, androidx.constraintlayout.core.LinearSystem!, int, int, androidx.constraintlayout.core.widgets.ChainHead!, boolean, boolean, boolean);
+    method public static void solvingPass(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!, androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.Measurer!);
+  }
+
+  public class Grouping {
+    ctor public Grouping();
+    method public static androidx.constraintlayout.core.widgets.analyzer.WidgetGroup! findDependents(androidx.constraintlayout.core.widgets.ConstraintWidget!, int, java.util.ArrayList<androidx.constraintlayout.core.widgets.analyzer.WidgetGroup!>!, androidx.constraintlayout.core.widgets.analyzer.WidgetGroup!);
+    method public static boolean simpleSolvingPass(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!, androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.Measurer!);
+    method public static boolean validInGroup(androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour!, androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour!, androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour!, androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour!);
+  }
+
+  public class HorizontalWidgetRun extends androidx.constraintlayout.core.widgets.analyzer.WidgetRun {
+    ctor public HorizontalWidgetRun(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public void applyToWidget();
+  }
+
+  public class VerticalWidgetRun extends androidx.constraintlayout.core.widgets.analyzer.WidgetRun {
+    ctor public VerticalWidgetRun(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public void applyToWidget();
+    field public androidx.constraintlayout.core.widgets.analyzer.DependencyNode! baseline;
+  }
+
+  public class WidgetGroup {
+    ctor public WidgetGroup(int);
+    method public boolean add(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public void apply();
+    method public void cleanup(java.util.ArrayList<androidx.constraintlayout.core.widgets.analyzer.WidgetGroup!>!);
+    method public void clear();
+    method public int getId();
+    method public int getOrientation();
+    method public boolean intersectWith(androidx.constraintlayout.core.widgets.analyzer.WidgetGroup!);
+    method public boolean isAuthoritative();
+    method public int measureWrap(androidx.constraintlayout.core.LinearSystem!, int);
+    method public void moveTo(int, androidx.constraintlayout.core.widgets.analyzer.WidgetGroup!);
+    method public void setAuthoritative(boolean);
+    method public void setOrientation(int);
+    method public int size();
+  }
+
+  public abstract class WidgetRun implements androidx.constraintlayout.core.widgets.analyzer.Dependency {
+    ctor public WidgetRun(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method protected final void addTarget(androidx.constraintlayout.core.widgets.analyzer.DependencyNode!, androidx.constraintlayout.core.widgets.analyzer.DependencyNode!, int);
+    method protected final void addTarget(androidx.constraintlayout.core.widgets.analyzer.DependencyNode!, androidx.constraintlayout.core.widgets.analyzer.DependencyNode!, int, androidx.constraintlayout.core.widgets.analyzer.DimensionDependency!);
+    method protected final int getLimitedDimension(int, int);
+    method protected final androidx.constraintlayout.core.widgets.analyzer.DependencyNode! getTarget(androidx.constraintlayout.core.widgets.ConstraintAnchor!);
+    method protected final androidx.constraintlayout.core.widgets.analyzer.DependencyNode! getTarget(androidx.constraintlayout.core.widgets.ConstraintAnchor!, int);
+    method public long getWrapDimension();
+    method public boolean isCenterConnection();
+    method public boolean isDimensionResolved();
+    method public boolean isResolved();
+    method public void update(androidx.constraintlayout.core.widgets.analyzer.Dependency!);
+    method protected void updateRunCenter(androidx.constraintlayout.core.widgets.analyzer.Dependency!, androidx.constraintlayout.core.widgets.ConstraintAnchor!, androidx.constraintlayout.core.widgets.ConstraintAnchor!, int);
+    method protected void updateRunEnd(androidx.constraintlayout.core.widgets.analyzer.Dependency!);
+    method protected void updateRunStart(androidx.constraintlayout.core.widgets.analyzer.Dependency!);
+    method public long wrapSize(int);
+    field public androidx.constraintlayout.core.widgets.analyzer.DependencyNode! end;
+    field protected androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour! mDimensionBehavior;
+    field protected androidx.constraintlayout.core.widgets.analyzer.WidgetRun.RunType! mRunType;
+    field public int matchConstraintsType;
+    field public int orientation;
+    field public androidx.constraintlayout.core.widgets.analyzer.DependencyNode! start;
+  }
+
+}
+
diff --git a/constraintlayout/constraintlayout-core/api/current.txt b/constraintlayout/constraintlayout-core/api/current.txt
index 184a753..5be1d12 100644
--- a/constraintlayout/constraintlayout-core/api/current.txt
+++ b/constraintlayout/constraintlayout-core/api/current.txt
@@ -2597,7 +2597,7 @@
     ctor public GridReference(androidx.constraintlayout.core.state.State, androidx.constraintlayout.core.state.State.Helper);
     method public String? getColumnWeights();
     method public int getColumnsSet();
-    method public int[] getFlags();
+    method public int getFlags();
     method public float getHorizontalGaps();
     method public int getOrientation();
     method public int getPaddingBottom();
@@ -2611,7 +2611,7 @@
     method public float getVerticalGaps();
     method public void setColumnWeights(String);
     method public void setColumnsSet(int);
-    method public void setFlags(int[]);
+    method public void setFlags(int);
     method public void setFlags(String);
     method public void setHorizontalGaps(float);
     method public void setOrientation(int);
@@ -2658,7 +2658,7 @@
     ctor public GridCore(int, int);
     method public String? getColumnWeights();
     method public androidx.constraintlayout.core.widgets.ConstraintWidgetContainer? getContainer();
-    method public int[] getFlags();
+    method public int getFlags();
     method public float getHorizontalGaps();
     method public int getOrientation();
     method public String? getRowWeights();
@@ -2666,7 +2666,7 @@
     method public void setColumnWeights(String);
     method public void setColumns(int);
     method public void setContainer(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer);
-    method public void setFlags(int[]);
+    method public void setFlags(int);
     method public void setHorizontalGaps(float);
     method public void setOrientation(int);
     method public void setRowWeights(String);
@@ -2675,8 +2675,8 @@
     method public void setSpans(CharSequence);
     method public void setVerticalGaps(float);
     field public static final int HORIZONTAL = 0; // 0x0
-    field public static final int SPANS_RESPECT_WIDGET_ORDER = 1; // 0x1
-    field public static final int SUB_GRID_BY_COL_ROW = 0; // 0x0
+    field public static final int SPANS_RESPECT_WIDGET_ORDER = 2; // 0x2
+    field public static final int SUB_GRID_BY_COL_ROW = 1; // 0x1
     field public static final int VERTICAL = 1; // 0x1
   }
 
diff --git a/constraintlayout/constraintlayout-core/api/restricted_1.1.0-beta01.txt b/constraintlayout/constraintlayout-core/api/restricted_1.1.0-beta01.txt
new file mode 100644
index 0000000..daaf9e5
--- /dev/null
+++ b/constraintlayout/constraintlayout-core/api/restricted_1.1.0-beta01.txt
@@ -0,0 +1,3397 @@
+// Signature format: 4.0
+package androidx.constraintlayout.core {
+
+  public class ArrayLinkedVariables implements androidx.constraintlayout.core.ArrayRow.ArrayRowVariables {
+    method public void add(androidx.constraintlayout.core.SolverVariable!, float, boolean);
+    method public final void clear();
+    method public boolean contains(androidx.constraintlayout.core.SolverVariable!);
+    method public void display();
+    method public void divideByAmount(float);
+    method public final float get(androidx.constraintlayout.core.SolverVariable!);
+    method public int getCurrentSize();
+    method public int getHead();
+    method public final int getId(int);
+    method public final int getNextIndice(int);
+    method public final float getValue(int);
+    method public androidx.constraintlayout.core.SolverVariable! getVariable(int);
+    method public float getVariableValue(int);
+    method public int indexOf(androidx.constraintlayout.core.SolverVariable!);
+    method public void invert();
+    method public final void put(androidx.constraintlayout.core.SolverVariable!, float);
+    method public final float remove(androidx.constraintlayout.core.SolverVariable!, boolean);
+    method public int sizeInBytes();
+    method public float use(androidx.constraintlayout.core.ArrayRow!, boolean);
+    field protected final androidx.constraintlayout.core.Cache! mCache;
+  }
+
+  public class ArrayRow {
+    ctor public ArrayRow();
+    ctor public ArrayRow(androidx.constraintlayout.core.Cache!);
+    method public androidx.constraintlayout.core.ArrayRow! addError(androidx.constraintlayout.core.LinearSystem!, int);
+    method public void addError(androidx.constraintlayout.core.SolverVariable!);
+    method public void clear();
+    method public androidx.constraintlayout.core.ArrayRow! createRowDimensionRatio(androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, float);
+    method public androidx.constraintlayout.core.ArrayRow! createRowEqualDimension(float, float, float, androidx.constraintlayout.core.SolverVariable!, int, androidx.constraintlayout.core.SolverVariable!, int, androidx.constraintlayout.core.SolverVariable!, int, androidx.constraintlayout.core.SolverVariable!, int);
+    method public androidx.constraintlayout.core.ArrayRow! createRowEqualMatchDimensions(float, float, float, androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!);
+    method public androidx.constraintlayout.core.ArrayRow! createRowEquals(androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, int);
+    method public androidx.constraintlayout.core.ArrayRow! createRowEquals(androidx.constraintlayout.core.SolverVariable!, int);
+    method public androidx.constraintlayout.core.ArrayRow! createRowGreaterThan(androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, int);
+    method public androidx.constraintlayout.core.ArrayRow! createRowGreaterThan(androidx.constraintlayout.core.SolverVariable!, int, androidx.constraintlayout.core.SolverVariable!);
+    method public androidx.constraintlayout.core.ArrayRow! createRowLowerThan(androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, int);
+    method public androidx.constraintlayout.core.ArrayRow! createRowWithAngle(androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, float);
+    method public androidx.constraintlayout.core.SolverVariable! getKey();
+    method public androidx.constraintlayout.core.SolverVariable! getPivotCandidate(androidx.constraintlayout.core.LinearSystem!, boolean[]!);
+    method public void initFromRow(androidx.constraintlayout.core.LinearSystem.Row!);
+    method public boolean isEmpty();
+    method public androidx.constraintlayout.core.SolverVariable! pickPivot(androidx.constraintlayout.core.SolverVariable!);
+    method public void reset();
+    method public void updateFromFinalVariable(androidx.constraintlayout.core.LinearSystem!, androidx.constraintlayout.core.SolverVariable!, boolean);
+    method public void updateFromRow(androidx.constraintlayout.core.LinearSystem!, androidx.constraintlayout.core.ArrayRow!, boolean);
+    method public void updateFromSynonymVariable(androidx.constraintlayout.core.LinearSystem!, androidx.constraintlayout.core.SolverVariable!, boolean);
+    method public void updateFromSystem(androidx.constraintlayout.core.LinearSystem!);
+    field public androidx.constraintlayout.core.ArrayRow.ArrayRowVariables! variables;
+  }
+
+  public static interface ArrayRow.ArrayRowVariables {
+    method public void add(androidx.constraintlayout.core.SolverVariable!, float, boolean);
+    method public void clear();
+    method public boolean contains(androidx.constraintlayout.core.SolverVariable!);
+    method public void display();
+    method public void divideByAmount(float);
+    method public float get(androidx.constraintlayout.core.SolverVariable!);
+    method public int getCurrentSize();
+    method public androidx.constraintlayout.core.SolverVariable! getVariable(int);
+    method public float getVariableValue(int);
+    method public int indexOf(androidx.constraintlayout.core.SolverVariable!);
+    method public void invert();
+    method public void put(androidx.constraintlayout.core.SolverVariable!, float);
+    method public float remove(androidx.constraintlayout.core.SolverVariable!, boolean);
+    method public int sizeInBytes();
+    method public float use(androidx.constraintlayout.core.ArrayRow!, boolean);
+  }
+
+  public class Cache {
+    ctor public Cache();
+  }
+
+  public class GoalRow extends androidx.constraintlayout.core.ArrayRow {
+    ctor public GoalRow(androidx.constraintlayout.core.Cache!);
+  }
+
+  public class LinearSystem {
+    ctor public LinearSystem();
+    method public void addCenterPoint(androidx.constraintlayout.core.widgets.ConstraintWidget!, androidx.constraintlayout.core.widgets.ConstraintWidget!, float, int);
+    method public void addCentering(androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, int, float, androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, int, int);
+    method public void addConstraint(androidx.constraintlayout.core.ArrayRow!);
+    method public androidx.constraintlayout.core.ArrayRow! addEquality(androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, int, int);
+    method public void addEquality(androidx.constraintlayout.core.SolverVariable!, int);
+    method public void addGreaterBarrier(androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, int, boolean);
+    method public void addGreaterThan(androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, int, int);
+    method public void addLowerBarrier(androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, int, boolean);
+    method public void addLowerThan(androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, int, int);
+    method public void addRatio(androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, float, int);
+    method public void addSynonym(androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, int);
+    method public androidx.constraintlayout.core.SolverVariable! createErrorVariable(int, String!);
+    method public androidx.constraintlayout.core.SolverVariable! createExtraVariable();
+    method public androidx.constraintlayout.core.SolverVariable! createObjectVariable(Object!);
+    method public androidx.constraintlayout.core.ArrayRow! createRow();
+    method public static androidx.constraintlayout.core.ArrayRow! createRowDimensionPercent(androidx.constraintlayout.core.LinearSystem!, androidx.constraintlayout.core.SolverVariable!, androidx.constraintlayout.core.SolverVariable!, float);
+    method public androidx.constraintlayout.core.SolverVariable! createSlackVariable();
+    method public void displayReadableRows();
+    method public void displayVariablesReadableRows();
+    method public void fillMetrics(androidx.constraintlayout.core.Metrics!);
+    method public androidx.constraintlayout.core.Cache! getCache();
+    method public int getMemoryUsed();
+    method public static androidx.constraintlayout.core.Metrics! getMetrics();
+    method public int getNumEquations();
+    method public int getNumVariables();
+    method public int getObjectVariableValue(Object!);
+    method public void minimize() throws java.lang.Exception;
+    method public void removeRow(androidx.constraintlayout.core.ArrayRow!);
+    method public void reset();
+    field public static long ARRAY_ROW_CREATION;
+    field public static final boolean DEBUG = false;
+    field public static final boolean FULL_DEBUG = false;
+    field public static long OPTIMIZED_ARRAY_ROW_CREATION;
+    field public static boolean OPTIMIZED_ENGINE;
+    field public static boolean SIMPLIFY_SYNONYMS;
+    field public static boolean SKIP_COLUMNS;
+    field public static boolean USE_BASIC_SYNONYMS;
+    field public static boolean USE_DEPENDENCY_ORDERING;
+    field public static boolean USE_SYNONYMS;
+    field public boolean graphOptimizer;
+    field public boolean hasSimpleDefinition;
+    field public boolean newgraphOptimizer;
+    field public static androidx.constraintlayout.core.Metrics! sMetrics;
+  }
+
+  public class Metrics {
+    ctor public Metrics();
+    method public void copy(androidx.constraintlayout.core.Metrics!);
+    method public void reset();
+    field public long additionalMeasures;
+    field public long bfs;
+    field public long constraints;
+    field public long determineGroups;
+    field public long errors;
+    field public long extravariables;
+    field public long fullySolved;
+    field public long graphOptimizer;
+    field public long graphSolved;
+    field public long grouping;
+    field public long infeasibleDetermineGroups;
+    field public long iterations;
+    field public long lastTableSize;
+    field public long layouts;
+    field public long linearSolved;
+    field public long mChildCount;
+    field public long mEquations;
+    field public long mMeasureCalls;
+    field public long mMeasureDuration;
+    field public int mNumberOfLayouts;
+    field public int mNumberOfMeasures;
+    field public long mSimpleEquations;
+    field public long mSolverPasses;
+    field public long mVariables;
+    field public long maxRows;
+    field public long maxTableSize;
+    field public long maxVariables;
+    field public long measuredMatchWidgets;
+    field public long measuredWidgets;
+    field public long measures;
+    field public long measuresLayoutDuration;
+    field public long measuresWidgetsDuration;
+    field public long measuresWrap;
+    field public long measuresWrapInfeasible;
+    field public long minimize;
+    field public long minimizeGoal;
+    field public long nonresolvedWidgets;
+    field public long optimize;
+    field public long pivots;
+    field public java.util.ArrayList<java.lang.String!>! problematicLayouts;
+    field public long resolutions;
+    field public long resolvedWidgets;
+    field public long simpleconstraints;
+    field public long slackvariables;
+    field public long tableSizeIncrease;
+    field public long variables;
+    field public long widgets;
+  }
+
+  public class PriorityGoalRow extends androidx.constraintlayout.core.ArrayRow {
+    ctor public PriorityGoalRow(androidx.constraintlayout.core.Cache!);
+  }
+
+  public class SolverVariable implements java.lang.Comparable<androidx.constraintlayout.core.SolverVariable!> {
+    ctor public SolverVariable(androidx.constraintlayout.core.SolverVariable.Type!, String!);
+    ctor public SolverVariable(String!, androidx.constraintlayout.core.SolverVariable.Type!);
+    method public final void addToRow(androidx.constraintlayout.core.ArrayRow!);
+    method public int compareTo(androidx.constraintlayout.core.SolverVariable!);
+    method public String! getName();
+    method public final void removeFromRow(androidx.constraintlayout.core.ArrayRow!);
+    method public void reset();
+    method public void setFinalValue(androidx.constraintlayout.core.LinearSystem!, float);
+    method public void setName(String!);
+    method public void setSynonym(androidx.constraintlayout.core.LinearSystem!, androidx.constraintlayout.core.SolverVariable!, float);
+    method public void setType(androidx.constraintlayout.core.SolverVariable.Type!, String!);
+    method public final void updateReferencesWithNewDefinition(androidx.constraintlayout.core.LinearSystem!, androidx.constraintlayout.core.ArrayRow!);
+    field public static final int STRENGTH_BARRIER = 6; // 0x6
+    field public static final int STRENGTH_CENTERING = 7; // 0x7
+    field public static final int STRENGTH_EQUALITY = 5; // 0x5
+    field public static final int STRENGTH_FIXED = 8; // 0x8
+    field public static final int STRENGTH_HIGH = 3; // 0x3
+    field public static final int STRENGTH_HIGHEST = 4; // 0x4
+    field public static final int STRENGTH_LOW = 1; // 0x1
+    field public static final int STRENGTH_MEDIUM = 2; // 0x2
+    field public static final int STRENGTH_NONE = 0; // 0x0
+    field public float computedValue;
+    field public int id;
+    field public boolean inGoal;
+    field public boolean isFinalValue;
+    field public int strength;
+    field public int usageInRowCount;
+  }
+
+  public enum SolverVariable.Type {
+    enum_constant public static final androidx.constraintlayout.core.SolverVariable.Type CONSTANT;
+    enum_constant public static final androidx.constraintlayout.core.SolverVariable.Type ERROR;
+    enum_constant public static final androidx.constraintlayout.core.SolverVariable.Type SLACK;
+    enum_constant public static final androidx.constraintlayout.core.SolverVariable.Type UNKNOWN;
+    enum_constant public static final androidx.constraintlayout.core.SolverVariable.Type UNRESTRICTED;
+  }
+
+  public class SolverVariableValues implements androidx.constraintlayout.core.ArrayRow.ArrayRowVariables {
+    method public void add(androidx.constraintlayout.core.SolverVariable!, float, boolean);
+    method public void clear();
+    method public boolean contains(androidx.constraintlayout.core.SolverVariable!);
+    method public void display();
+    method public void divideByAmount(float);
+    method public float get(androidx.constraintlayout.core.SolverVariable!);
+    method public int getCurrentSize();
+    method public androidx.constraintlayout.core.SolverVariable! getVariable(int);
+    method public float getVariableValue(int);
+    method public int indexOf(androidx.constraintlayout.core.SolverVariable!);
+    method public void invert();
+    method public void put(androidx.constraintlayout.core.SolverVariable!, float);
+    method public float remove(androidx.constraintlayout.core.SolverVariable!, boolean);
+    method public int sizeInBytes();
+    method public float use(androidx.constraintlayout.core.ArrayRow!, boolean);
+    field protected final androidx.constraintlayout.core.Cache! mCache;
+  }
+
+}
+
+package androidx.constraintlayout.core.dsl {
+
+  public class Barrier extends androidx.constraintlayout.core.dsl.Helper {
+    ctor public Barrier(String!);
+    ctor public Barrier(String!, String!);
+    method public androidx.constraintlayout.core.dsl.Barrier! addReference(androidx.constraintlayout.core.dsl.Ref!);
+    method public androidx.constraintlayout.core.dsl.Barrier! addReference(String!);
+    method public androidx.constraintlayout.core.dsl.Constraint.Side! getDirection();
+    method public int getMargin();
+    method public String! referencesToString();
+    method public void setDirection(androidx.constraintlayout.core.dsl.Constraint.Side!);
+    method public void setMargin(int);
+  }
+
+  public abstract class Chain extends androidx.constraintlayout.core.dsl.Helper {
+    ctor public Chain(String!);
+    method public androidx.constraintlayout.core.dsl.Chain! addReference(androidx.constraintlayout.core.dsl.Ref!);
+    method public androidx.constraintlayout.core.dsl.Chain! addReference(String!);
+    method public androidx.constraintlayout.core.dsl.Chain.Style! getStyle();
+    method public String! referencesToString();
+    method public void setStyle(androidx.constraintlayout.core.dsl.Chain.Style!);
+    field protected java.util.ArrayList<androidx.constraintlayout.core.dsl.Ref!>! references;
+    field protected static final java.util.Map<androidx.constraintlayout.core.dsl.Chain.Style!,java.lang.String!>! styleMap;
+  }
+
+  public class Chain.Anchor {
+    method public void build(StringBuilder!);
+    method public String! getId();
+  }
+
+  public enum Chain.Style {
+    enum_constant public static final androidx.constraintlayout.core.dsl.Chain.Style PACKED;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Chain.Style SPREAD;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Chain.Style SPREAD_INSIDE;
+  }
+
+  public class Constraint {
+    ctor public Constraint(String!);
+    method protected void append(StringBuilder!, String!, float);
+    method public String! convertStringArrayToString(String![]!);
+    method public androidx.constraintlayout.core.dsl.Constraint.VAnchor! getBaseline();
+    method public androidx.constraintlayout.core.dsl.Constraint.VAnchor! getBottom();
+    method public float getCircleAngle();
+    method public String! getCircleConstraint();
+    method public int getCircleRadius();
+    method public String! getDimensionRatio();
+    method public int getEditorAbsoluteX();
+    method public int getEditorAbsoluteY();
+    method public androidx.constraintlayout.core.dsl.Constraint.HAnchor! getEnd();
+    method public int getHeight();
+    method public androidx.constraintlayout.core.dsl.Constraint.Behaviour! getHeightDefault();
+    method public int getHeightMax();
+    method public int getHeightMin();
+    method public float getHeightPercent();
+    method public float getHorizontalBias();
+    method public androidx.constraintlayout.core.dsl.Constraint.ChainMode! getHorizontalChainStyle();
+    method public float getHorizontalWeight();
+    method public androidx.constraintlayout.core.dsl.Constraint.HAnchor! getLeft();
+    method public String![]! getReferenceIds();
+    method public androidx.constraintlayout.core.dsl.Constraint.HAnchor! getRight();
+    method public androidx.constraintlayout.core.dsl.Constraint.HAnchor! getStart();
+    method public androidx.constraintlayout.core.dsl.Constraint.VAnchor! getTop();
+    method public float getVerticalBias();
+    method public androidx.constraintlayout.core.dsl.Constraint.ChainMode! getVerticalChainStyle();
+    method public float getVerticalWeight();
+    method public int getWidth();
+    method public androidx.constraintlayout.core.dsl.Constraint.Behaviour! getWidthDefault();
+    method public int getWidthMax();
+    method public int getWidthMin();
+    method public float getWidthPercent();
+    method public boolean isConstrainedHeight();
+    method public boolean isConstrainedWidth();
+    method public void linkToBaseline(androidx.constraintlayout.core.dsl.Constraint.VAnchor!);
+    method public void linkToBaseline(androidx.constraintlayout.core.dsl.Constraint.VAnchor!, int);
+    method public void linkToBaseline(androidx.constraintlayout.core.dsl.Constraint.VAnchor!, int, int);
+    method public void linkToBottom(androidx.constraintlayout.core.dsl.Constraint.VAnchor!);
+    method public void linkToBottom(androidx.constraintlayout.core.dsl.Constraint.VAnchor!, int);
+    method public void linkToBottom(androidx.constraintlayout.core.dsl.Constraint.VAnchor!, int, int);
+    method public void linkToEnd(androidx.constraintlayout.core.dsl.Constraint.HAnchor!);
+    method public void linkToEnd(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int);
+    method public void linkToEnd(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int, int);
+    method public void linkToLeft(androidx.constraintlayout.core.dsl.Constraint.HAnchor!);
+    method public void linkToLeft(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int);
+    method public void linkToLeft(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int, int);
+    method public void linkToRight(androidx.constraintlayout.core.dsl.Constraint.HAnchor!);
+    method public void linkToRight(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int);
+    method public void linkToRight(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int, int);
+    method public void linkToStart(androidx.constraintlayout.core.dsl.Constraint.HAnchor!);
+    method public void linkToStart(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int);
+    method public void linkToStart(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int, int);
+    method public void linkToTop(androidx.constraintlayout.core.dsl.Constraint.VAnchor!);
+    method public void linkToTop(androidx.constraintlayout.core.dsl.Constraint.VAnchor!, int);
+    method public void linkToTop(androidx.constraintlayout.core.dsl.Constraint.VAnchor!, int, int);
+    method public void setCircleAngle(float);
+    method public void setCircleConstraint(String!);
+    method public void setCircleRadius(int);
+    method public void setConstrainedHeight(boolean);
+    method public void setConstrainedWidth(boolean);
+    method public void setDimensionRatio(String!);
+    method public void setEditorAbsoluteX(int);
+    method public void setEditorAbsoluteY(int);
+    method public void setHeight(int);
+    method public void setHeightDefault(androidx.constraintlayout.core.dsl.Constraint.Behaviour!);
+    method public void setHeightMax(int);
+    method public void setHeightMin(int);
+    method public void setHeightPercent(float);
+    method public void setHorizontalBias(float);
+    method public void setHorizontalChainStyle(androidx.constraintlayout.core.dsl.Constraint.ChainMode!);
+    method public void setHorizontalWeight(float);
+    method public void setReferenceIds(String![]!);
+    method public void setVerticalBias(float);
+    method public void setVerticalChainStyle(androidx.constraintlayout.core.dsl.Constraint.ChainMode!);
+    method public void setVerticalWeight(float);
+    method public void setWidth(int);
+    method public void setWidthDefault(androidx.constraintlayout.core.dsl.Constraint.Behaviour!);
+    method public void setWidthMax(int);
+    method public void setWidthMin(int);
+    method public void setWidthPercent(float);
+    field public static final androidx.constraintlayout.core.dsl.Constraint! PARENT;
+  }
+
+  public class Constraint.Anchor {
+    method public void build(StringBuilder!);
+    method public String! getId();
+  }
+
+  public enum Constraint.Behaviour {
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.Behaviour PERCENT;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.Behaviour RATIO;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.Behaviour RESOLVED;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.Behaviour SPREAD;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.Behaviour WRAP;
+  }
+
+  public enum Constraint.ChainMode {
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.ChainMode PACKED;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.ChainMode SPREAD;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.ChainMode SPREAD_INSIDE;
+  }
+
+  public class Constraint.HAnchor extends androidx.constraintlayout.core.dsl.Constraint.Anchor {
+  }
+
+  public enum Constraint.HSide {
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.HSide END;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.HSide LEFT;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.HSide RIGHT;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.HSide START;
+  }
+
+  public enum Constraint.Side {
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.Side BASELINE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.Side BOTTOM;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.Side END;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.Side LEFT;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.Side RIGHT;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.Side START;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.Side TOP;
+  }
+
+  public class Constraint.VAnchor extends androidx.constraintlayout.core.dsl.Constraint.Anchor {
+  }
+
+  public enum Constraint.VSide {
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.VSide BASELINE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.VSide BOTTOM;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Constraint.VSide TOP;
+  }
+
+  public class ConstraintSet {
+    ctor public ConstraintSet(String!);
+    method public void add(androidx.constraintlayout.core.dsl.Constraint!);
+    method public void add(androidx.constraintlayout.core.dsl.Helper!);
+  }
+
+  public abstract class Guideline extends androidx.constraintlayout.core.dsl.Helper {
+    method public int getEnd();
+    method public float getPercent();
+    method public int getStart();
+    method public void setEnd(int);
+    method public void setPercent(float);
+    method public void setStart(int);
+  }
+
+  public class HChain extends androidx.constraintlayout.core.dsl.Chain {
+    ctor public HChain(String!);
+    ctor public HChain(String!, String!);
+    method public androidx.constraintlayout.core.dsl.HChain.HAnchor! getEnd();
+    method public androidx.constraintlayout.core.dsl.HChain.HAnchor! getLeft();
+    method public androidx.constraintlayout.core.dsl.HChain.HAnchor! getRight();
+    method public androidx.constraintlayout.core.dsl.HChain.HAnchor! getStart();
+    method public void linkToEnd(androidx.constraintlayout.core.dsl.Constraint.HAnchor!);
+    method public void linkToEnd(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int);
+    method public void linkToEnd(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int, int);
+    method public void linkToLeft(androidx.constraintlayout.core.dsl.Constraint.HAnchor!);
+    method public void linkToLeft(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int);
+    method public void linkToLeft(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int, int);
+    method public void linkToRight(androidx.constraintlayout.core.dsl.Constraint.HAnchor!);
+    method public void linkToRight(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int);
+    method public void linkToRight(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int, int);
+    method public void linkToStart(androidx.constraintlayout.core.dsl.Constraint.HAnchor!);
+    method public void linkToStart(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int);
+    method public void linkToStart(androidx.constraintlayout.core.dsl.Constraint.HAnchor!, int, int);
+  }
+
+  public class HChain.HAnchor extends androidx.constraintlayout.core.dsl.Chain.Anchor {
+  }
+
+  public class Helper {
+    ctor public Helper(String!, androidx.constraintlayout.core.dsl.Helper.HelperType!);
+    ctor public Helper(String!, androidx.constraintlayout.core.dsl.Helper.HelperType!, String!);
+    method public void append(java.util.Map<java.lang.String!,java.lang.String!>!, StringBuilder!);
+    method public java.util.Map<java.lang.String!,java.lang.String!>! convertConfigToMap();
+    method public String! getConfig();
+    method public String! getId();
+    method public androidx.constraintlayout.core.dsl.Helper.HelperType! getType();
+    method public static void main(String![]!);
+    field protected String! config;
+    field protected java.util.Map<java.lang.String!,java.lang.String!>! configMap;
+    field protected final String! name;
+    field protected static final java.util.Map<androidx.constraintlayout.core.dsl.Constraint.Side!,java.lang.String!>! sideMap;
+    field protected androidx.constraintlayout.core.dsl.Helper.HelperType! type;
+    field protected static final java.util.Map<androidx.constraintlayout.core.dsl.Helper.Type!,java.lang.String!>! typeMap;
+  }
+
+  public static final class Helper.HelperType {
+    ctor public Helper.HelperType(String!);
+  }
+
+  public enum Helper.Type {
+    enum_constant public static final androidx.constraintlayout.core.dsl.Helper.Type BARRIER;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Helper.Type HORIZONTAL_CHAIN;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Helper.Type HORIZONTAL_GUIDELINE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Helper.Type VERTICAL_CHAIN;
+    enum_constant public static final androidx.constraintlayout.core.dsl.Helper.Type VERTICAL_GUIDELINE;
+  }
+
+  public class KeyAttribute extends androidx.constraintlayout.core.dsl.Keys {
+    ctor public KeyAttribute(int, String!);
+    method protected void attributesToString(StringBuilder!);
+    method public float getAlpha();
+    method public androidx.constraintlayout.core.dsl.KeyAttribute.Fit! getCurveFit();
+    method public float getPivotX();
+    method public float getPivotY();
+    method public float getRotation();
+    method public float getRotationX();
+    method public float getRotationY();
+    method public float getScaleX();
+    method public float getScaleY();
+    method public String! getTarget();
+    method public String! getTransitionEasing();
+    method public float getTransitionPathRotate();
+    method public float getTranslationX();
+    method public float getTranslationY();
+    method public float getTranslationZ();
+    method public androidx.constraintlayout.core.dsl.KeyAttribute.Visibility! getVisibility();
+    method public void setAlpha(float);
+    method public void setCurveFit(androidx.constraintlayout.core.dsl.KeyAttribute.Fit!);
+    method public void setPivotX(float);
+    method public void setPivotY(float);
+    method public void setRotation(float);
+    method public void setRotationX(float);
+    method public void setRotationY(float);
+    method public void setScaleX(float);
+    method public void setScaleY(float);
+    method public void setTarget(String!);
+    method public void setTransitionEasing(String!);
+    method public void setTransitionPathRotate(float);
+    method public void setTranslationX(float);
+    method public void setTranslationY(float);
+    method public void setTranslationZ(float);
+    method public void setVisibility(androidx.constraintlayout.core.dsl.KeyAttribute.Visibility!);
+    field protected String! TYPE;
+  }
+
+  public enum KeyAttribute.Fit {
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyAttribute.Fit LINEAR;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyAttribute.Fit SPLINE;
+  }
+
+  public enum KeyAttribute.Visibility {
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyAttribute.Visibility GONE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyAttribute.Visibility INVISIBLE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyAttribute.Visibility VISIBLE;
+  }
+
+  public class KeyAttributes extends androidx.constraintlayout.core.dsl.Keys {
+    method protected void attributesToString(StringBuilder!);
+    method public float[]! getAlpha();
+    method public androidx.constraintlayout.core.dsl.KeyAttributes.Fit! getCurveFit();
+    method public float[]! getPivotX();
+    method public float[]! getPivotY();
+    method public float[]! getRotation();
+    method public float[]! getRotationX();
+    method public float[]! getRotationY();
+    method public float[]! getScaleX();
+    method public float[]! getScaleY();
+    method public String![]! getTarget();
+    method public String! getTransitionEasing();
+    method public float[]! getTransitionPathRotate();
+    method public float[]! getTranslationX();
+    method public float[]! getTranslationY();
+    method public float[]! getTranslationZ();
+    method public androidx.constraintlayout.core.dsl.KeyAttributes.Visibility![]! getVisibility();
+    method public void setAlpha(float...!);
+    method public void setCurveFit(androidx.constraintlayout.core.dsl.KeyAttributes.Fit!);
+    method public void setPivotX(float...!);
+    method public void setPivotY(float...!);
+    method public void setRotation(float...!);
+    method public void setRotationX(float...!);
+    method public void setRotationY(float...!);
+    method public void setScaleX(float[]!);
+    method public void setScaleY(float[]!);
+    method public void setTarget(String![]!);
+    method public void setTransitionEasing(String!);
+    method public void setTransitionPathRotate(float...!);
+    method public void setTranslationX(float[]!);
+    method public void setTranslationY(float[]!);
+    method public void setTranslationZ(float[]!);
+    method public void setVisibility(androidx.constraintlayout.core.dsl.KeyAttributes.Visibility!...!);
+    field protected String! TYPE;
+  }
+
+  public enum KeyAttributes.Fit {
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyAttributes.Fit LINEAR;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyAttributes.Fit SPLINE;
+  }
+
+  public enum KeyAttributes.Visibility {
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyAttributes.Visibility GONE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyAttributes.Visibility INVISIBLE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyAttributes.Visibility VISIBLE;
+  }
+
+  public class KeyCycle extends androidx.constraintlayout.core.dsl.KeyAttribute {
+    method public float getOffset();
+    method public float getPeriod();
+    method public float getPhase();
+    method public androidx.constraintlayout.core.dsl.KeyCycle.Wave! getShape();
+    method public void setOffset(float);
+    method public void setPeriod(float);
+    method public void setPhase(float);
+    method public void setShape(androidx.constraintlayout.core.dsl.KeyCycle.Wave!);
+  }
+
+  public enum KeyCycle.Wave {
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyCycle.Wave COS;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyCycle.Wave REVERSE_SAW;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyCycle.Wave SAW;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyCycle.Wave SIN;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyCycle.Wave SQUARE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyCycle.Wave TRIANGLE;
+  }
+
+  public class KeyCycles extends androidx.constraintlayout.core.dsl.KeyAttributes {
+    method public float[]! getWaveOffset();
+    method public float[]! getWavePeriod();
+    method public float[]! getWavePhase();
+    method public androidx.constraintlayout.core.dsl.KeyCycles.Wave! getWaveShape();
+    method public void setWaveOffset(float...!);
+    method public void setWavePeriod(float...!);
+    method public void setWavePhase(float...!);
+    method public void setWaveShape(androidx.constraintlayout.core.dsl.KeyCycles.Wave!);
+  }
+
+  public enum KeyCycles.Wave {
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyCycles.Wave COS;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyCycles.Wave REVERSE_SAW;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyCycles.Wave SAW;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyCycles.Wave SIN;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyCycles.Wave SQUARE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyCycles.Wave TRIANGLE;
+  }
+
+  public class KeyFrames {
+    ctor public KeyFrames();
+    method public void add(androidx.constraintlayout.core.dsl.Keys!);
+  }
+
+  public class KeyPosition extends androidx.constraintlayout.core.dsl.Keys {
+    ctor public KeyPosition(String!, int);
+    method public int getFrames();
+    method public float getPercentHeight();
+    method public float getPercentWidth();
+    method public float getPercentX();
+    method public float getPercentY();
+    method public androidx.constraintlayout.core.dsl.KeyPosition.Type! getPositionType();
+    method public String! getTarget();
+    method public String! getTransitionEasing();
+    method public void setFrames(int);
+    method public void setPercentHeight(float);
+    method public void setPercentWidth(float);
+    method public void setPercentX(float);
+    method public void setPercentY(float);
+    method public void setPositionType(androidx.constraintlayout.core.dsl.KeyPosition.Type!);
+    method public void setTarget(String!);
+    method public void setTransitionEasing(String!);
+  }
+
+  public enum KeyPosition.Type {
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyPosition.Type CARTESIAN;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyPosition.Type PATH;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyPosition.Type SCREEN;
+  }
+
+  public class KeyPositions extends androidx.constraintlayout.core.dsl.Keys {
+    ctor public KeyPositions(int, java.lang.String!...!);
+    method public int[]! getFrames();
+    method public float[]! getPercentHeight();
+    method public float[]! getPercentWidth();
+    method public float[]! getPercentX();
+    method public float[]! getPercentY();
+    method public androidx.constraintlayout.core.dsl.KeyPositions.Type! getPositionType();
+    method public String![]! getTarget();
+    method public String! getTransitionEasing();
+    method public void setFrames(int...!);
+    method public void setPercentHeight(float...!);
+    method public void setPercentWidth(float...!);
+    method public void setPercentX(float...!);
+    method public void setPercentY(float...!);
+    method public void setPositionType(androidx.constraintlayout.core.dsl.KeyPositions.Type!);
+    method public void setTransitionEasing(String!);
+  }
+
+  public enum KeyPositions.Type {
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyPositions.Type CARTESIAN;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyPositions.Type PATH;
+    enum_constant public static final androidx.constraintlayout.core.dsl.KeyPositions.Type SCREEN;
+  }
+
+  public class Keys {
+    ctor public Keys();
+    method protected void append(StringBuilder!, String!, float);
+    method protected void append(StringBuilder!, String!, float[]!);
+    method protected void append(StringBuilder!, String!, int);
+    method protected void append(StringBuilder!, String!, String!);
+    method protected void append(StringBuilder!, String!, String![]!);
+    method protected String! unpack(String![]!);
+  }
+
+  public class MotionScene {
+    ctor public MotionScene();
+    method public void addConstraintSet(androidx.constraintlayout.core.dsl.ConstraintSet!);
+    method public void addTransition(androidx.constraintlayout.core.dsl.Transition!);
+  }
+
+  public class OnSwipe {
+    ctor public OnSwipe();
+    ctor public OnSwipe(String!, androidx.constraintlayout.core.dsl.OnSwipe.Side!, androidx.constraintlayout.core.dsl.OnSwipe.Drag!);
+    method public androidx.constraintlayout.core.dsl.OnSwipe.Mode! getAutoCompleteMode();
+    method public androidx.constraintlayout.core.dsl.OnSwipe.Drag! getDragDirection();
+    method public float getDragScale();
+    method public float getDragThreshold();
+    method public String! getLimitBoundsTo();
+    method public float getMaxAcceleration();
+    method public float getMaxVelocity();
+    method public androidx.constraintlayout.core.dsl.OnSwipe.TouchUp! getOnTouchUp();
+    method public String! getRotationCenterId();
+    method public androidx.constraintlayout.core.dsl.OnSwipe.Boundary! getSpringBoundary();
+    method public float getSpringDamping();
+    method public float getSpringMass();
+    method public float getSpringStiffness();
+    method public float getSpringStopThreshold();
+    method public String! getTouchAnchorId();
+    method public androidx.constraintlayout.core.dsl.OnSwipe.Side! getTouchAnchorSide();
+    method public void setAutoCompleteMode(androidx.constraintlayout.core.dsl.OnSwipe.Mode!);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setDragDirection(androidx.constraintlayout.core.dsl.OnSwipe.Drag!);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setDragScale(int);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setDragThreshold(int);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setLimitBoundsTo(String!);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setMaxAcceleration(int);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setMaxVelocity(int);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setOnTouchUp(androidx.constraintlayout.core.dsl.OnSwipe.TouchUp!);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setRotateCenter(String!);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setSpringBoundary(androidx.constraintlayout.core.dsl.OnSwipe.Boundary!);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setSpringDamping(float);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setSpringMass(float);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setSpringStiffness(float);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setSpringStopThreshold(float);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setTouchAnchorId(String!);
+    method public androidx.constraintlayout.core.dsl.OnSwipe! setTouchAnchorSide(androidx.constraintlayout.core.dsl.OnSwipe.Side!);
+    field public static final int FLAG_DISABLE_POST_SCROLL = 1; // 0x1
+    field public static final int FLAG_DISABLE_SCROLL = 2; // 0x2
+  }
+
+  public enum OnSwipe.Boundary {
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Boundary BOUNCE_BOTH;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Boundary BOUNCE_END;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Boundary BOUNCE_START;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Boundary OVERSHOOT;
+  }
+
+  public enum OnSwipe.Drag {
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Drag ANTICLOCKWISE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Drag CLOCKWISE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Drag DOWN;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Drag END;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Drag LEFT;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Drag RIGHT;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Drag START;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Drag UP;
+  }
+
+  public enum OnSwipe.Mode {
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Mode SPRING;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Mode VELOCITY;
+  }
+
+  public enum OnSwipe.Side {
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Side BOTTOM;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Side END;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Side LEFT;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Side MIDDLE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Side RIGHT;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Side START;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.Side TOP;
+  }
+
+  public enum OnSwipe.TouchUp {
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.TouchUp AUTOCOMPLETE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.TouchUp DECELERATE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.TouchUp DECELERATE_COMPLETE;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.TouchUp NEVER_COMPLETE_END;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.TouchUp NEVER_COMPLETE_START;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.TouchUp STOP;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.TouchUp TO_END;
+    enum_constant public static final androidx.constraintlayout.core.dsl.OnSwipe.TouchUp TO_START;
+  }
+
+  public class Ref {
+    method public static void addStringToReferences(String!, java.util.ArrayList<androidx.constraintlayout.core.dsl.Ref!>!);
+    method public String! getId();
+    method public float getPostMargin();
+    method public float getPreMargin();
+    method public float getWeight();
+    method public static float parseFloat(Object!);
+    method public static androidx.constraintlayout.core.dsl.Ref! parseStringToRef(String!);
+    method public void setId(String!);
+    method public void setPostMargin(float);
+    method public void setPreMargin(float);
+    method public void setWeight(float);
+  }
+
+  public class Transition {
+    ctor public Transition(String!, String!);
+    ctor public Transition(String!, String!, String!);
+    method public String! getId();
+    method public void setDuration(int);
+    method public void setFrom(String!);
+    method public void setId(String!);
+    method public void setKeyFrames(androidx.constraintlayout.core.dsl.Keys!);
+    method public void setOnSwipe(androidx.constraintlayout.core.dsl.OnSwipe!);
+    method public void setStagger(float);
+    method public void setTo(String!);
+  }
+
+  public class VChain extends androidx.constraintlayout.core.dsl.Chain {
+    ctor public VChain(String!);
+    ctor public VChain(String!, String!);
+    method public androidx.constraintlayout.core.dsl.VChain.VAnchor! getBaseline();
+    method public androidx.constraintlayout.core.dsl.VChain.VAnchor! getBottom();
+    method public androidx.constraintlayout.core.dsl.VChain.VAnchor! getTop();
+    method public void linkToBaseline(androidx.constraintlayout.core.dsl.Constraint.VAnchor!);
+    method public void linkToBaseline(androidx.constraintlayout.core.dsl.Constraint.VAnchor!, int);
+    method public void linkToBaseline(androidx.constraintlayout.core.dsl.Constraint.VAnchor!, int, int);
+    method public void linkToBottom(androidx.constraintlayout.core.dsl.Constraint.VAnchor!);
+    method public void linkToBottom(androidx.constraintlayout.core.dsl.Constraint.VAnchor!, int);
+    method public void linkToBottom(androidx.constraintlayout.core.dsl.Constraint.VAnchor!, int, int);
+    method public void linkToTop(androidx.constraintlayout.core.dsl.Constraint.VAnchor!);
+    method public void linkToTop(androidx.constraintlayout.core.dsl.Constraint.VAnchor!, int);
+    method public void linkToTop(androidx.constraintlayout.core.dsl.Constraint.VAnchor!, int, int);
+  }
+
+  public class VChain.VAnchor extends androidx.constraintlayout.core.dsl.Chain.Anchor {
+  }
+
+  public class VGuideline extends androidx.constraintlayout.core.dsl.Guideline {
+    ctor public VGuideline(String!);
+    ctor public VGuideline(String!, String!);
+  }
+
+}
+
+package androidx.constraintlayout.core.motion {
+
+  public class CustomAttribute {
+    ctor public CustomAttribute(androidx.constraintlayout.core.motion.CustomAttribute!, Object!);
+    ctor public CustomAttribute(String!, androidx.constraintlayout.core.motion.CustomAttribute.AttributeType!);
+    ctor public CustomAttribute(String!, androidx.constraintlayout.core.motion.CustomAttribute.AttributeType!, Object!, boolean);
+    method public boolean diff(androidx.constraintlayout.core.motion.CustomAttribute!);
+    method public androidx.constraintlayout.core.motion.CustomAttribute.AttributeType! getType();
+    method public float getValueToInterpolate();
+    method public void getValuesToInterpolate(float[]!);
+    method public static int hsvToRgb(float, float, float);
+    method public boolean isContinuous();
+    method public int numberOfInterpolatedValues();
+    method public void setColorValue(int);
+    method public void setFloatValue(float);
+    method public void setIntValue(int);
+    method public void setStringValue(String!);
+    method public void setValue(float[]!);
+    method public void setValue(Object!);
+  }
+
+  public enum CustomAttribute.AttributeType {
+    enum_constant public static final androidx.constraintlayout.core.motion.CustomAttribute.AttributeType BOOLEAN_TYPE;
+    enum_constant public static final androidx.constraintlayout.core.motion.CustomAttribute.AttributeType COLOR_DRAWABLE_TYPE;
+    enum_constant public static final androidx.constraintlayout.core.motion.CustomAttribute.AttributeType COLOR_TYPE;
+    enum_constant public static final androidx.constraintlayout.core.motion.CustomAttribute.AttributeType DIMENSION_TYPE;
+    enum_constant public static final androidx.constraintlayout.core.motion.CustomAttribute.AttributeType FLOAT_TYPE;
+    enum_constant public static final androidx.constraintlayout.core.motion.CustomAttribute.AttributeType INT_TYPE;
+    enum_constant public static final androidx.constraintlayout.core.motion.CustomAttribute.AttributeType REFERENCE_TYPE;
+    enum_constant public static final androidx.constraintlayout.core.motion.CustomAttribute.AttributeType STRING_TYPE;
+  }
+
+  public class CustomVariable {
+    ctor public CustomVariable(androidx.constraintlayout.core.motion.CustomVariable!);
+    ctor public CustomVariable(androidx.constraintlayout.core.motion.CustomVariable!, Object!);
+    ctor public CustomVariable(String!, int);
+    ctor public CustomVariable(String!, int, boolean);
+    ctor public CustomVariable(String!, int, float);
+    ctor public CustomVariable(String!, int, int);
+    ctor public CustomVariable(String!, int, Object!);
+    ctor public CustomVariable(String!, int, String!);
+    method public void applyToWidget(androidx.constraintlayout.core.motion.MotionWidget!);
+    method public static String! colorString(int);
+    method public androidx.constraintlayout.core.motion.CustomVariable! copy();
+    method public boolean diff(androidx.constraintlayout.core.motion.CustomVariable!);
+    method public boolean getBooleanValue();
+    method public int getColorValue();
+    method public float getFloatValue();
+    method public int getIntegerValue();
+    method public int getInterpolatedColor(float[]!);
+    method public String! getName();
+    method public String! getStringValue();
+    method public int getType();
+    method public float getValueToInterpolate();
+    method public void getValuesToInterpolate(float[]!);
+    method public static int hsvToRgb(float, float, float);
+    method public boolean isContinuous();
+    method public int numberOfInterpolatedValues();
+    method public static int rgbaTocColor(float, float, float, float);
+    method public void setBooleanValue(boolean);
+    method public void setFloatValue(float);
+    method public void setIntValue(int);
+    method public void setInterpolatedValue(androidx.constraintlayout.core.motion.MotionWidget!, float[]!);
+    method public void setStringValue(String!);
+    method public void setValue(float[]!);
+    method public void setValue(Object!);
+  }
+
+  public class Motion implements androidx.constraintlayout.core.motion.utils.TypedValues {
+    ctor public Motion(androidx.constraintlayout.core.motion.MotionWidget!);
+    method public void addKey(androidx.constraintlayout.core.motion.key.MotionKey!);
+    method public int buildKeyFrames(float[]!, int[]!, int[]!);
+    method public void buildPath(float[]!, int);
+    method public void buildRect(float, float[]!, int);
+    method public String! getAnimateRelativeTo();
+    method public void getCenter(double, float[]!, float[]!);
+    method public float getCenterX();
+    method public float getCenterY();
+    method public void getDpDt(float, float, float, float[]!);
+    method public int getDrawPath();
+    method public float getFinalHeight();
+    method public float getFinalWidth();
+    method public float getFinalX();
+    method public float getFinalY();
+    method public int getId(String!);
+    method public androidx.constraintlayout.core.motion.MotionPaths! getKeyFrame(int);
+    method public int getKeyFrameInfo(int, int[]!);
+    method public int getKeyFramePositions(int[]!, float[]!);
+    method public float getMotionStagger();
+    method public float getStartHeight();
+    method public float getStartWidth();
+    method public float getStartX();
+    method public float getStartY();
+    method public int getTransformPivotTarget();
+    method public androidx.constraintlayout.core.motion.MotionWidget! getView();
+    method public boolean interpolate(androidx.constraintlayout.core.motion.MotionWidget!, float, long, androidx.constraintlayout.core.motion.utils.KeyCache!);
+    method public void setDrawPath(int);
+    method public void setEnd(androidx.constraintlayout.core.motion.MotionWidget!);
+    method public void setIdString(String!);
+    method public void setPathMotionArc(int);
+    method public void setStaggerOffset(float);
+    method public void setStaggerScale(float);
+    method public void setStart(androidx.constraintlayout.core.motion.MotionWidget!);
+    method public void setStartState(androidx.constraintlayout.core.motion.utils.ViewState!, androidx.constraintlayout.core.motion.MotionWidget!, int, int, int);
+    method public void setTransformPivotTarget(int);
+    method public boolean setValue(int, boolean);
+    method public boolean setValue(int, float);
+    method public boolean setValue(int, int);
+    method public boolean setValue(int, String!);
+    method public void setView(androidx.constraintlayout.core.motion.MotionWidget!);
+    method public void setup(int, int, float, long);
+    method public void setupRelative(androidx.constraintlayout.core.motion.Motion!);
+    field public static final int DRAW_PATH_AS_CONFIGURED = 4; // 0x4
+    field public static final int DRAW_PATH_BASIC = 1; // 0x1
+    field public static final int DRAW_PATH_CARTESIAN = 3; // 0x3
+    field public static final int DRAW_PATH_NONE = 0; // 0x0
+    field public static final int DRAW_PATH_RECTANGLE = 5; // 0x5
+    field public static final int DRAW_PATH_RELATIVE = 2; // 0x2
+    field public static final int DRAW_PATH_SCREEN = 6; // 0x6
+    field public static final int HORIZONTAL_PATH_X = 2; // 0x2
+    field public static final int HORIZONTAL_PATH_Y = 3; // 0x3
+    field public static final int PATH_PERCENT = 0; // 0x0
+    field public static final int PATH_PERPENDICULAR = 1; // 0x1
+    field public static final int ROTATION_LEFT = 2; // 0x2
+    field public static final int ROTATION_RIGHT = 1; // 0x1
+    field public static final int VERTICAL_PATH_X = 4; // 0x4
+    field public static final int VERTICAL_PATH_Y = 5; // 0x5
+    field public String! mId;
+  }
+
+  public class MotionPaths implements java.lang.Comparable<androidx.constraintlayout.core.motion.MotionPaths!> {
+    ctor public MotionPaths();
+    ctor public MotionPaths(int, int, androidx.constraintlayout.core.motion.key.MotionKeyPosition!, androidx.constraintlayout.core.motion.MotionPaths!, androidx.constraintlayout.core.motion.MotionPaths!);
+    method public void applyParameters(androidx.constraintlayout.core.motion.MotionWidget!);
+    method public int compareTo(androidx.constraintlayout.core.motion.MotionPaths!);
+    method public void configureRelativeTo(androidx.constraintlayout.core.motion.Motion!);
+    method public void setupRelative(androidx.constraintlayout.core.motion.Motion!, androidx.constraintlayout.core.motion.MotionPaths!);
+    field public static final int CARTESIAN = 0; // 0x0
+    field public static final boolean DEBUG = false;
+    field public static final boolean OLD_WAY = false;
+    field public static final int PERPENDICULAR = 1; // 0x1
+    field public static final int SCREEN = 2; // 0x2
+    field public static final String TAG = "MotionPaths";
+    field public String! mId;
+  }
+
+  public class MotionWidget implements androidx.constraintlayout.core.motion.utils.TypedValues {
+    ctor public MotionWidget();
+    ctor public MotionWidget(androidx.constraintlayout.core.state.WidgetFrame!);
+    method public androidx.constraintlayout.core.motion.MotionWidget! findViewById(int);
+    method public float getAlpha();
+    method public int getBottom();
+    method public androidx.constraintlayout.core.motion.CustomVariable! getCustomAttribute(String!);
+    method public java.util.Set<java.lang.String!>! getCustomAttributeNames();
+    method public int getHeight();
+    method public int getId(String!);
+    method public int getLeft();
+    method public String! getName();
+    method public androidx.constraintlayout.core.motion.MotionWidget! getParent();
+    method public float getPivotX();
+    method public float getPivotY();
+    method public int getRight();
+    method public float getRotationX();
+    method public float getRotationY();
+    method public float getRotationZ();
+    method public float getScaleX();
+    method public float getScaleY();
+    method public int getTop();
+    method public float getTranslationX();
+    method public float getTranslationY();
+    method public float getTranslationZ();
+    method public float getValueAttributes(int);
+    method public int getVisibility();
+    method public androidx.constraintlayout.core.state.WidgetFrame! getWidgetFrame();
+    method public int getWidth();
+    method public int getX();
+    method public int getY();
+    method public void layout(int, int, int, int);
+    method public void setBounds(int, int, int, int);
+    method public void setCustomAttribute(String!, int, boolean);
+    method public void setCustomAttribute(String!, int, float);
+    method public void setCustomAttribute(String!, int, int);
+    method public void setCustomAttribute(String!, int, String!);
+    method public void setInterpolatedValue(androidx.constraintlayout.core.motion.CustomAttribute!, float[]!);
+    method public void setPivotX(float);
+    method public void setPivotY(float);
+    method public void setRotationX(float);
+    method public void setRotationY(float);
+    method public void setRotationZ(float);
+    method public void setScaleX(float);
+    method public void setScaleY(float);
+    method public void setTranslationX(float);
+    method public void setTranslationY(float);
+    method public void setTranslationZ(float);
+    method public boolean setValue(int, boolean);
+    method public boolean setValue(int, float);
+    method public boolean setValue(int, int);
+    method public boolean setValue(int, String!);
+    method public boolean setValueAttributes(int, float);
+    method public boolean setValueMotion(int, float);
+    method public boolean setValueMotion(int, int);
+    method public boolean setValueMotion(int, String!);
+    method public void setVisibility(int);
+    method public void updateMotion(androidx.constraintlayout.core.motion.utils.TypedValues!);
+    field public static final int FILL_PARENT = -1; // 0xffffffff
+    field public static final int GONE_UNSET = -2147483648; // 0x80000000
+    field public static final int INVISIBLE = 0; // 0x0
+    field public static final int MATCH_CONSTRAINT = 0; // 0x0
+    field public static final int MATCH_CONSTRAINT_WRAP = 1; // 0x1
+    field public static final int MATCH_PARENT = -1; // 0xffffffff
+    field public static final int PARENT_ID = 0; // 0x0
+    field public static final int ROTATE_LEFT_OF_PORTRATE = 4; // 0x4
+    field public static final int ROTATE_NONE = 0; // 0x0
+    field public static final int ROTATE_PORTRATE_OF_LEFT = 2; // 0x2
+    field public static final int ROTATE_PORTRATE_OF_RIGHT = 1; // 0x1
+    field public static final int ROTATE_RIGHT_OF_PORTRATE = 3; // 0x3
+    field public static final int UNSET = -1; // 0xffffffff
+    field public static final int VISIBILITY_MODE_IGNORE = 1; // 0x1
+    field public static final int VISIBILITY_MODE_NORMAL = 0; // 0x0
+    field public static final int VISIBLE = 4; // 0x4
+    field public static final int WRAP_CONTENT = -2; // 0xfffffffe
+  }
+
+  public static class MotionWidget.Motion {
+    ctor public MotionWidget.Motion();
+    field public int mAnimateCircleAngleTo;
+    field public String! mAnimateRelativeTo;
+    field public int mDrawPath;
+    field public float mMotionStagger;
+    field public int mPathMotionArc;
+    field public float mPathRotate;
+    field public int mPolarRelativeTo;
+    field public int mQuantizeInterpolatorID;
+    field public String! mQuantizeInterpolatorString;
+    field public int mQuantizeInterpolatorType;
+    field public float mQuantizeMotionPhase;
+    field public int mQuantizeMotionSteps;
+    field public String! mTransitionEasing;
+  }
+
+  public static class MotionWidget.PropertySet {
+    ctor public MotionWidget.PropertySet();
+    field public float alpha;
+    field public float mProgress;
+    field public int mVisibilityMode;
+    field public int visibility;
+  }
+
+}
+
+package androidx.constraintlayout.core.motion.key {
+
+  public class MotionConstraintSet {
+    ctor public MotionConstraintSet();
+    field public static final int ROTATE_LEFT_OF_PORTRATE = 4; // 0x4
+    field public static final int ROTATE_NONE = 0; // 0x0
+    field public static final int ROTATE_PORTRATE_OF_LEFT = 2; // 0x2
+    field public static final int ROTATE_PORTRATE_OF_RIGHT = 1; // 0x1
+    field public static final int ROTATE_RIGHT_OF_PORTRATE = 3; // 0x3
+    field public String! mIdString;
+    field public int mRotate;
+  }
+
+  public abstract class MotionKey implements androidx.constraintlayout.core.motion.utils.TypedValues {
+    ctor public MotionKey();
+    method public abstract void addValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.core.motion.utils.SplineSet!>!);
+    method public abstract androidx.constraintlayout.core.motion.key.MotionKey! clone();
+    method public androidx.constraintlayout.core.motion.key.MotionKey! copy(androidx.constraintlayout.core.motion.key.MotionKey!);
+    method public abstract void getAttributeNames(java.util.HashSet<java.lang.String!>!);
+    method public int getFramePosition();
+    method public void setCustomAttribute(String!, int, boolean);
+    method public void setCustomAttribute(String!, int, float);
+    method public void setCustomAttribute(String!, int, int);
+    method public void setCustomAttribute(String!, int, String!);
+    method public void setFramePosition(int);
+    method public void setInterpolation(java.util.HashMap<java.lang.String!,java.lang.Integer!>!);
+    method public boolean setValue(int, boolean);
+    method public boolean setValue(int, float);
+    method public boolean setValue(int, int);
+    method public boolean setValue(int, String!);
+    method public androidx.constraintlayout.core.motion.key.MotionKey! setViewId(int);
+    field public static final String ALPHA = "alpha";
+    field public static final String CUSTOM = "CUSTOM";
+    field public static final String ELEVATION = "elevation";
+    field public static final String ROTATION = "rotationZ";
+    field public static final String ROTATION_X = "rotationX";
+    field public static final String SCALE_X = "scaleX";
+    field public static final String SCALE_Y = "scaleY";
+    field public static final String TRANSITION_PATH_ROTATE = "transitionPathRotate";
+    field public static final String TRANSLATION_X = "translationX";
+    field public static final String TRANSLATION_Y = "translationY";
+    field public static int UNSET;
+    field public static final String VISIBILITY = "visibility";
+    field public java.util.HashMap<java.lang.String!,androidx.constraintlayout.core.motion.CustomVariable!>! mCustom;
+    field public int mFramePosition;
+    field public int mType;
+  }
+
+  public class MotionKeyAttributes extends androidx.constraintlayout.core.motion.key.MotionKey {
+    ctor public MotionKeyAttributes();
+    method public void addValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.core.motion.utils.SplineSet!>!);
+    method public androidx.constraintlayout.core.motion.key.MotionKey! clone();
+    method public void getAttributeNames(java.util.HashSet<java.lang.String!>!);
+    method public int getCurveFit();
+    method public int getId(String!);
+    method public void printAttributes();
+    field public static final int KEY_TYPE = 1; // 0x1
+  }
+
+  public class MotionKeyCycle extends androidx.constraintlayout.core.motion.key.MotionKey {
+    ctor public MotionKeyCycle();
+    method public void addCycleValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.core.motion.utils.KeyCycleOscillator!>!);
+    method public void addValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.core.motion.utils.SplineSet!>!);
+    method public androidx.constraintlayout.core.motion.key.MotionKey! clone();
+    method public void dump();
+    method public void getAttributeNames(java.util.HashSet<java.lang.String!>!);
+    method public int getId(String!);
+    method public float getValue(String!);
+    method public void printAttributes();
+    field public static final int KEY_TYPE = 4; // 0x4
+    field public static final int SHAPE_BOUNCE = 6; // 0x6
+    field public static final int SHAPE_COS_WAVE = 5; // 0x5
+    field public static final int SHAPE_REVERSE_SAW_WAVE = 4; // 0x4
+    field public static final int SHAPE_SAW_WAVE = 3; // 0x3
+    field public static final int SHAPE_SIN_WAVE = 0; // 0x0
+    field public static final int SHAPE_SQUARE_WAVE = 1; // 0x1
+    field public static final int SHAPE_TRIANGLE_WAVE = 2; // 0x2
+    field public static final String WAVE_OFFSET = "waveOffset";
+    field public static final String WAVE_PERIOD = "wavePeriod";
+    field public static final String WAVE_PHASE = "wavePhase";
+    field public static final String WAVE_SHAPE = "waveShape";
+  }
+
+  public class MotionKeyPosition extends androidx.constraintlayout.core.motion.key.MotionKey {
+    ctor public MotionKeyPosition();
+    method public void addValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.core.motion.utils.SplineSet!>!);
+    method public androidx.constraintlayout.core.motion.key.MotionKey! clone();
+    method public void getAttributeNames(java.util.HashSet<java.lang.String!>!);
+    method public int getId(String!);
+    method public boolean intersects(int, int, androidx.constraintlayout.core.motion.utils.FloatRect!, androidx.constraintlayout.core.motion.utils.FloatRect!, float, float);
+    method public void positionAttributes(androidx.constraintlayout.core.motion.MotionWidget!, androidx.constraintlayout.core.motion.utils.FloatRect!, androidx.constraintlayout.core.motion.utils.FloatRect!, float, float, String![]!, float[]!);
+    field protected static final float SELECTION_SLOPE = 20.0f;
+    field public static final int TYPE_CARTESIAN = 0; // 0x0
+    field public static final int TYPE_PATH = 1; // 0x1
+    field public static final int TYPE_SCREEN = 2; // 0x2
+    field public float mAltPercentX;
+    field public float mAltPercentY;
+    field public int mCurveFit;
+    field public int mDrawPath;
+    field public int mPathMotionArc;
+    field public float mPercentHeight;
+    field public float mPercentWidth;
+    field public float mPercentX;
+    field public float mPercentY;
+    field public int mPositionType;
+    field public String! mTransitionEasing;
+  }
+
+  public class MotionKeyTimeCycle extends androidx.constraintlayout.core.motion.key.MotionKey {
+    ctor public MotionKeyTimeCycle();
+    method public void addTimeValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.core.motion.utils.TimeCycleSplineSet!>!);
+    method public void addValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.core.motion.utils.SplineSet!>!);
+    method public androidx.constraintlayout.core.motion.key.MotionKey! clone();
+    method public androidx.constraintlayout.core.motion.key.MotionKeyTimeCycle! copy(androidx.constraintlayout.core.motion.key.MotionKey!);
+    method public void getAttributeNames(java.util.HashSet<java.lang.String!>!);
+    method public int getId(String!);
+    field public static final int KEY_TYPE = 3; // 0x3
+  }
+
+  public class MotionKeyTrigger extends androidx.constraintlayout.core.motion.key.MotionKey {
+    ctor public MotionKeyTrigger();
+    method public void addValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.core.motion.utils.SplineSet!>!);
+    method public androidx.constraintlayout.core.motion.key.MotionKey! clone();
+    method public void conditionallyFire(float, androidx.constraintlayout.core.motion.MotionWidget!);
+    method public androidx.constraintlayout.core.motion.key.MotionKeyTrigger! copy(androidx.constraintlayout.core.motion.key.MotionKey!);
+    method public void getAttributeNames(java.util.HashSet<java.lang.String!>!);
+    method public int getId(String!);
+    field public static final String CROSS = "CROSS";
+    field public static final int KEY_TYPE = 5; // 0x5
+    field public static final String NEGATIVE_CROSS = "negativeCross";
+    field public static final String POSITIVE_CROSS = "positiveCross";
+    field public static final String POST_LAYOUT = "postLayout";
+    field public static final String TRIGGER_COLLISION_ID = "triggerCollisionId";
+    field public static final String TRIGGER_COLLISION_VIEW = "triggerCollisionView";
+    field public static final String TRIGGER_ID = "triggerID";
+    field public static final String TRIGGER_RECEIVER = "triggerReceiver";
+    field public static final String TRIGGER_SLACK = "triggerSlack";
+    field public static final int TYPE_CROSS = 312; // 0x138
+    field public static final int TYPE_NEGATIVE_CROSS = 310; // 0x136
+    field public static final int TYPE_POSITIVE_CROSS = 309; // 0x135
+    field public static final int TYPE_POST_LAYOUT = 304; // 0x130
+    field public static final int TYPE_TRIGGER_COLLISION_ID = 307; // 0x133
+    field public static final int TYPE_TRIGGER_COLLISION_VIEW = 306; // 0x132
+    field public static final int TYPE_TRIGGER_ID = 308; // 0x134
+    field public static final int TYPE_TRIGGER_RECEIVER = 311; // 0x137
+    field public static final int TYPE_TRIGGER_SLACK = 305; // 0x131
+    field public static final int TYPE_VIEW_TRANSITION_ON_CROSS = 301; // 0x12d
+    field public static final int TYPE_VIEW_TRANSITION_ON_NEGATIVE_CROSS = 303; // 0x12f
+    field public static final int TYPE_VIEW_TRANSITION_ON_POSITIVE_CROSS = 302; // 0x12e
+    field public static final String VIEW_TRANSITION_ON_CROSS = "viewTransitionOnCross";
+    field public static final String VIEW_TRANSITION_ON_NEGATIVE_CROSS = "viewTransitionOnNegativeCross";
+    field public static final String VIEW_TRANSITION_ON_POSITIVE_CROSS = "viewTransitionOnPositiveCross";
+  }
+
+}
+
+package androidx.constraintlayout.core.motion.parse {
+
+  public class KeyParser {
+    ctor public KeyParser();
+    method public static void main(String![]!);
+    method public static androidx.constraintlayout.core.motion.utils.TypedBundle! parseAttributes(String!);
+  }
+
+}
+
+package androidx.constraintlayout.core.motion.utils {
+
+  public class ArcCurveFit extends androidx.constraintlayout.core.motion.utils.CurveFit {
+    ctor public ArcCurveFit(int[]!, double[]!, double[]![]!);
+    method public void getPos(double, double[]!);
+    method public void getPos(double, float[]!);
+    method public double getPos(double, int);
+    method public void getSlope(double, double[]!);
+    method public double getSlope(double, int);
+    method public double[]! getTimePoints();
+    field public static final int ARC_ABOVE = 5; // 0x5
+    field public static final int ARC_BELOW = 4; // 0x4
+    field public static final int ARC_START_FLIP = 3; // 0x3
+    field public static final int ARC_START_HORIZONTAL = 2; // 0x2
+    field public static final int ARC_START_LINEAR = 0; // 0x0
+    field public static final int ARC_START_VERTICAL = 1; // 0x1
+  }
+
+  public abstract class CurveFit {
+    ctor public CurveFit();
+    method public static androidx.constraintlayout.core.motion.utils.CurveFit! get(int, double[]!, double[]![]!);
+    method public static androidx.constraintlayout.core.motion.utils.CurveFit! getArc(int[]!, double[]!, double[]![]!);
+    method public abstract void getPos(double, double[]!);
+    method public abstract void getPos(double, float[]!);
+    method public abstract double getPos(double, int);
+    method public abstract void getSlope(double, double[]!);
+    method public abstract double getSlope(double, int);
+    method public abstract double[]! getTimePoints();
+    field public static final int CONSTANT = 2; // 0x2
+    field public static final int LINEAR = 1; // 0x1
+    field public static final int SPLINE = 0; // 0x0
+  }
+
+  public interface DifferentialInterpolator {
+    method public float getInterpolation(float);
+    method public float getVelocity();
+  }
+
+  public class Easing {
+    ctor public Easing();
+    method public double get(double);
+    method public double getDiff(double);
+    method public static androidx.constraintlayout.core.motion.utils.Easing! getInterpolator(String!);
+    field public static String![]! NAMED_EASING;
+  }
+
+  public class FloatRect {
+    ctor public FloatRect();
+    method public final float centerX();
+    method public final float centerY();
+    field public float bottom;
+    field public float left;
+    field public float right;
+    field public float top;
+  }
+
+  public class HyperSpline {
+    ctor public HyperSpline();
+    ctor public HyperSpline(double[]![]!);
+    method public double approxLength(androidx.constraintlayout.core.motion.utils.HyperSpline.Cubic![]!);
+    method public void getPos(double, double[]!);
+    method public void getPos(double, float[]!);
+    method public double getPos(double, int);
+    method public void getVelocity(double, double[]!);
+    method public void setup(double[]![]!);
+  }
+
+  public static class HyperSpline.Cubic {
+    ctor public HyperSpline.Cubic(double, double, double, double);
+    method public double eval(double);
+    method public double vel(double);
+  }
+
+  public class KeyCache {
+    ctor public KeyCache();
+    method public float getFloatValue(Object!, String!, int);
+    method public void setFloatValue(Object!, String!, int, float);
+  }
+
+  public abstract class KeyCycleOscillator {
+    ctor public KeyCycleOscillator();
+    method public float get(float);
+    method public androidx.constraintlayout.core.motion.utils.CurveFit! getCurveFit();
+    method public float getSlope(float);
+    method public static androidx.constraintlayout.core.motion.utils.KeyCycleOscillator! makeWidgetCycle(String!);
+    method protected void setCustom(Object!);
+    method public void setPoint(int, int, String!, int, float, float, float, float);
+    method public void setPoint(int, int, String!, int, float, float, float, float, Object!);
+    method public void setProperty(androidx.constraintlayout.core.motion.MotionWidget!, float);
+    method public void setType(String!);
+    method public void setup(float);
+    method public boolean variesByPath();
+    field public int mVariesBy;
+  }
+
+  public static class KeyCycleOscillator.PathRotateSet extends androidx.constraintlayout.core.motion.utils.KeyCycleOscillator {
+    ctor public KeyCycleOscillator.PathRotateSet(String!);
+    method public void setPathRotate(androidx.constraintlayout.core.motion.MotionWidget!, float, double, double);
+  }
+
+  public class KeyFrameArray {
+    ctor public KeyFrameArray();
+  }
+
+  public static class KeyFrameArray.CustomArray {
+    ctor public KeyFrameArray.CustomArray();
+    method public void append(int, androidx.constraintlayout.core.motion.CustomAttribute!);
+    method public void clear();
+    method public void dump();
+    method public int keyAt(int);
+    method public void remove(int);
+    method public int size();
+    method public androidx.constraintlayout.core.motion.CustomAttribute! valueAt(int);
+  }
+
+  public static class KeyFrameArray.CustomVar {
+    ctor public KeyFrameArray.CustomVar();
+    method public void append(int, androidx.constraintlayout.core.motion.CustomVariable!);
+    method public void clear();
+    method public void dump();
+    method public int keyAt(int);
+    method public void remove(int);
+    method public int size();
+    method public androidx.constraintlayout.core.motion.CustomVariable! valueAt(int);
+  }
+
+  public class LinearCurveFit extends androidx.constraintlayout.core.motion.utils.CurveFit {
+    ctor public LinearCurveFit(double[]!, double[]![]!);
+    method public void getPos(double, double[]!);
+    method public void getPos(double, float[]!);
+    method public double getPos(double, int);
+    method public void getSlope(double, double[]!);
+    method public double getSlope(double, int);
+    method public double[]! getTimePoints();
+  }
+
+  public class MonotonicCurveFit extends androidx.constraintlayout.core.motion.utils.CurveFit {
+    ctor public MonotonicCurveFit(double[]!, double[]![]!);
+    method public static androidx.constraintlayout.core.motion.utils.MonotonicCurveFit! buildWave(String!);
+    method public void getPos(double, double[]!);
+    method public void getPos(double, float[]!);
+    method public double getPos(double, int);
+    method public void getSlope(double, double[]!);
+    method public double getSlope(double, int);
+    method public double[]! getTimePoints();
+  }
+
+  public class Oscillator {
+    ctor public Oscillator();
+    method public void addPoint(double, float);
+    method public double getSlope(double, double, double);
+    method public double getValue(double, double);
+    method public void normalize();
+    method public void setType(int, String!);
+    field public static final int BOUNCE = 6; // 0x6
+    field public static final int COS_WAVE = 5; // 0x5
+    field public static final int CUSTOM = 7; // 0x7
+    field public static final int REVERSE_SAW_WAVE = 4; // 0x4
+    field public static final int SAW_WAVE = 3; // 0x3
+    field public static final int SIN_WAVE = 0; // 0x0
+    field public static final int SQUARE_WAVE = 1; // 0x1
+    field public static String! TAG;
+    field public static final int TRIANGLE_WAVE = 2; // 0x2
+  }
+
+  public class Rect {
+    ctor public Rect();
+    method public int height();
+    method public int width();
+    field public int bottom;
+    field public int left;
+    field public int right;
+    field public int top;
+  }
+
+  public class Schlick extends androidx.constraintlayout.core.motion.utils.Easing {
+  }
+
+  public abstract class SplineSet {
+    ctor public SplineSet();
+    method public float get(float);
+    method public androidx.constraintlayout.core.motion.utils.CurveFit! getCurveFit();
+    method public float getSlope(float);
+    method public static androidx.constraintlayout.core.motion.utils.SplineSet! makeCustomSpline(String!, androidx.constraintlayout.core.motion.utils.KeyFrameArray.CustomArray!);
+    method public static androidx.constraintlayout.core.motion.utils.SplineSet! makeCustomSplineSet(String!, androidx.constraintlayout.core.motion.utils.KeyFrameArray.CustomVar!);
+    method public static androidx.constraintlayout.core.motion.utils.SplineSet! makeSpline(String!, long);
+    method public void setPoint(int, float);
+    method public void setProperty(androidx.constraintlayout.core.motion.utils.TypedValues!, float);
+    method public void setType(String!);
+    method public void setup(int);
+    field protected androidx.constraintlayout.core.motion.utils.CurveFit! mCurveFit;
+    field protected int[]! mTimePoints;
+    field protected float[]! mValues;
+  }
+
+  public static class SplineSet.CustomSet extends androidx.constraintlayout.core.motion.utils.SplineSet {
+    ctor public SplineSet.CustomSet(String!, androidx.constraintlayout.core.motion.utils.KeyFrameArray.CustomArray!);
+    method public void setPoint(int, androidx.constraintlayout.core.motion.CustomAttribute!);
+    method public void setProperty(androidx.constraintlayout.core.state.WidgetFrame!, float);
+  }
+
+  public static class SplineSet.CustomSpline extends androidx.constraintlayout.core.motion.utils.SplineSet {
+    ctor public SplineSet.CustomSpline(String!, androidx.constraintlayout.core.motion.utils.KeyFrameArray.CustomVar!);
+    method public void setPoint(int, androidx.constraintlayout.core.motion.CustomVariable!);
+    method public void setProperty(androidx.constraintlayout.core.motion.MotionWidget!, float);
+  }
+
+  public class SpringStopEngine implements androidx.constraintlayout.core.motion.utils.StopEngine {
+    ctor public SpringStopEngine();
+    method public String! debug(String!, float);
+    method public float getAcceleration();
+    method public float getInterpolation(float);
+    method public float getVelocity();
+    method public float getVelocity(float);
+    method public boolean isStopped();
+    method public void springConfig(float, float, float, float, float, float, float, int);
+  }
+
+  public class StepCurve extends androidx.constraintlayout.core.motion.utils.Easing {
+  }
+
+  public interface StopEngine {
+    method public String! debug(String!, float);
+    method public float getInterpolation(float);
+    method public float getVelocity();
+    method public float getVelocity(float);
+    method public boolean isStopped();
+  }
+
+  public class StopLogicEngine implements androidx.constraintlayout.core.motion.utils.StopEngine {
+    ctor public StopLogicEngine();
+    method public void config(float, float, float, float, float, float);
+    method public String! debug(String!, float);
+    method public float getInterpolation(float);
+    method public float getVelocity();
+    method public float getVelocity(float);
+    method public boolean isStopped();
+  }
+
+  public static class StopLogicEngine.Decelerate implements androidx.constraintlayout.core.motion.utils.StopEngine {
+    ctor public StopLogicEngine.Decelerate();
+    method public void config(float, float, float);
+    method public String! debug(String!, float);
+    method public float getInterpolation(float);
+    method public float getVelocity();
+    method public float getVelocity(float);
+    method public boolean isStopped();
+  }
+
+  public abstract class TimeCycleSplineSet {
+    ctor public TimeCycleSplineSet();
+    method protected float calcWave(float);
+    method public androidx.constraintlayout.core.motion.utils.CurveFit! getCurveFit();
+    method public void setPoint(int, float, float, int, float);
+    method protected void setStartTime(long);
+    method public void setType(String!);
+    method public void setup(int);
+    field protected static final int CURVE_OFFSET = 2; // 0x2
+    field protected static final int CURVE_PERIOD = 1; // 0x1
+    field protected static final int CURVE_VALUE = 0; // 0x0
+    field protected float[]! mCache;
+    field protected boolean mContinue;
+    field protected int mCount;
+    field protected androidx.constraintlayout.core.motion.utils.CurveFit! mCurveFit;
+    field protected float mLastCycle;
+    field protected long mLastTime;
+    field protected int[]! mTimePoints;
+    field protected String! mType;
+    field protected float[]![]! mValues;
+    field protected int mWaveShape;
+    field protected static float sVal2PI;
+  }
+
+  public static class TimeCycleSplineSet.CustomSet extends androidx.constraintlayout.core.motion.utils.TimeCycleSplineSet {
+    ctor public TimeCycleSplineSet.CustomSet(String!, androidx.constraintlayout.core.motion.utils.KeyFrameArray.CustomArray!);
+    method public void setPoint(int, androidx.constraintlayout.core.motion.CustomAttribute!, float, int, float);
+    method public boolean setProperty(androidx.constraintlayout.core.motion.MotionWidget!, float, long, androidx.constraintlayout.core.motion.utils.KeyCache!);
+  }
+
+  public static class TimeCycleSplineSet.CustomVarSet extends androidx.constraintlayout.core.motion.utils.TimeCycleSplineSet {
+    ctor public TimeCycleSplineSet.CustomVarSet(String!, androidx.constraintlayout.core.motion.utils.KeyFrameArray.CustomVar!);
+    method public void setPoint(int, androidx.constraintlayout.core.motion.CustomVariable!, float, int, float);
+    method public boolean setProperty(androidx.constraintlayout.core.motion.MotionWidget!, float, long, androidx.constraintlayout.core.motion.utils.KeyCache!);
+  }
+
+  protected static class TimeCycleSplineSet.Sort {
+    ctor protected TimeCycleSplineSet.Sort();
+  }
+
+  public class TypedBundle {
+    ctor public TypedBundle();
+    method public void add(int, boolean);
+    method public void add(int, float);
+    method public void add(int, int);
+    method public void add(int, String!);
+    method public void addIfNotNull(int, String!);
+    method public void applyDelta(androidx.constraintlayout.core.motion.utils.TypedBundle!);
+    method public void applyDelta(androidx.constraintlayout.core.motion.utils.TypedValues!);
+    method public void clear();
+    method public int getInteger(int);
+  }
+
+  public interface TypedValues {
+    method public int getId(String!);
+    method public boolean setValue(int, boolean);
+    method public boolean setValue(int, float);
+    method public boolean setValue(int, int);
+    method public boolean setValue(int, String!);
+    field public static final int BOOLEAN_MASK = 1; // 0x1
+    field public static final int FLOAT_MASK = 4; // 0x4
+    field public static final int INT_MASK = 2; // 0x2
+    field public static final int STRING_MASK = 8; // 0x8
+    field public static final String S_CUSTOM = "CUSTOM";
+    field public static final int TYPE_FRAME_POSITION = 100; // 0x64
+    field public static final int TYPE_TARGET = 101; // 0x65
+  }
+
+  public static interface TypedValues.AttributesType {
+    method public static int getId(String!);
+    method public static int getType(int);
+    field public static final String![]! KEY_WORDS;
+    field public static final String NAME = "KeyAttributes";
+    field public static final String S_ALPHA = "alpha";
+    field public static final String S_CURVE_FIT = "curveFit";
+    field public static final String S_CUSTOM = "CUSTOM";
+    field public static final String S_EASING = "easing";
+    field public static final String S_ELEVATION = "elevation";
+    field public static final String S_FRAME = "frame";
+    field public static final String S_PATH_ROTATE = "pathRotate";
+    field public static final String S_PIVOT_TARGET = "pivotTarget";
+    field public static final String S_PIVOT_X = "pivotX";
+    field public static final String S_PIVOT_Y = "pivotY";
+    field public static final String S_PROGRESS = "progress";
+    field public static final String S_ROTATION_X = "rotationX";
+    field public static final String S_ROTATION_Y = "rotationY";
+    field public static final String S_ROTATION_Z = "rotationZ";
+    field public static final String S_SCALE_X = "scaleX";
+    field public static final String S_SCALE_Y = "scaleY";
+    field public static final String S_TARGET = "target";
+    field public static final String S_TRANSLATION_X = "translationX";
+    field public static final String S_TRANSLATION_Y = "translationY";
+    field public static final String S_TRANSLATION_Z = "translationZ";
+    field public static final String S_VISIBILITY = "visibility";
+    field public static final int TYPE_ALPHA = 303; // 0x12f
+    field public static final int TYPE_CURVE_FIT = 301; // 0x12d
+    field public static final int TYPE_EASING = 317; // 0x13d
+    field public static final int TYPE_ELEVATION = 307; // 0x133
+    field public static final int TYPE_PATH_ROTATE = 316; // 0x13c
+    field public static final int TYPE_PIVOT_TARGET = 318; // 0x13e
+    field public static final int TYPE_PIVOT_X = 313; // 0x139
+    field public static final int TYPE_PIVOT_Y = 314; // 0x13a
+    field public static final int TYPE_PROGRESS = 315; // 0x13b
+    field public static final int TYPE_ROTATION_X = 308; // 0x134
+    field public static final int TYPE_ROTATION_Y = 309; // 0x135
+    field public static final int TYPE_ROTATION_Z = 310; // 0x136
+    field public static final int TYPE_SCALE_X = 311; // 0x137
+    field public static final int TYPE_SCALE_Y = 312; // 0x138
+    field public static final int TYPE_TRANSLATION_X = 304; // 0x130
+    field public static final int TYPE_TRANSLATION_Y = 305; // 0x131
+    field public static final int TYPE_TRANSLATION_Z = 306; // 0x132
+    field public static final int TYPE_VISIBILITY = 302; // 0x12e
+  }
+
+  public static interface TypedValues.Custom {
+    method public static int getId(String!);
+    field public static final String![]! KEY_WORDS;
+    field public static final String NAME = "Custom";
+    field public static final String S_BOOLEAN = "boolean";
+    field public static final String S_COLOR = "color";
+    field public static final String S_DIMENSION = "dimension";
+    field public static final String S_FLOAT = "float";
+    field public static final String S_INT = "integer";
+    field public static final String S_REFERENCE = "reference";
+    field public static final String S_STRING = "string";
+    field public static final int TYPE_BOOLEAN = 904; // 0x388
+    field public static final int TYPE_COLOR = 902; // 0x386
+    field public static final int TYPE_DIMENSION = 905; // 0x389
+    field public static final int TYPE_FLOAT = 901; // 0x385
+    field public static final int TYPE_INT = 900; // 0x384
+    field public static final int TYPE_REFERENCE = 906; // 0x38a
+    field public static final int TYPE_STRING = 903; // 0x387
+  }
+
+  public static interface TypedValues.CycleType {
+    method public static int getId(String!);
+    method public static int getType(int);
+    field public static final String![]! KEY_WORDS;
+    field public static final String NAME = "KeyCycle";
+    field public static final String S_ALPHA = "alpha";
+    field public static final String S_CURVE_FIT = "curveFit";
+    field public static final String S_CUSTOM_WAVE_SHAPE = "customWave";
+    field public static final String S_EASING = "easing";
+    field public static final String S_ELEVATION = "elevation";
+    field public static final String S_PATH_ROTATE = "pathRotate";
+    field public static final String S_PIVOT_X = "pivotX";
+    field public static final String S_PIVOT_Y = "pivotY";
+    field public static final String S_PROGRESS = "progress";
+    field public static final String S_ROTATION_X = "rotationX";
+    field public static final String S_ROTATION_Y = "rotationY";
+    field public static final String S_ROTATION_Z = "rotationZ";
+    field public static final String S_SCALE_X = "scaleX";
+    field public static final String S_SCALE_Y = "scaleY";
+    field public static final String S_TRANSLATION_X = "translationX";
+    field public static final String S_TRANSLATION_Y = "translationY";
+    field public static final String S_TRANSLATION_Z = "translationZ";
+    field public static final String S_VISIBILITY = "visibility";
+    field public static final String S_WAVE_OFFSET = "offset";
+    field public static final String S_WAVE_PERIOD = "period";
+    field public static final String S_WAVE_PHASE = "phase";
+    field public static final String S_WAVE_SHAPE = "waveShape";
+    field public static final int TYPE_ALPHA = 403; // 0x193
+    field public static final int TYPE_CURVE_FIT = 401; // 0x191
+    field public static final int TYPE_CUSTOM_WAVE_SHAPE = 422; // 0x1a6
+    field public static final int TYPE_EASING = 420; // 0x1a4
+    field public static final int TYPE_ELEVATION = 307; // 0x133
+    field public static final int TYPE_PATH_ROTATE = 416; // 0x1a0
+    field public static final int TYPE_PIVOT_X = 313; // 0x139
+    field public static final int TYPE_PIVOT_Y = 314; // 0x13a
+    field public static final int TYPE_PROGRESS = 315; // 0x13b
+    field public static final int TYPE_ROTATION_X = 308; // 0x134
+    field public static final int TYPE_ROTATION_Y = 309; // 0x135
+    field public static final int TYPE_ROTATION_Z = 310; // 0x136
+    field public static final int TYPE_SCALE_X = 311; // 0x137
+    field public static final int TYPE_SCALE_Y = 312; // 0x138
+    field public static final int TYPE_TRANSLATION_X = 304; // 0x130
+    field public static final int TYPE_TRANSLATION_Y = 305; // 0x131
+    field public static final int TYPE_TRANSLATION_Z = 306; // 0x132
+    field public static final int TYPE_VISIBILITY = 402; // 0x192
+    field public static final int TYPE_WAVE_OFFSET = 424; // 0x1a8
+    field public static final int TYPE_WAVE_PERIOD = 423; // 0x1a7
+    field public static final int TYPE_WAVE_PHASE = 425; // 0x1a9
+    field public static final int TYPE_WAVE_SHAPE = 421; // 0x1a5
+  }
+
+  public static interface TypedValues.MotionScene {
+    method public static int getId(String!);
+    method public static int getType(int);
+    field public static final String![]! KEY_WORDS;
+    field public static final String NAME = "MotionScene";
+    field public static final String S_DEFAULT_DURATION = "defaultDuration";
+    field public static final String S_LAYOUT_DURING_TRANSITION = "layoutDuringTransition";
+    field public static final int TYPE_DEFAULT_DURATION = 600; // 0x258
+    field public static final int TYPE_LAYOUT_DURING_TRANSITION = 601; // 0x259
+  }
+
+  public static interface TypedValues.MotionType {
+    method public static int getId(String!);
+    field public static final String![]! KEY_WORDS;
+    field public static final String NAME = "Motion";
+    field public static final String S_ANIMATE_CIRCLEANGLE_TO = "AnimateCircleAngleTo";
+    field public static final String S_ANIMATE_RELATIVE_TO = "AnimateRelativeTo";
+    field public static final String S_DRAW_PATH = "DrawPath";
+    field public static final String S_EASING = "TransitionEasing";
+    field public static final String S_PATHMOTION_ARC = "PathMotionArc";
+    field public static final String S_PATH_ROTATE = "PathRotate";
+    field public static final String S_POLAR_RELATIVETO = "PolarRelativeTo";
+    field public static final String S_QUANTIZE_INTERPOLATOR = "QuantizeInterpolator";
+    field public static final String S_QUANTIZE_INTERPOLATOR_ID = "QuantizeInterpolatorID";
+    field public static final String S_QUANTIZE_INTERPOLATOR_TYPE = "QuantizeInterpolatorType";
+    field public static final String S_QUANTIZE_MOTIONSTEPS = "QuantizeMotionSteps";
+    field public static final String S_QUANTIZE_MOTION_PHASE = "QuantizeMotionPhase";
+    field public static final String S_STAGGER = "Stagger";
+    field public static final int TYPE_ANIMATE_CIRCLEANGLE_TO = 606; // 0x25e
+    field public static final int TYPE_ANIMATE_RELATIVE_TO = 605; // 0x25d
+    field public static final int TYPE_DRAW_PATH = 608; // 0x260
+    field public static final int TYPE_EASING = 603; // 0x25b
+    field public static final int TYPE_PATHMOTION_ARC = 607; // 0x25f
+    field public static final int TYPE_PATH_ROTATE = 601; // 0x259
+    field public static final int TYPE_POLAR_RELATIVETO = 609; // 0x261
+    field public static final int TYPE_QUANTIZE_INTERPOLATOR = 604; // 0x25c
+    field public static final int TYPE_QUANTIZE_INTERPOLATOR_ID = 612; // 0x264
+    field public static final int TYPE_QUANTIZE_INTERPOLATOR_TYPE = 611; // 0x263
+    field public static final int TYPE_QUANTIZE_MOTIONSTEPS = 610; // 0x262
+    field public static final int TYPE_QUANTIZE_MOTION_PHASE = 602; // 0x25a
+    field public static final int TYPE_STAGGER = 600; // 0x258
+  }
+
+  public static interface TypedValues.OnSwipe {
+    field public static final String AUTOCOMPLETE_MODE = "autocompletemode";
+    field public static final String![]! AUTOCOMPLETE_MODE_ENUM;
+    field public static final String DRAG_DIRECTION = "dragdirection";
+    field public static final String DRAG_SCALE = "dragscale";
+    field public static final String DRAG_THRESHOLD = "dragthreshold";
+    field public static final String LIMIT_BOUNDS_TO = "limitboundsto";
+    field public static final String MAX_ACCELERATION = "maxacceleration";
+    field public static final String MAX_VELOCITY = "maxvelocity";
+    field public static final String MOVE_WHEN_SCROLLAT_TOP = "movewhenscrollattop";
+    field public static final String NESTED_SCROLL_FLAGS = "nestedscrollflags";
+    field public static final String![]! NESTED_SCROLL_FLAGS_ENUM;
+    field public static final String ON_TOUCH_UP = "ontouchup";
+    field public static final String![]! ON_TOUCH_UP_ENUM;
+    field public static final String ROTATION_CENTER_ID = "rotationcenterid";
+    field public static final String SPRINGS_TOP_THRESHOLD = "springstopthreshold";
+    field public static final String SPRING_BOUNDARY = "springboundary";
+    field public static final String![]! SPRING_BOUNDARY_ENUM;
+    field public static final String SPRING_DAMPING = "springdamping";
+    field public static final String SPRING_MASS = "springmass";
+    field public static final String SPRING_STIFFNESS = "springstiffness";
+    field public static final String TOUCH_ANCHOR_ID = "touchanchorid";
+    field public static final String TOUCH_ANCHOR_SIDE = "touchanchorside";
+    field public static final String TOUCH_REGION_ID = "touchregionid";
+  }
+
+  public static interface TypedValues.PositionType {
+    method public static int getId(String!);
+    method public static int getType(int);
+    field public static final String![]! KEY_WORDS;
+    field public static final String NAME = "KeyPosition";
+    field public static final String S_DRAWPATH = "drawPath";
+    field public static final String S_PERCENT_HEIGHT = "percentHeight";
+    field public static final String S_PERCENT_WIDTH = "percentWidth";
+    field public static final String S_PERCENT_X = "percentX";
+    field public static final String S_PERCENT_Y = "percentY";
+    field public static final String S_SIZE_PERCENT = "sizePercent";
+    field public static final String S_TRANSITION_EASING = "transitionEasing";
+    field public static final int TYPE_CURVE_FIT = 508; // 0x1fc
+    field public static final int TYPE_DRAWPATH = 502; // 0x1f6
+    field public static final int TYPE_PATH_MOTION_ARC = 509; // 0x1fd
+    field public static final int TYPE_PERCENT_HEIGHT = 504; // 0x1f8
+    field public static final int TYPE_PERCENT_WIDTH = 503; // 0x1f7
+    field public static final int TYPE_PERCENT_X = 506; // 0x1fa
+    field public static final int TYPE_PERCENT_Y = 507; // 0x1fb
+    field public static final int TYPE_POSITION_TYPE = 510; // 0x1fe
+    field public static final int TYPE_SIZE_PERCENT = 505; // 0x1f9
+    field public static final int TYPE_TRANSITION_EASING = 501; // 0x1f5
+  }
+
+  public static interface TypedValues.TransitionType {
+    method public static int getId(String!);
+    method public static int getType(int);
+    field public static final String![]! KEY_WORDS;
+    field public static final String NAME = "Transitions";
+    field public static final String S_AUTO_TRANSITION = "autoTransition";
+    field public static final String S_DURATION = "duration";
+    field public static final String S_FROM = "from";
+    field public static final String S_INTERPOLATOR = "motionInterpolator";
+    field public static final String S_PATH_MOTION_ARC = "pathMotionArc";
+    field public static final String S_STAGGERED = "staggered";
+    field public static final String S_TO = "to";
+    field public static final String S_TRANSITION_FLAGS = "transitionFlags";
+    field public static final int TYPE_AUTO_TRANSITION = 704; // 0x2c0
+    field public static final int TYPE_DURATION = 700; // 0x2bc
+    field public static final int TYPE_FROM = 701; // 0x2bd
+    field public static final int TYPE_INTERPOLATOR = 705; // 0x2c1
+    field public static final int TYPE_PATH_MOTION_ARC = 509; // 0x1fd
+    field public static final int TYPE_STAGGERED = 706; // 0x2c2
+    field public static final int TYPE_TO = 702; // 0x2be
+    field public static final int TYPE_TRANSITION_FLAGS = 707; // 0x2c3
+  }
+
+  public static interface TypedValues.TriggerType {
+    method public static int getId(String!);
+    field public static final String CROSS = "CROSS";
+    field public static final String![]! KEY_WORDS;
+    field public static final String NAME = "KeyTrigger";
+    field public static final String NEGATIVE_CROSS = "negativeCross";
+    field public static final String POSITIVE_CROSS = "positiveCross";
+    field public static final String POST_LAYOUT = "postLayout";
+    field public static final String TRIGGER_COLLISION_ID = "triggerCollisionId";
+    field public static final String TRIGGER_COLLISION_VIEW = "triggerCollisionView";
+    field public static final String TRIGGER_ID = "triggerID";
+    field public static final String TRIGGER_RECEIVER = "triggerReceiver";
+    field public static final String TRIGGER_SLACK = "triggerSlack";
+    field public static final int TYPE_CROSS = 312; // 0x138
+    field public static final int TYPE_NEGATIVE_CROSS = 310; // 0x136
+    field public static final int TYPE_POSITIVE_CROSS = 309; // 0x135
+    field public static final int TYPE_POST_LAYOUT = 304; // 0x130
+    field public static final int TYPE_TRIGGER_COLLISION_ID = 307; // 0x133
+    field public static final int TYPE_TRIGGER_COLLISION_VIEW = 306; // 0x132
+    field public static final int TYPE_TRIGGER_ID = 308; // 0x134
+    field public static final int TYPE_TRIGGER_RECEIVER = 311; // 0x137
+    field public static final int TYPE_TRIGGER_SLACK = 305; // 0x131
+    field public static final int TYPE_VIEW_TRANSITION_ON_CROSS = 301; // 0x12d
+    field public static final int TYPE_VIEW_TRANSITION_ON_NEGATIVE_CROSS = 303; // 0x12f
+    field public static final int TYPE_VIEW_TRANSITION_ON_POSITIVE_CROSS = 302; // 0x12e
+    field public static final String VIEW_TRANSITION_ON_CROSS = "viewTransitionOnCross";
+    field public static final String VIEW_TRANSITION_ON_NEGATIVE_CROSS = "viewTransitionOnNegativeCross";
+    field public static final String VIEW_TRANSITION_ON_POSITIVE_CROSS = "viewTransitionOnPositiveCross";
+  }
+
+  public class Utils {
+    ctor public Utils();
+    method public int getInterpolatedColor(float[]!);
+    method public static void log(String!);
+    method public static void log(String!, String!);
+    method public static void logStack(String!, int);
+    method public static void loge(String!, String!);
+    method public static int rgbaTocColor(float, float, float, float);
+    method public static void setDebugHandle(androidx.constraintlayout.core.motion.utils.Utils.DebugHandle!);
+    method public static void socketSend(String!);
+  }
+
+  public static interface Utils.DebugHandle {
+    method public void message(String!);
+  }
+
+  public class VelocityMatrix {
+    ctor public VelocityMatrix();
+    method public void applyTransform(float, float, int, int, float[]!);
+    method public void clear();
+    method public void setRotationVelocity(androidx.constraintlayout.core.motion.utils.KeyCycleOscillator!, float);
+    method public void setRotationVelocity(androidx.constraintlayout.core.motion.utils.SplineSet!, float);
+    method public void setScaleVelocity(androidx.constraintlayout.core.motion.utils.KeyCycleOscillator!, androidx.constraintlayout.core.motion.utils.KeyCycleOscillator!, float);
+    method public void setScaleVelocity(androidx.constraintlayout.core.motion.utils.SplineSet!, androidx.constraintlayout.core.motion.utils.SplineSet!, float);
+    method public void setTranslationVelocity(androidx.constraintlayout.core.motion.utils.KeyCycleOscillator!, androidx.constraintlayout.core.motion.utils.KeyCycleOscillator!, float);
+    method public void setTranslationVelocity(androidx.constraintlayout.core.motion.utils.SplineSet!, androidx.constraintlayout.core.motion.utils.SplineSet!, float);
+  }
+
+  public class ViewState {
+    ctor public ViewState();
+    method public void getState(androidx.constraintlayout.core.motion.MotionWidget!);
+    method public int height();
+    method public int width();
+    field public int bottom;
+    field public int left;
+    field public int right;
+    field public float rotation;
+    field public int top;
+  }
+
+}
+
+package androidx.constraintlayout.core.parser {
+
+  public class CLArray extends androidx.constraintlayout.core.parser.CLContainer {
+    ctor public CLArray(char[]!);
+    method public static androidx.constraintlayout.core.parser.CLElement! allocate(char[]!);
+  }
+
+  public class CLContainer extends androidx.constraintlayout.core.parser.CLElement {
+    ctor public CLContainer(char[]!);
+    method public void add(androidx.constraintlayout.core.parser.CLElement!);
+    method public static androidx.constraintlayout.core.parser.CLElement! allocate(char[]!);
+    method public void clear();
+    method public androidx.constraintlayout.core.parser.CLContainer clone();
+    method public androidx.constraintlayout.core.parser.CLElement! get(int) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public androidx.constraintlayout.core.parser.CLElement! get(String!) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public androidx.constraintlayout.core.parser.CLArray! getArray(int) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public androidx.constraintlayout.core.parser.CLArray! getArray(String!) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public androidx.constraintlayout.core.parser.CLArray! getArrayOrCreate(String!);
+    method public androidx.constraintlayout.core.parser.CLArray! getArrayOrNull(String!);
+    method public boolean getBoolean(int) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public boolean getBoolean(String!) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public float getFloat(int) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public float getFloat(String!) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public float getFloatOrNaN(String!);
+    method public int getInt(int) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public int getInt(String!) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public androidx.constraintlayout.core.parser.CLObject! getObject(int) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public androidx.constraintlayout.core.parser.CLObject! getObject(String!) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public androidx.constraintlayout.core.parser.CLObject! getObjectOrNull(String!);
+    method public androidx.constraintlayout.core.parser.CLElement! getOrNull(int);
+    method public androidx.constraintlayout.core.parser.CLElement! getOrNull(String!);
+    method public String! getString(int) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public String! getString(String!) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public String! getStringOrNull(int);
+    method public String! getStringOrNull(String!);
+    method public boolean has(String!);
+    method public java.util.ArrayList<java.lang.String!>! names();
+    method public void put(String!, androidx.constraintlayout.core.parser.CLElement!);
+    method public void putNumber(String!, float);
+    method public void putString(String!, String!);
+    method public void remove(String!);
+    method public int size();
+  }
+
+  public class CLElement implements java.lang.Cloneable {
+    ctor public CLElement(char[]!);
+    method protected void addIndent(StringBuilder!, int);
+    method public androidx.constraintlayout.core.parser.CLElement clone();
+    method public String! content();
+    method public androidx.constraintlayout.core.parser.CLElement! getContainer();
+    method protected String! getDebugName();
+    method public long getEnd();
+    method public float getFloat();
+    method public int getInt();
+    method public int getLine();
+    method public long getStart();
+    method protected String! getStrClass();
+    method public boolean hasContent();
+    method public boolean isDone();
+    method public boolean isStarted();
+    method public boolean notStarted();
+    method public void setContainer(androidx.constraintlayout.core.parser.CLContainer!);
+    method public void setEnd(long);
+    method public void setLine(int);
+    method public void setStart(long);
+    method protected String! toFormattedJSON(int, int);
+    method protected String! toJSON();
+    field protected androidx.constraintlayout.core.parser.CLContainer! mContainer;
+    field protected long mEnd;
+    field protected long mStart;
+    field protected static int sBaseIndent;
+    field protected static int sMaxLine;
+  }
+
+  public class CLKey extends androidx.constraintlayout.core.parser.CLContainer {
+    ctor public CLKey(char[]!);
+    method public static androidx.constraintlayout.core.parser.CLElement! allocate(char[]!);
+    method public static androidx.constraintlayout.core.parser.CLElement! allocate(String!, androidx.constraintlayout.core.parser.CLElement!);
+    method public String! getName();
+    method public androidx.constraintlayout.core.parser.CLElement! getValue();
+    method public void set(androidx.constraintlayout.core.parser.CLElement!);
+  }
+
+  public class CLNumber extends androidx.constraintlayout.core.parser.CLElement {
+    ctor public CLNumber(char[]!);
+    ctor public CLNumber(float);
+    method public static androidx.constraintlayout.core.parser.CLElement! allocate(char[]!);
+    method public boolean isInt();
+    method public void putValue(float);
+  }
+
+  public class CLObject extends androidx.constraintlayout.core.parser.CLContainer implements java.lang.Iterable<androidx.constraintlayout.core.parser.CLKey!> {
+    ctor public CLObject(char[]!);
+    method public static androidx.constraintlayout.core.parser.CLObject! allocate(char[]!);
+    method public androidx.constraintlayout.core.parser.CLObject clone();
+    method public java.util.Iterator<androidx.constraintlayout.core.parser.CLKey!>! iterator();
+    method public String! toFormattedJSON();
+    method public String! toFormattedJSON(int, int);
+    method public String! toJSON();
+  }
+
+  public class CLParser {
+    ctor public CLParser(String!);
+    method public androidx.constraintlayout.core.parser.CLObject! parse() throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public static androidx.constraintlayout.core.parser.CLObject! parse(String!) throws androidx.constraintlayout.core.parser.CLParsingException;
+  }
+
+  public class CLParsingException extends java.lang.Exception {
+    ctor public CLParsingException(String!, androidx.constraintlayout.core.parser.CLElement!);
+    method public String! reason();
+  }
+
+  public class CLString extends androidx.constraintlayout.core.parser.CLElement {
+    ctor public CLString(char[]!);
+    method public static androidx.constraintlayout.core.parser.CLElement! allocate(char[]!);
+    method public static androidx.constraintlayout.core.parser.CLString from(String);
+  }
+
+  public class CLToken extends androidx.constraintlayout.core.parser.CLElement {
+    ctor public CLToken(char[]!);
+    method public static androidx.constraintlayout.core.parser.CLElement! allocate(char[]!);
+    method public boolean getBoolean() throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public androidx.constraintlayout.core.parser.CLToken.Type! getType();
+    method public boolean isNull() throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public boolean validate(char, long);
+  }
+
+}
+
+package androidx.constraintlayout.core.state {
+
+  public class ConstraintReference implements androidx.constraintlayout.core.state.Reference {
+    ctor public ConstraintReference(androidx.constraintlayout.core.state.State!);
+    method public void addCustomColor(String!, int);
+    method public void addCustomFloat(String!, float);
+    method public androidx.constraintlayout.core.state.ConstraintReference! alpha(float);
+    method public void apply();
+    method public void applyWidgetConstraints();
+    method public androidx.constraintlayout.core.state.ConstraintReference! baseline();
+    method public androidx.constraintlayout.core.state.ConstraintReference! baselineToBaseline(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! baselineToBottom(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! baselineToTop(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! bias(float);
+    method public androidx.constraintlayout.core.state.ConstraintReference! bottom();
+    method public androidx.constraintlayout.core.state.ConstraintReference! bottomToBottom(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! bottomToTop(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! centerHorizontally(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! centerVertically(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! circularConstraint(Object!, float, float);
+    method public androidx.constraintlayout.core.state.ConstraintReference! clear();
+    method public androidx.constraintlayout.core.state.ConstraintReference! clearAll();
+    method public androidx.constraintlayout.core.state.ConstraintReference! clearHorizontal();
+    method public androidx.constraintlayout.core.state.ConstraintReference! clearVertical();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! createConstraintWidget();
+    method public androidx.constraintlayout.core.state.ConstraintReference! end();
+    method public androidx.constraintlayout.core.state.ConstraintReference! endToEnd(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! endToStart(Object!);
+    method public float getAlpha();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getConstraintWidget();
+    method public androidx.constraintlayout.core.state.helpers.Facade! getFacade();
+    method public androidx.constraintlayout.core.state.Dimension! getHeight();
+    method public int getHorizontalChainStyle();
+    method public float getHorizontalChainWeight();
+    method public Object! getKey();
+    method public float getPivotX();
+    method public float getPivotY();
+    method public float getRotationX();
+    method public float getRotationY();
+    method public float getRotationZ();
+    method public float getScaleX();
+    method public float getScaleY();
+    method public String! getTag();
+    method public float getTranslationX();
+    method public float getTranslationY();
+    method public float getTranslationZ();
+    method public int getVerticalChainStyle(int);
+    method public float getVerticalChainWeight();
+    method public Object! getView();
+    method public androidx.constraintlayout.core.state.Dimension! getWidth();
+    method public androidx.constraintlayout.core.state.ConstraintReference! height(androidx.constraintlayout.core.state.Dimension!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! horizontalBias(float);
+    method public androidx.constraintlayout.core.state.ConstraintReference! left();
+    method public androidx.constraintlayout.core.state.ConstraintReference! leftToLeft(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! leftToRight(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! margin(int);
+    method public androidx.constraintlayout.core.state.ConstraintReference! margin(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! marginGone(int);
+    method public androidx.constraintlayout.core.state.ConstraintReference! marginGone(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! pivotX(float);
+    method public androidx.constraintlayout.core.state.ConstraintReference! pivotY(float);
+    method public androidx.constraintlayout.core.state.ConstraintReference! right();
+    method public androidx.constraintlayout.core.state.ConstraintReference! rightToLeft(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! rightToRight(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! rotationX(float);
+    method public androidx.constraintlayout.core.state.ConstraintReference! rotationY(float);
+    method public androidx.constraintlayout.core.state.ConstraintReference! rotationZ(float);
+    method public androidx.constraintlayout.core.state.ConstraintReference! scaleX(float);
+    method public androidx.constraintlayout.core.state.ConstraintReference! scaleY(float);
+    method public void setConstraintWidget(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public void setFacade(androidx.constraintlayout.core.state.helpers.Facade!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! setHeight(androidx.constraintlayout.core.state.Dimension!);
+    method public void setHorizontalChainStyle(int);
+    method public void setHorizontalChainWeight(float);
+    method public void setKey(Object!);
+    method public void setTag(String!);
+    method public void setVerticalChainStyle(int);
+    method public void setVerticalChainWeight(float);
+    method public void setView(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! setWidth(androidx.constraintlayout.core.state.Dimension!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! start();
+    method public androidx.constraintlayout.core.state.ConstraintReference! startToEnd(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! startToStart(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! top();
+    method public androidx.constraintlayout.core.state.ConstraintReference! topToBottom(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! topToTop(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! translationX(float);
+    method public androidx.constraintlayout.core.state.ConstraintReference! translationY(float);
+    method public androidx.constraintlayout.core.state.ConstraintReference! translationZ(float);
+    method public void validate() throws java.lang.Exception;
+    method public androidx.constraintlayout.core.state.ConstraintReference! verticalBias(float);
+    method public androidx.constraintlayout.core.state.ConstraintReference! visibility(int);
+    method public androidx.constraintlayout.core.state.ConstraintReference! width(androidx.constraintlayout.core.state.Dimension!);
+    field protected Object! mBottomToBottom;
+    field protected Object! mBottomToTop;
+    field protected Object! mEndToEnd;
+    field protected Object! mEndToStart;
+    field protected float mHorizontalBias;
+    field protected Object! mLeftToLeft;
+    field protected Object! mLeftToRight;
+    field protected int mMarginBottom;
+    field protected int mMarginBottomGone;
+    field protected int mMarginEnd;
+    field protected int mMarginEndGone;
+    field protected int mMarginLeft;
+    field protected int mMarginLeftGone;
+    field protected int mMarginRight;
+    field protected int mMarginRightGone;
+    field protected int mMarginStart;
+    field protected int mMarginStartGone;
+    field protected int mMarginTop;
+    field protected int mMarginTopGone;
+    field protected Object! mRightToLeft;
+    field protected Object! mRightToRight;
+    field protected Object! mStartToEnd;
+    field protected Object! mStartToStart;
+    field protected Object! mTopToBottom;
+    field protected Object! mTopToTop;
+    field protected float mVerticalBias;
+  }
+
+  public static interface ConstraintReference.ConstraintReferenceFactory {
+    method public androidx.constraintlayout.core.state.ConstraintReference! create(androidx.constraintlayout.core.state.State!);
+  }
+
+  public class ConstraintSetParser {
+    ctor public ConstraintSetParser();
+    method public static void parseDesignElementsJSON(String!, java.util.ArrayList<androidx.constraintlayout.core.state.ConstraintSetParser.DesignElement!>!) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public static void parseJSON(String!, androidx.constraintlayout.core.state.State!, androidx.constraintlayout.core.state.ConstraintSetParser.LayoutVariables!) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public static void parseJSON(String!, androidx.constraintlayout.core.state.Transition!, int);
+    method public static void parseMotionSceneJSON(androidx.constraintlayout.core.state.CoreMotionScene!, String!);
+    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public static void populateState(androidx.constraintlayout.core.parser.CLObject, androidx.constraintlayout.core.state.State, androidx.constraintlayout.core.state.ConstraintSetParser.LayoutVariables) throws androidx.constraintlayout.core.parser.CLParsingException;
+  }
+
+  public static class ConstraintSetParser.DesignElement {
+    method public String! getId();
+    method public java.util.HashMap<java.lang.String!,java.lang.String!>! getParams();
+    method public String! getType();
+  }
+
+  public static class ConstraintSetParser.LayoutVariables {
+    ctor public ConstraintSetParser.LayoutVariables();
+    method public void putOverride(String!, float);
+  }
+
+  public enum ConstraintSetParser.MotionLayoutDebugFlags {
+    enum_constant public static final androidx.constraintlayout.core.state.ConstraintSetParser.MotionLayoutDebugFlags NONE;
+    enum_constant public static final androidx.constraintlayout.core.state.ConstraintSetParser.MotionLayoutDebugFlags SHOW_ALL;
+    enum_constant public static final androidx.constraintlayout.core.state.ConstraintSetParser.MotionLayoutDebugFlags UNKNOWN;
+  }
+
+  public interface CoreMotionScene {
+    method public String! getConstraintSet(int);
+    method public String! getConstraintSet(String!);
+    method public String! getTransition(String!);
+    method public void setConstraintSetContent(String!, String!);
+    method public void setDebugName(String!);
+    method public void setTransitionContent(String!, String!);
+  }
+
+  public interface CorePixelDp {
+    method public float toPixels(float);
+  }
+
+  public class Dimension {
+    method public void apply(androidx.constraintlayout.core.state.State!, androidx.constraintlayout.core.widgets.ConstraintWidget!, int);
+    method public static androidx.constraintlayout.core.state.Dimension! createFixed(int);
+    method public static androidx.constraintlayout.core.state.Dimension! createFixed(Object!);
+    method public static androidx.constraintlayout.core.state.Dimension! createParent();
+    method public static androidx.constraintlayout.core.state.Dimension! createPercent(Object!, float);
+    method public static androidx.constraintlayout.core.state.Dimension! createRatio(String!);
+    method public static androidx.constraintlayout.core.state.Dimension! createSpread();
+    method public static androidx.constraintlayout.core.state.Dimension! createSuggested(int);
+    method public static androidx.constraintlayout.core.state.Dimension! createSuggested(Object!);
+    method public static androidx.constraintlayout.core.state.Dimension! createWrap();
+    method public boolean equalsFixedValue(int);
+    method public androidx.constraintlayout.core.state.Dimension! fixed(int);
+    method public androidx.constraintlayout.core.state.Dimension! fixed(Object!);
+    method public androidx.constraintlayout.core.state.Dimension! max(int);
+    method public androidx.constraintlayout.core.state.Dimension! max(Object!);
+    method public androidx.constraintlayout.core.state.Dimension! min(int);
+    method public androidx.constraintlayout.core.state.Dimension! min(Object!);
+    method public androidx.constraintlayout.core.state.Dimension! percent(Object!, float);
+    method public androidx.constraintlayout.core.state.Dimension! ratio(String!);
+    method public androidx.constraintlayout.core.state.Dimension! suggested(int);
+    method public androidx.constraintlayout.core.state.Dimension! suggested(Object!);
+    field public static final Object! FIXED_DIMENSION;
+    field public static final Object! PARENT_DIMENSION;
+    field public static final Object! PERCENT_DIMENSION;
+    field public static final Object! RATIO_DIMENSION;
+    field public static final Object! SPREAD_DIMENSION;
+    field public static final Object! WRAP_DIMENSION;
+  }
+
+  public enum Dimension.Type {
+    enum_constant public static final androidx.constraintlayout.core.state.Dimension.Type FIXED;
+    enum_constant public static final androidx.constraintlayout.core.state.Dimension.Type MATCH_CONSTRAINT;
+    enum_constant public static final androidx.constraintlayout.core.state.Dimension.Type MATCH_PARENT;
+    enum_constant public static final androidx.constraintlayout.core.state.Dimension.Type WRAP;
+  }
+
+  public class HelperReference extends androidx.constraintlayout.core.state.ConstraintReference implements androidx.constraintlayout.core.state.helpers.Facade {
+    ctor public HelperReference(androidx.constraintlayout.core.state.State!, androidx.constraintlayout.core.state.State.Helper!);
+    method public androidx.constraintlayout.core.state.HelperReference! add(java.lang.Object!...!);
+    method public void applyBase();
+    method public androidx.constraintlayout.core.widgets.HelperWidget! getHelperWidget();
+    method public androidx.constraintlayout.core.state.State.Helper! getType();
+    method public void setHelperWidget(androidx.constraintlayout.core.widgets.HelperWidget!);
+    field protected final androidx.constraintlayout.core.state.State! mHelperState;
+    field protected java.util.ArrayList<java.lang.Object!>! mReferences;
+  }
+
+  public interface Interpolator {
+    method public float getInterpolation(float);
+  }
+
+  public interface Reference {
+    method public void apply();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getConstraintWidget();
+    method public androidx.constraintlayout.core.state.helpers.Facade! getFacade();
+    method public Object! getKey();
+    method public void setConstraintWidget(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public void setKey(Object!);
+  }
+
+  public class Registry {
+    ctor public Registry();
+    method public String! currentContent(String!);
+    method public String! currentLayoutInformation(String!);
+    method public static androidx.constraintlayout.core.state.Registry! getInstance();
+    method public long getLastModified(String!);
+    method public java.util.Set<java.lang.String!>! getLayoutList();
+    method public void register(String!, androidx.constraintlayout.core.state.RegistryCallback!);
+    method public void setDrawDebug(String!, int);
+    method public void setLayoutInformationMode(String!, int);
+    method public void unregister(String!, androidx.constraintlayout.core.state.RegistryCallback!);
+    method public void updateContent(String!, String!);
+    method public void updateDimensions(String!, int, int);
+    method public void updateProgress(String!, float);
+  }
+
+  public interface RegistryCallback {
+    method public String! currentLayoutInformation();
+    method public String! currentMotionScene();
+    method public long getLastModified();
+    method public void onDimensions(int, int);
+    method public void onNewMotionScene(String!);
+    method public void onProgress(float);
+    method public void setDrawDebug(int);
+    method public void setLayoutInformationMode(int);
+  }
+
+  public class State {
+    ctor public State();
+    method public void apply(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!);
+    method public androidx.constraintlayout.core.state.helpers.BarrierReference! barrier(Object!, androidx.constraintlayout.core.state.State.Direction!);
+    method public void baselineNeededFor(Object!);
+    method public androidx.constraintlayout.core.state.helpers.AlignHorizontallyReference! centerHorizontally(java.lang.Object!...!);
+    method public androidx.constraintlayout.core.state.helpers.AlignVerticallyReference! centerVertically(java.lang.Object!...!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! constraints(Object!);
+    method public int convertDimension(Object!);
+    method public androidx.constraintlayout.core.state.ConstraintReference! createConstraintReference(Object!);
+    method public void directMapping();
+    method public androidx.constraintlayout.core.state.helpers.FlowReference! getFlow(Object!, boolean);
+    method public androidx.constraintlayout.core.state.helpers.GridReference getGrid(Object, String);
+    method public androidx.constraintlayout.core.state.helpers.FlowReference! getHorizontalFlow();
+    method public androidx.constraintlayout.core.state.helpers.FlowReference! getHorizontalFlow(java.lang.Object!...!);
+    method public java.util.ArrayList<java.lang.String!>! getIdsForTag(String!);
+    method public androidx.constraintlayout.core.state.helpers.FlowReference! getVerticalFlow();
+    method public androidx.constraintlayout.core.state.helpers.FlowReference! getVerticalFlow(java.lang.Object!...!);
+    method public androidx.constraintlayout.core.state.helpers.GuidelineReference! guideline(Object!, int);
+    method public androidx.constraintlayout.core.state.State! height(androidx.constraintlayout.core.state.Dimension!);
+    method public androidx.constraintlayout.core.state.HelperReference! helper(Object!, androidx.constraintlayout.core.state.State.Helper!);
+    method public androidx.constraintlayout.core.state.helpers.HorizontalChainReference! horizontalChain();
+    method public androidx.constraintlayout.core.state.helpers.HorizontalChainReference! horizontalChain(java.lang.Object!...!);
+    method public androidx.constraintlayout.core.state.helpers.GuidelineReference! horizontalGuideline(Object!);
+    method public boolean isBaselineNeeded(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method @Deprecated public boolean isLtr();
+    method public boolean isRtl();
+    method public void map(Object!, Object!);
+    method public void reset();
+    method public boolean sameFixedHeight(int);
+    method public boolean sameFixedWidth(int);
+    method public void setDpToPixel(androidx.constraintlayout.core.state.CorePixelDp!);
+    method public androidx.constraintlayout.core.state.State! setHeight(androidx.constraintlayout.core.state.Dimension!);
+    method @Deprecated public void setLtr(boolean);
+    method public void setRtl(boolean);
+    method public void setTag(String!, String!);
+    method public androidx.constraintlayout.core.state.State! setWidth(androidx.constraintlayout.core.state.Dimension!);
+    method public androidx.constraintlayout.core.state.helpers.VerticalChainReference! verticalChain();
+    method public androidx.constraintlayout.core.state.helpers.VerticalChainReference! verticalChain(java.lang.Object!...!);
+    method public androidx.constraintlayout.core.state.helpers.GuidelineReference! verticalGuideline(Object!);
+    method public androidx.constraintlayout.core.state.State! width(androidx.constraintlayout.core.state.Dimension!);
+    field public static final Integer PARENT;
+    field protected java.util.HashMap<java.lang.Object!,androidx.constraintlayout.core.state.HelperReference!>! mHelperReferences;
+    field public final androidx.constraintlayout.core.state.ConstraintReference! mParent;
+    field protected java.util.HashMap<java.lang.Object!,androidx.constraintlayout.core.state.Reference!>! mReferences;
+  }
+
+  public enum State.Chain {
+    method public static androidx.constraintlayout.core.state.State.Chain! getChainByString(String!);
+    method public static int getValueByString(String!);
+    enum_constant public static final androidx.constraintlayout.core.state.State.Chain PACKED;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Chain SPREAD;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Chain SPREAD_INSIDE;
+    field public static java.util.Map<java.lang.String!,androidx.constraintlayout.core.state.State.Chain!>! chainMap;
+    field public static java.util.Map<java.lang.String!,java.lang.Integer!>! valueMap;
+  }
+
+  public enum State.Constraint {
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint BASELINE_TO_BASELINE;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint BASELINE_TO_BOTTOM;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint BASELINE_TO_TOP;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint BOTTOM_TO_BASELINE;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint BOTTOM_TO_BOTTOM;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint BOTTOM_TO_TOP;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint CENTER_HORIZONTALLY;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint CENTER_VERTICALLY;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint CIRCULAR_CONSTRAINT;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint END_TO_END;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint END_TO_START;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint LEFT_TO_LEFT;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint LEFT_TO_RIGHT;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint RIGHT_TO_LEFT;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint RIGHT_TO_RIGHT;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint START_TO_END;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint START_TO_START;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint TOP_TO_BASELINE;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint TOP_TO_BOTTOM;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Constraint TOP_TO_TOP;
+  }
+
+  public enum State.Direction {
+    enum_constant public static final androidx.constraintlayout.core.state.State.Direction BOTTOM;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Direction END;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Direction LEFT;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Direction RIGHT;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Direction START;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Direction TOP;
+  }
+
+  public enum State.Helper {
+    enum_constant public static final androidx.constraintlayout.core.state.State.Helper ALIGN_HORIZONTALLY;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Helper ALIGN_VERTICALLY;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Helper BARRIER;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Helper COLUMN;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Helper FLOW;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Helper GRID;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Helper HORIZONTAL_CHAIN;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Helper HORIZONTAL_FLOW;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Helper LAYER;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Helper ROW;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Helper VERTICAL_CHAIN;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Helper VERTICAL_FLOW;
+  }
+
+  public enum State.Wrap {
+    method public static androidx.constraintlayout.core.state.State.Wrap! getChainByString(String!);
+    method public static int getValueByString(String!);
+    enum_constant public static final androidx.constraintlayout.core.state.State.Wrap ALIGNED;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Wrap CHAIN;
+    enum_constant public static final androidx.constraintlayout.core.state.State.Wrap NONE;
+    field public static java.util.Map<java.lang.String!,java.lang.Integer!>! valueMap;
+    field public static java.util.Map<java.lang.String!,androidx.constraintlayout.core.state.State.Wrap!>! wrapMap;
+  }
+
+  public class Transition implements androidx.constraintlayout.core.motion.utils.TypedValues {
+    ctor public Transition(androidx.constraintlayout.core.state.CorePixelDp);
+    method public void addCustomColor(int, String!, String!, int);
+    method public void addCustomFloat(int, String!, String!, float);
+    method public void addKeyAttribute(String!, androidx.constraintlayout.core.motion.utils.TypedBundle!);
+    method public void addKeyAttribute(String!, androidx.constraintlayout.core.motion.utils.TypedBundle!, androidx.constraintlayout.core.motion.CustomVariable![]!);
+    method public void addKeyCycle(String!, androidx.constraintlayout.core.motion.utils.TypedBundle!);
+    method public void addKeyPosition(String!, androidx.constraintlayout.core.motion.utils.TypedBundle!);
+    method public void addKeyPosition(String!, int, int, float, float);
+    method public void calcStagger();
+    method public void clear();
+    method public boolean contains(String!);
+    method public float dragToProgress(float, int, int, float, float);
+    method public void fillKeyPositions(androidx.constraintlayout.core.state.WidgetFrame!, float[]!, float[]!, float[]!);
+    method public androidx.constraintlayout.core.state.Transition.KeyPosition! findNextPosition(String!, int);
+    method public androidx.constraintlayout.core.state.Transition.KeyPosition! findPreviousPosition(String!, int);
+    method public int getAutoTransition();
+    method public androidx.constraintlayout.core.state.WidgetFrame! getEnd(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public androidx.constraintlayout.core.state.WidgetFrame! getEnd(String!);
+    method public int getId(String!);
+    method public androidx.constraintlayout.core.state.WidgetFrame! getInterpolated(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public androidx.constraintlayout.core.state.WidgetFrame! getInterpolated(String!);
+    method public int getInterpolatedHeight();
+    method public int getInterpolatedWidth();
+    method public androidx.constraintlayout.core.state.Interpolator! getInterpolator();
+    method public static androidx.constraintlayout.core.state.Interpolator! getInterpolator(int, String!);
+    method public int getKeyFrames(String!, float[]!, int[]!, int[]!);
+    method public androidx.constraintlayout.core.motion.Motion! getMotion(String!);
+    method public int getNumberKeyPositions(androidx.constraintlayout.core.state.WidgetFrame!);
+    method public float[]! getPath(String!);
+    method public androidx.constraintlayout.core.state.WidgetFrame! getStart(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public androidx.constraintlayout.core.state.WidgetFrame! getStart(String!);
+    method public float getTouchUpProgress(long);
+    method public androidx.constraintlayout.core.state.Transition.WidgetState! getWidgetState(String!, androidx.constraintlayout.core.widgets.ConstraintWidget!, int);
+    method public boolean hasOnSwipe();
+    method public boolean hasPositionKeyframes();
+    method public void interpolate(int, int, float);
+    method public boolean isEmpty();
+    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public boolean isFirstDownAccepted(float, float);
+    method public boolean isTouchNotDone(float);
+    method public void setTouchUp(float, long, float, float);
+    method public void setTransitionProperties(androidx.constraintlayout.core.motion.utils.TypedBundle!);
+    method public boolean setValue(int, boolean);
+    method public boolean setValue(int, float);
+    method public boolean setValue(int, int);
+    method public boolean setValue(int, String!);
+    method public void updateFrom(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!, int);
+    field public static final int END = 1; // 0x1
+    field public static final int INTERPOLATED = 2; // 0x2
+    field public static final int START = 0; // 0x0
+  }
+
+  public static class Transition.WidgetState {
+    ctor public Transition.WidgetState();
+    method public androidx.constraintlayout.core.state.WidgetFrame! getFrame(int);
+    method public void interpolate(int, int, float, androidx.constraintlayout.core.state.Transition!);
+    method public void setKeyAttribute(androidx.constraintlayout.core.motion.utils.TypedBundle!);
+    method public void setKeyAttribute(androidx.constraintlayout.core.motion.utils.TypedBundle!, androidx.constraintlayout.core.motion.CustomVariable![]!);
+    method public void setKeyCycle(androidx.constraintlayout.core.motion.utils.TypedBundle!);
+    method public void setKeyPosition(androidx.constraintlayout.core.motion.utils.TypedBundle!);
+    method public void setPathRelative(androidx.constraintlayout.core.state.Transition.WidgetState!);
+    method public void update(androidx.constraintlayout.core.widgets.ConstraintWidget!, int);
+  }
+
+  public class TransitionParser {
+    ctor public TransitionParser();
+    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public static void parse(androidx.constraintlayout.core.parser.CLObject, androidx.constraintlayout.core.state.Transition) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method @Deprecated public static void parse(androidx.constraintlayout.core.parser.CLObject!, androidx.constraintlayout.core.state.Transition!, androidx.constraintlayout.core.state.CorePixelDp!) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public static void parseKeyFrames(androidx.constraintlayout.core.parser.CLObject!, androidx.constraintlayout.core.state.Transition!) throws androidx.constraintlayout.core.parser.CLParsingException;
+  }
+
+  public class WidgetFrame {
+    ctor public WidgetFrame();
+    ctor public WidgetFrame(androidx.constraintlayout.core.state.WidgetFrame!);
+    ctor public WidgetFrame(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public void addCustomColor(String!, int);
+    method public void addCustomFloat(String!, float);
+    method public float centerX();
+    method public float centerY();
+    method public boolean containsCustom(String);
+    method public androidx.constraintlayout.core.motion.CustomVariable! getCustomAttribute(String!);
+    method public java.util.Set<java.lang.String!>! getCustomAttributeNames();
+    method public int getCustomColor(String!);
+    method public float getCustomFloat(String!);
+    method public String! getId();
+    method public androidx.constraintlayout.core.motion.utils.TypedBundle! getMotionProperties();
+    method public int height();
+    method public static void interpolate(int, int, androidx.constraintlayout.core.state.WidgetFrame!, androidx.constraintlayout.core.state.WidgetFrame!, androidx.constraintlayout.core.state.WidgetFrame!, androidx.constraintlayout.core.state.Transition!, float);
+    method public boolean isDefaultTransform();
+    method public StringBuilder! serialize(StringBuilder!);
+    method public StringBuilder! serialize(StringBuilder!, boolean);
+    method public void setCustomAttribute(String!, int, boolean);
+    method public void setCustomAttribute(String!, int, float);
+    method public void setCustomAttribute(String!, int, int);
+    method public void setCustomAttribute(String!, int, String!);
+    method public void setCustomValue(androidx.constraintlayout.core.motion.CustomAttribute!, float[]!);
+    method public boolean setValue(String!, androidx.constraintlayout.core.parser.CLElement!) throws androidx.constraintlayout.core.parser.CLParsingException;
+    method public androidx.constraintlayout.core.state.WidgetFrame! update();
+    method public androidx.constraintlayout.core.state.WidgetFrame! update(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public void updateAttributes(androidx.constraintlayout.core.state.WidgetFrame!);
+    method public int width();
+    field public float alpha;
+    field public int bottom;
+    field public float interpolatedPos;
+    field public int left;
+    field public String! name;
+    field public static float phone_orientation;
+    field public float pivotX;
+    field public float pivotY;
+    field public int right;
+    field public float rotationX;
+    field public float rotationY;
+    field public float rotationZ;
+    field public float scaleX;
+    field public float scaleY;
+    field public int top;
+    field public float translationX;
+    field public float translationY;
+    field public float translationZ;
+    field public int visibility;
+    field public androidx.constraintlayout.core.widgets.ConstraintWidget! widget;
+  }
+
+}
+
+package androidx.constraintlayout.core.state.helpers {
+
+  public class AlignHorizontallyReference extends androidx.constraintlayout.core.state.HelperReference {
+    ctor public AlignHorizontallyReference(androidx.constraintlayout.core.state.State!);
+  }
+
+  public class AlignVerticallyReference extends androidx.constraintlayout.core.state.HelperReference {
+    ctor public AlignVerticallyReference(androidx.constraintlayout.core.state.State!);
+  }
+
+  public class BarrierReference extends androidx.constraintlayout.core.state.HelperReference {
+    ctor public BarrierReference(androidx.constraintlayout.core.state.State!);
+    method public void setBarrierDirection(androidx.constraintlayout.core.state.State.Direction!);
+  }
+
+  public class ChainReference extends androidx.constraintlayout.core.state.HelperReference {
+    ctor public ChainReference(androidx.constraintlayout.core.state.State, androidx.constraintlayout.core.state.State.Helper);
+    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public void addChainElement(Object, float, float, float, float, float);
+    method public void addChainElement(String, float, float, float);
+    method public androidx.constraintlayout.core.state.helpers.ChainReference bias(float);
+    method public float getBias();
+    method protected float getPostMargin(String);
+    method protected float getPreMargin(String);
+    method public androidx.constraintlayout.core.state.State.Chain getStyle();
+    method protected float getWeight(String);
+    method public androidx.constraintlayout.core.state.helpers.ChainReference style(androidx.constraintlayout.core.state.State.Chain);
+    field protected float mBias;
+    field @Deprecated protected java.util.HashMap<java.lang.String!,java.lang.Float!> mMapPostMargin;
+    field @Deprecated protected java.util.HashMap<java.lang.String!,java.lang.Float!> mMapPreMargin;
+    field @Deprecated protected java.util.HashMap<java.lang.String!,java.lang.Float!> mMapWeights;
+    field protected androidx.constraintlayout.core.state.State.Chain mStyle;
+  }
+
+  public interface Facade {
+    method public void apply();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getConstraintWidget();
+  }
+
+  public class FlowReference extends androidx.constraintlayout.core.state.HelperReference {
+    ctor public FlowReference(androidx.constraintlayout.core.state.State!, androidx.constraintlayout.core.state.State.Helper!);
+    method public void addFlowElement(String!, float, float, float);
+    method public float getFirstHorizontalBias();
+    method public int getFirstHorizontalStyle();
+    method public float getFirstVerticalBias();
+    method public int getFirstVerticalStyle();
+    method public int getHorizontalAlign();
+    method public float getHorizontalBias();
+    method public int getHorizontalGap();
+    method public int getHorizontalStyle();
+    method public float getLastHorizontalBias();
+    method public int getLastHorizontalStyle();
+    method public float getLastVerticalBias();
+    method public int getLastVerticalStyle();
+    method public int getMaxElementsWrap();
+    method public int getOrientation();
+    method public int getPaddingBottom();
+    method public int getPaddingLeft();
+    method public int getPaddingRight();
+    method public int getPaddingTop();
+    method protected float getPostMargin(String!);
+    method protected float getPreMargin(String!);
+    method public int getVerticalAlign();
+    method public float getVerticalBias();
+    method public int getVerticalGap();
+    method public int getVerticalStyle();
+    method protected float getWeight(String!);
+    method public int getWrapMode();
+    method public void setFirstHorizontalBias(float);
+    method public void setFirstHorizontalStyle(int);
+    method public void setFirstVerticalBias(float);
+    method public void setFirstVerticalStyle(int);
+    method public void setHorizontalAlign(int);
+    method public void setHorizontalGap(int);
+    method public void setHorizontalStyle(int);
+    method public void setLastHorizontalBias(float);
+    method public void setLastHorizontalStyle(int);
+    method public void setLastVerticalBias(float);
+    method public void setLastVerticalStyle(int);
+    method public void setMaxElementsWrap(int);
+    method public void setOrientation(int);
+    method public void setPaddingBottom(int);
+    method public void setPaddingLeft(int);
+    method public void setPaddingRight(int);
+    method public void setPaddingTop(int);
+    method public void setVerticalAlign(int);
+    method public void setVerticalGap(int);
+    method public void setVerticalStyle(int);
+    method public void setWrapMode(int);
+    field protected float mFirstHorizontalBias;
+    field protected int mFirstHorizontalStyle;
+    field protected float mFirstVerticalBias;
+    field protected int mFirstVerticalStyle;
+    field protected androidx.constraintlayout.core.widgets.Flow! mFlow;
+    field protected int mHorizontalAlign;
+    field protected int mHorizontalGap;
+    field protected int mHorizontalStyle;
+    field protected float mLastHorizontalBias;
+    field protected int mLastHorizontalStyle;
+    field protected float mLastVerticalBias;
+    field protected int mLastVerticalStyle;
+    field protected java.util.HashMap<java.lang.String!,java.lang.Float!>! mMapPostMargin;
+    field protected java.util.HashMap<java.lang.String!,java.lang.Float!>! mMapPreMargin;
+    field protected java.util.HashMap<java.lang.String!,java.lang.Float!>! mMapWeights;
+    field protected int mMaxElementsWrap;
+    field protected int mOrientation;
+    field protected int mPaddingBottom;
+    field protected int mPaddingLeft;
+    field protected int mPaddingRight;
+    field protected int mPaddingTop;
+    field protected int mVerticalAlign;
+    field protected int mVerticalGap;
+    field protected int mVerticalStyle;
+    field protected int mWrapMode;
+  }
+
+  public class GridReference extends androidx.constraintlayout.core.state.HelperReference {
+    ctor public GridReference(androidx.constraintlayout.core.state.State, androidx.constraintlayout.core.state.State.Helper);
+    method public String? getColumnWeights();
+    method public int getColumnsSet();
+    method public int getFlags();
+    method public float getHorizontalGaps();
+    method public int getOrientation();
+    method public int getPaddingBottom();
+    method public int getPaddingEnd();
+    method public int getPaddingStart();
+    method public int getPaddingTop();
+    method public String? getRowWeights();
+    method public int getRowsSet();
+    method public String? getSkips();
+    method public String? getSpans();
+    method public float getVerticalGaps();
+    method public void setColumnWeights(String);
+    method public void setColumnsSet(int);
+    method public void setFlags(int);
+    method public void setFlags(String);
+    method public void setHorizontalGaps(float);
+    method public void setOrientation(int);
+    method public void setPaddingBottom(int);
+    method public void setPaddingEnd(int);
+    method public void setPaddingStart(int);
+    method public void setPaddingTop(int);
+    method public void setRowWeights(String);
+    method public void setRowsSet(int);
+    method public void setSkips(String);
+    method public void setSpans(String);
+    method public void setVerticalGaps(float);
+  }
+
+  public class GuidelineReference implements androidx.constraintlayout.core.state.helpers.Facade androidx.constraintlayout.core.state.Reference {
+    ctor public GuidelineReference(androidx.constraintlayout.core.state.State!);
+    method public void apply();
+    method public androidx.constraintlayout.core.state.helpers.GuidelineReference! end(Object!);
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getConstraintWidget();
+    method public androidx.constraintlayout.core.state.helpers.Facade! getFacade();
+    method public Object! getKey();
+    method public int getOrientation();
+    method public androidx.constraintlayout.core.state.helpers.GuidelineReference! percent(float);
+    method public void setConstraintWidget(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public void setKey(Object!);
+    method public void setOrientation(int);
+    method public androidx.constraintlayout.core.state.helpers.GuidelineReference! start(Object!);
+  }
+
+  public class HorizontalChainReference extends androidx.constraintlayout.core.state.helpers.ChainReference {
+    ctor public HorizontalChainReference(androidx.constraintlayout.core.state.State!);
+  }
+
+  public class VerticalChainReference extends androidx.constraintlayout.core.state.helpers.ChainReference {
+    ctor public VerticalChainReference(androidx.constraintlayout.core.state.State!);
+  }
+
+}
+
+package androidx.constraintlayout.core.utils {
+
+  public class GridCore extends androidx.constraintlayout.core.widgets.VirtualLayout {
+    ctor public GridCore();
+    ctor public GridCore(int, int);
+    method public String? getColumnWeights();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidgetContainer? getContainer();
+    method public int getFlags();
+    method public float getHorizontalGaps();
+    method public int getOrientation();
+    method public String? getRowWeights();
+    method public float getVerticalGaps();
+    method public void setColumnWeights(String);
+    method public void setColumns(int);
+    method public void setContainer(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer);
+    method public void setFlags(int);
+    method public void setHorizontalGaps(float);
+    method public void setOrientation(int);
+    method public void setRowWeights(String);
+    method public void setRows(int);
+    method public void setSkips(String);
+    method public void setSpans(CharSequence);
+    method public void setVerticalGaps(float);
+    field public static final int HORIZONTAL = 0; // 0x0
+    field public static final int SPANS_RESPECT_WIDGET_ORDER = 2; // 0x2
+    field public static final int SUB_GRID_BY_COL_ROW = 1; // 0x1
+    field public static final int VERTICAL = 1; // 0x1
+  }
+
+  public class GridEngine {
+    ctor public GridEngine();
+    ctor public GridEngine(int, int);
+    ctor public GridEngine(int, int, int);
+    method public int bottomOfWidget(int);
+    method public int leftOfWidget(int);
+    method public int rightOfWidget(int);
+    method public void setColumns(int);
+    method public void setNumWidgets(int);
+    method public void setOrientation(int);
+    method public void setRows(int);
+    method public void setSkips(String!);
+    method public void setSpans(CharSequence!);
+    method public void setup();
+    method public int topOfWidget(int);
+    field public static final int HORIZONTAL = 0; // 0x0
+    field public static final int VERTICAL = 1; // 0x1
+  }
+
+}
+
+package androidx.constraintlayout.core.widgets {
+
+  public class Barrier extends androidx.constraintlayout.core.widgets.HelperWidget {
+    ctor public Barrier();
+    ctor public Barrier(String!);
+    method public boolean allSolved();
+    method @Deprecated public boolean allowsGoneWidget();
+    method public boolean getAllowsGoneWidget();
+    method public int getBarrierType();
+    method public int getMargin();
+    method public int getOrientation();
+    method protected void markWidgets();
+    method public void setAllowsGoneWidget(boolean);
+    method public void setBarrierType(int);
+    method public void setMargin(int);
+    field public static final int BOTTOM = 3; // 0x3
+    field public static final int LEFT = 0; // 0x0
+    field public static final int RIGHT = 1; // 0x1
+    field public static final int TOP = 2; // 0x2
+  }
+
+  public class Chain {
+    ctor public Chain();
+    method public static void applyChainConstraints(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!, androidx.constraintlayout.core.LinearSystem!, java.util.ArrayList<androidx.constraintlayout.core.widgets.ConstraintWidget!>!, int);
+    field public static final boolean USE_CHAIN_OPTIMIZATION = false;
+  }
+
+  public class ChainHead {
+    ctor public ChainHead(androidx.constraintlayout.core.widgets.ConstraintWidget!, int, boolean);
+    method public void define();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getFirst();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getFirstMatchConstraintWidget();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getFirstVisibleWidget();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getHead();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getLast();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getLastMatchConstraintWidget();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getLastVisibleWidget();
+    method public float getTotalWeight();
+    field protected androidx.constraintlayout.core.widgets.ConstraintWidget! mFirst;
+    field protected androidx.constraintlayout.core.widgets.ConstraintWidget! mFirstMatchConstraintWidget;
+    field protected androidx.constraintlayout.core.widgets.ConstraintWidget! mFirstVisibleWidget;
+    field protected boolean mHasComplexMatchWeights;
+    field protected boolean mHasDefinedWeights;
+    field protected boolean mHasRatio;
+    field protected boolean mHasUndefinedWeights;
+    field protected androidx.constraintlayout.core.widgets.ConstraintWidget! mHead;
+    field protected androidx.constraintlayout.core.widgets.ConstraintWidget! mLast;
+    field protected androidx.constraintlayout.core.widgets.ConstraintWidget! mLastMatchConstraintWidget;
+    field protected androidx.constraintlayout.core.widgets.ConstraintWidget! mLastVisibleWidget;
+    field protected float mTotalWeight;
+    field protected java.util.ArrayList<androidx.constraintlayout.core.widgets.ConstraintWidget!>! mWeightedMatchConstraintsWidgets;
+    field protected int mWidgetsCount;
+    field protected int mWidgetsMatchCount;
+  }
+
+  public class ConstraintAnchor {
+    ctor public ConstraintAnchor(androidx.constraintlayout.core.widgets.ConstraintWidget!, androidx.constraintlayout.core.widgets.ConstraintAnchor.Type!);
+    method public boolean connect(androidx.constraintlayout.core.widgets.ConstraintAnchor!, int);
+    method public boolean connect(androidx.constraintlayout.core.widgets.ConstraintAnchor!, int, int, boolean);
+    method public void copyFrom(androidx.constraintlayout.core.widgets.ConstraintAnchor!, java.util.HashMap<androidx.constraintlayout.core.widgets.ConstraintWidget!,androidx.constraintlayout.core.widgets.ConstraintWidget!>!);
+    method public void findDependents(int, java.util.ArrayList<androidx.constraintlayout.core.widgets.analyzer.WidgetGroup!>!, androidx.constraintlayout.core.widgets.analyzer.WidgetGroup!);
+    method public java.util.HashSet<androidx.constraintlayout.core.widgets.ConstraintAnchor!>! getDependents();
+    method public int getFinalValue();
+    method public int getMargin();
+    method public final androidx.constraintlayout.core.widgets.ConstraintAnchor! getOpposite();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getOwner();
+    method public androidx.constraintlayout.core.SolverVariable! getSolverVariable();
+    method public androidx.constraintlayout.core.widgets.ConstraintAnchor! getTarget();
+    method public androidx.constraintlayout.core.widgets.ConstraintAnchor.Type! getType();
+    method public boolean hasCenteredDependents();
+    method public boolean hasDependents();
+    method public boolean hasFinalValue();
+    method public boolean isConnected();
+    method public boolean isConnectionAllowed(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public boolean isConnectionAllowed(androidx.constraintlayout.core.widgets.ConstraintWidget!, androidx.constraintlayout.core.widgets.ConstraintAnchor!);
+    method public boolean isSideAnchor();
+    method public boolean isSimilarDimensionConnection(androidx.constraintlayout.core.widgets.ConstraintAnchor!);
+    method public boolean isValidConnection(androidx.constraintlayout.core.widgets.ConstraintAnchor!);
+    method public boolean isVerticalAnchor();
+    method public void reset();
+    method public void resetFinalResolution();
+    method public void resetSolverVariable(androidx.constraintlayout.core.Cache!);
+    method public void setFinalValue(int);
+    method public void setGoneMargin(int);
+    method public void setMargin(int);
+    field public int mMargin;
+    field public final androidx.constraintlayout.core.widgets.ConstraintWidget! mOwner;
+    field public androidx.constraintlayout.core.widgets.ConstraintAnchor! mTarget;
+    field public final androidx.constraintlayout.core.widgets.ConstraintAnchor.Type! mType;
+  }
+
+  public enum ConstraintAnchor.Type {
+    enum_constant public static final androidx.constraintlayout.core.widgets.ConstraintAnchor.Type BASELINE;
+    enum_constant public static final androidx.constraintlayout.core.widgets.ConstraintAnchor.Type BOTTOM;
+    enum_constant public static final androidx.constraintlayout.core.widgets.ConstraintAnchor.Type CENTER;
+    enum_constant public static final androidx.constraintlayout.core.widgets.ConstraintAnchor.Type CENTER_X;
+    enum_constant public static final androidx.constraintlayout.core.widgets.ConstraintAnchor.Type CENTER_Y;
+    enum_constant public static final androidx.constraintlayout.core.widgets.ConstraintAnchor.Type LEFT;
+    enum_constant public static final androidx.constraintlayout.core.widgets.ConstraintAnchor.Type NONE;
+    enum_constant public static final androidx.constraintlayout.core.widgets.ConstraintAnchor.Type RIGHT;
+    enum_constant public static final androidx.constraintlayout.core.widgets.ConstraintAnchor.Type TOP;
+  }
+
+  public class ConstraintWidget {
+    ctor public ConstraintWidget();
+    ctor public ConstraintWidget(int, int);
+    ctor public ConstraintWidget(int, int, int, int);
+    ctor public ConstraintWidget(String!);
+    ctor public ConstraintWidget(String!, int, int);
+    ctor public ConstraintWidget(String!, int, int, int, int);
+    method public void addChildrenToSolverByDependency(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!, androidx.constraintlayout.core.LinearSystem!, java.util.HashSet<androidx.constraintlayout.core.widgets.ConstraintWidget!>!, int, boolean);
+    method public void addToSolver(androidx.constraintlayout.core.LinearSystem!, boolean);
+    method public boolean allowedInBarrier();
+    method public void connect(androidx.constraintlayout.core.widgets.ConstraintAnchor!, androidx.constraintlayout.core.widgets.ConstraintAnchor!, int);
+    method public void connect(androidx.constraintlayout.core.widgets.ConstraintAnchor.Type!, androidx.constraintlayout.core.widgets.ConstraintWidget!, androidx.constraintlayout.core.widgets.ConstraintAnchor.Type!);
+    method public void connect(androidx.constraintlayout.core.widgets.ConstraintAnchor.Type!, androidx.constraintlayout.core.widgets.ConstraintWidget!, androidx.constraintlayout.core.widgets.ConstraintAnchor.Type!, int);
+    method public void connectCircularConstraint(androidx.constraintlayout.core.widgets.ConstraintWidget!, float, int);
+    method public void copy(androidx.constraintlayout.core.widgets.ConstraintWidget!, java.util.HashMap<androidx.constraintlayout.core.widgets.ConstraintWidget!,androidx.constraintlayout.core.widgets.ConstraintWidget!>!);
+    method public void createObjectVariables(androidx.constraintlayout.core.LinearSystem!);
+    method public void ensureMeasureRequested();
+    method public void ensureWidgetRuns();
+    method public androidx.constraintlayout.core.widgets.ConstraintAnchor! getAnchor(androidx.constraintlayout.core.widgets.ConstraintAnchor.Type!);
+    method public java.util.ArrayList<androidx.constraintlayout.core.widgets.ConstraintAnchor!>! getAnchors();
+    method public int getBaselineDistance();
+    method public float getBiasPercent(int);
+    method public int getBottom();
+    method public Object! getCompanionWidget();
+    method public int getContainerItemSkip();
+    method public String! getDebugName();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour! getDimensionBehaviour(int);
+    method public float getDimensionRatio();
+    method public int getDimensionRatioSide();
+    method public boolean getHasBaseline();
+    method public int getHeight();
+    method public float getHorizontalBiasPercent();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getHorizontalChainControlWidget();
+    method public int getHorizontalChainStyle();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour! getHorizontalDimensionBehaviour();
+    method public int getHorizontalMargin();
+    method public int getLastHorizontalMeasureSpec();
+    method public int getLastVerticalMeasureSpec();
+    method public int getLeft();
+    method public int getLength(int);
+    method public int getMaxHeight();
+    method public int getMaxWidth();
+    method public int getMinHeight();
+    method public int getMinWidth();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getNextChainMember(int);
+    method public int getOptimizerWrapHeight();
+    method public int getOptimizerWrapWidth();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getParent();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getPreviousChainMember(int);
+    method public int getRight();
+    method protected int getRootX();
+    method protected int getRootY();
+    method public androidx.constraintlayout.core.widgets.analyzer.WidgetRun! getRun(int);
+    method public void getSceneString(StringBuilder!);
+    method public int getTop();
+    method public String! getType();
+    method public float getVerticalBiasPercent();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getVerticalChainControlWidget();
+    method public int getVerticalChainStyle();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour! getVerticalDimensionBehaviour();
+    method public int getVerticalMargin();
+    method public int getVisibility();
+    method public int getWidth();
+    method public int getWrapBehaviorInParent();
+    method public int getX();
+    method public int getY();
+    method public boolean hasBaseline();
+    method public boolean hasDanglingDimension(int);
+    method public boolean hasDependencies();
+    method public boolean hasDimensionOverride();
+    method public boolean hasResolvedTargets(int, int);
+    method public void immediateConnect(androidx.constraintlayout.core.widgets.ConstraintAnchor.Type!, androidx.constraintlayout.core.widgets.ConstraintWidget!, androidx.constraintlayout.core.widgets.ConstraintAnchor.Type!, int, int);
+    method public boolean isAnimated();
+    method public boolean isHeightWrapContent();
+    method public boolean isHorizontalSolvingPassDone();
+    method public boolean isInBarrier(int);
+    method public boolean isInHorizontalChain();
+    method public boolean isInPlaceholder();
+    method public boolean isInVerticalChain();
+    method public boolean isInVirtualLayout();
+    method public boolean isMeasureRequested();
+    method public boolean isResolvedHorizontally();
+    method public boolean isResolvedVertically();
+    method public boolean isRoot();
+    method public boolean isSpreadHeight();
+    method public boolean isSpreadWidth();
+    method public boolean isVerticalSolvingPassDone();
+    method public boolean isWidthWrapContent();
+    method public void markHorizontalSolvingPassDone();
+    method public void markVerticalSolvingPassDone();
+    method public boolean oppositeDimensionDependsOn(int);
+    method public boolean oppositeDimensionsTied();
+    method public void reset();
+    method public void resetAllConstraints();
+    method public void resetAnchor(androidx.constraintlayout.core.widgets.ConstraintAnchor!);
+    method public void resetAnchors();
+    method public void resetFinalResolution();
+    method public void resetSolverVariables(androidx.constraintlayout.core.Cache!);
+    method public void resetSolvingPassFlag();
+    method public StringBuilder! serialize(StringBuilder!);
+    method public void setAnimated(boolean);
+    method public void setBaselineDistance(int);
+    method public void setCompanionWidget(Object!);
+    method public void setContainerItemSkip(int);
+    method public void setDebugName(String!);
+    method public void setDebugSolverName(androidx.constraintlayout.core.LinearSystem!, String!);
+    method public void setDimension(int, int);
+    method public void setDimensionRatio(float, int);
+    method public void setDimensionRatio(String!);
+    method public void setFinalBaseline(int);
+    method public void setFinalFrame(int, int, int, int, int, int);
+    method public void setFinalHorizontal(int, int);
+    method public void setFinalLeft(int);
+    method public void setFinalTop(int);
+    method public void setFinalVertical(int, int);
+    method public void setFrame(int, int, int);
+    method public void setFrame(int, int, int, int);
+    method public void setGoneMargin(androidx.constraintlayout.core.widgets.ConstraintAnchor.Type!, int);
+    method public void setHasBaseline(boolean);
+    method public void setHeight(int);
+    method public void setHeightWrapContent(boolean);
+    method public void setHorizontalBiasPercent(float);
+    method public void setHorizontalChainStyle(int);
+    method public void setHorizontalDimension(int, int);
+    method public void setHorizontalDimensionBehaviour(androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour!);
+    method public void setHorizontalMatchStyle(int, int, int, float);
+    method public void setHorizontalWeight(float);
+    method protected void setInBarrier(int, boolean);
+    method public void setInPlaceholder(boolean);
+    method public void setInVirtualLayout(boolean);
+    method public void setLastMeasureSpec(int, int);
+    method public void setLength(int, int);
+    method public void setMaxHeight(int);
+    method public void setMaxWidth(int);
+    method public void setMeasureRequested(boolean);
+    method public void setMinHeight(int);
+    method public void setMinWidth(int);
+    method public void setOffset(int, int);
+    method public void setOrigin(int, int);
+    method public void setParent(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public void setType(String!);
+    method public void setVerticalBiasPercent(float);
+    method public void setVerticalChainStyle(int);
+    method public void setVerticalDimension(int, int);
+    method public void setVerticalDimensionBehaviour(androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour!);
+    method public void setVerticalMatchStyle(int, int, int, float);
+    method public void setVerticalWeight(float);
+    method public void setVisibility(int);
+    method public void setWidth(int);
+    method public void setWidthWrapContent(boolean);
+    method public void setWrapBehaviorInParent(int);
+    method public void setX(int);
+    method public void setY(int);
+    method public void setupDimensionRatio(boolean, boolean, boolean, boolean);
+    method public void updateFromRuns(boolean, boolean);
+    method public void updateFromSolver(androidx.constraintlayout.core.LinearSystem!, boolean);
+    field public static final int ANCHOR_BASELINE = 4; // 0x4
+    field public static final int ANCHOR_BOTTOM = 3; // 0x3
+    field public static final int ANCHOR_LEFT = 0; // 0x0
+    field public static final int ANCHOR_RIGHT = 1; // 0x1
+    field public static final int ANCHOR_TOP = 2; // 0x2
+    field public static final int BOTH = 2; // 0x2
+    field public static final int CHAIN_PACKED = 2; // 0x2
+    field public static final int CHAIN_SPREAD = 0; // 0x0
+    field public static final int CHAIN_SPREAD_INSIDE = 1; // 0x1
+    field public static float DEFAULT_BIAS;
+    field protected static final int DIRECT = 2; // 0x2
+    field public static final int GONE = 8; // 0x8
+    field public static final int HORIZONTAL = 0; // 0x0
+    field public static final int INVISIBLE = 4; // 0x4
+    field public static final int MATCH_CONSTRAINT_PERCENT = 2; // 0x2
+    field public static final int MATCH_CONSTRAINT_RATIO = 3; // 0x3
+    field public static final int MATCH_CONSTRAINT_RATIO_RESOLVED = 4; // 0x4
+    field public static final int MATCH_CONSTRAINT_SPREAD = 0; // 0x0
+    field public static final int MATCH_CONSTRAINT_WRAP = 1; // 0x1
+    field protected static final int SOLVER = 1; // 0x1
+    field public static final int UNKNOWN = -1; // 0xffffffff
+    field public static final int VERTICAL = 1; // 0x1
+    field public static final int VISIBLE = 0; // 0x0
+    field public static final int WRAP_BEHAVIOR_HORIZONTAL_ONLY = 1; // 0x1
+    field public static final int WRAP_BEHAVIOR_INCLUDED = 0; // 0x0
+    field public static final int WRAP_BEHAVIOR_SKIPPED = 3; // 0x3
+    field public static final int WRAP_BEHAVIOR_VERTICAL_ONLY = 2; // 0x2
+    field public androidx.constraintlayout.core.state.WidgetFrame! frame;
+    field public androidx.constraintlayout.core.widgets.analyzer.ChainRun! horizontalChainRun;
+    field public int horizontalGroup;
+    field public boolean[]! isTerminalWidget;
+    field protected java.util.ArrayList<androidx.constraintlayout.core.widgets.ConstraintAnchor!>! mAnchors;
+    field public androidx.constraintlayout.core.widgets.ConstraintAnchor! mBaseline;
+    field public androidx.constraintlayout.core.widgets.ConstraintAnchor! mBottom;
+    field public androidx.constraintlayout.core.widgets.ConstraintAnchor! mCenter;
+    field public float mCircleConstraintAngle;
+    field public float mDimensionRatio;
+    field protected int mDimensionRatioSide;
+    field public int mHorizontalResolution;
+    field public androidx.constraintlayout.core.widgets.analyzer.HorizontalWidgetRun! mHorizontalRun;
+    field public boolean mIsHeightWrapContent;
+    field public boolean mIsWidthWrapContent;
+    field public androidx.constraintlayout.core.widgets.ConstraintAnchor! mLeft;
+    field public androidx.constraintlayout.core.widgets.ConstraintAnchor![]! mListAnchors;
+    field public androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour![]! mListDimensionBehaviors;
+    field protected androidx.constraintlayout.core.widgets.ConstraintWidget![]! mListNextMatchConstraintsWidget;
+    field public int mMatchConstraintDefaultHeight;
+    field public int mMatchConstraintDefaultWidth;
+    field public int mMatchConstraintMaxHeight;
+    field public int mMatchConstraintMaxWidth;
+    field public int mMatchConstraintMinHeight;
+    field public int mMatchConstraintMinWidth;
+    field public float mMatchConstraintPercentHeight;
+    field public float mMatchConstraintPercentWidth;
+    field protected int mMinHeight;
+    field protected int mMinWidth;
+    field protected androidx.constraintlayout.core.widgets.ConstraintWidget![]! mNextChainWidget;
+    field protected int mOffsetX;
+    field protected int mOffsetY;
+    field public androidx.constraintlayout.core.widgets.ConstraintWidget! mParent;
+    field public int[]! mResolvedMatchConstraintDefault;
+    field public androidx.constraintlayout.core.widgets.ConstraintAnchor! mRight;
+    field public androidx.constraintlayout.core.widgets.ConstraintAnchor! mTop;
+    field public int mVerticalResolution;
+    field public androidx.constraintlayout.core.widgets.analyzer.VerticalWidgetRun! mVerticalRun;
+    field public float[]! mWeight;
+    field protected int mX;
+    field protected int mY;
+    field public boolean measured;
+    field public androidx.constraintlayout.core.widgets.analyzer.WidgetRun![]! run;
+    field public String! stringId;
+    field public androidx.constraintlayout.core.widgets.analyzer.ChainRun! verticalChainRun;
+    field public int verticalGroup;
+  }
+
+  public enum ConstraintWidget.DimensionBehaviour {
+    enum_constant public static final androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour FIXED;
+    enum_constant public static final androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour MATCH_CONSTRAINT;
+    enum_constant public static final androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour MATCH_PARENT;
+    enum_constant public static final androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour WRAP_CONTENT;
+  }
+
+  public class ConstraintWidgetContainer extends androidx.constraintlayout.core.widgets.WidgetContainer {
+    ctor public ConstraintWidgetContainer();
+    ctor public ConstraintWidgetContainer(int, int);
+    ctor public ConstraintWidgetContainer(int, int, int, int);
+    ctor public ConstraintWidgetContainer(String!, int, int);
+    method public boolean addChildrenToSolver(androidx.constraintlayout.core.LinearSystem!);
+    method public void addHorizontalWrapMaxVariable(androidx.constraintlayout.core.widgets.ConstraintAnchor!);
+    method public void addHorizontalWrapMinVariable(androidx.constraintlayout.core.widgets.ConstraintAnchor!);
+    method public void defineTerminalWidgets();
+    method public boolean directMeasure(boolean);
+    method public boolean directMeasureSetup(boolean);
+    method public boolean directMeasureWithOrientation(boolean, int);
+    method public void fillMetrics(androidx.constraintlayout.core.Metrics!);
+    method public java.util.ArrayList<androidx.constraintlayout.core.widgets.Guideline!>! getHorizontalGuidelines();
+    method public androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.Measurer! getMeasurer();
+    method public int getOptimizationLevel();
+    method public androidx.constraintlayout.core.LinearSystem! getSystem();
+    method public java.util.ArrayList<androidx.constraintlayout.core.widgets.Guideline!>! getVerticalGuidelines();
+    method public boolean handlesInternalConstraints();
+    method public void invalidateGraph();
+    method public void invalidateMeasures();
+    method public boolean isHeightMeasuredTooSmall();
+    method public boolean isRtl();
+    method public boolean isWidthMeasuredTooSmall();
+    method public static boolean measure(int, androidx.constraintlayout.core.widgets.ConstraintWidget!, androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.Measurer!, androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.Measure!, int);
+    method public long measure(int, int, int, int, int, int, int, int, int);
+    method public boolean optimizeFor(int);
+    method public void setMeasurer(androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.Measurer!);
+    method public void setOptimizationLevel(int);
+    method public void setPadding(int, int, int, int);
+    method public void setPass(int);
+    method public void setRtl(boolean);
+    method public boolean updateChildrenFromSolver(androidx.constraintlayout.core.LinearSystem!, boolean[]!);
+    method public void updateHierarchy();
+    field public androidx.constraintlayout.core.widgets.analyzer.DependencyGraph! mDependencyGraph;
+    field public boolean mGroupsWrapOptimized;
+    field public int mHorizontalChainsSize;
+    field public boolean mHorizontalWrapOptimized;
+    field public androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.Measure! mMeasure;
+    field protected androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.Measurer! mMeasurer;
+    field public androidx.constraintlayout.core.Metrics! mMetrics;
+    field public boolean mSkipSolver;
+    field protected androidx.constraintlayout.core.LinearSystem! mSystem;
+    field public int mVerticalChainsSize;
+    field public boolean mVerticalWrapOptimized;
+    field public int mWrapFixedHeight;
+    field public int mWrapFixedWidth;
+  }
+
+  public class Flow extends androidx.constraintlayout.core.widgets.VirtualLayout {
+    ctor public Flow();
+    method public float getMaxElementsWrap();
+    method public void setFirstHorizontalBias(float);
+    method public void setFirstHorizontalStyle(int);
+    method public void setFirstVerticalBias(float);
+    method public void setFirstVerticalStyle(int);
+    method public void setHorizontalAlign(int);
+    method public void setHorizontalBias(float);
+    method public void setHorizontalGap(int);
+    method public void setHorizontalStyle(int);
+    method public void setLastHorizontalBias(float);
+    method public void setLastHorizontalStyle(int);
+    method public void setLastVerticalBias(float);
+    method public void setLastVerticalStyle(int);
+    method public void setMaxElementsWrap(int);
+    method public void setOrientation(int);
+    method public void setVerticalAlign(int);
+    method public void setVerticalBias(float);
+    method public void setVerticalGap(int);
+    method public void setVerticalStyle(int);
+    method public void setWrapMode(int);
+    field public static final int HORIZONTAL_ALIGN_CENTER = 2; // 0x2
+    field public static final int HORIZONTAL_ALIGN_END = 1; // 0x1
+    field public static final int HORIZONTAL_ALIGN_START = 0; // 0x0
+    field public static final int VERTICAL_ALIGN_BASELINE = 3; // 0x3
+    field public static final int VERTICAL_ALIGN_BOTTOM = 1; // 0x1
+    field public static final int VERTICAL_ALIGN_CENTER = 2; // 0x2
+    field public static final int VERTICAL_ALIGN_TOP = 0; // 0x0
+    field public static final int WRAP_ALIGNED = 2; // 0x2
+    field public static final int WRAP_CHAIN = 1; // 0x1
+    field public static final int WRAP_CHAIN_NEW = 3; // 0x3
+    field public static final int WRAP_NONE = 0; // 0x0
+  }
+
+  public class Guideline extends androidx.constraintlayout.core.widgets.ConstraintWidget {
+    ctor public Guideline();
+    method public void cyclePosition();
+    method public androidx.constraintlayout.core.widgets.ConstraintAnchor! getAnchor();
+    method public int getMinimumPosition();
+    method public int getOrientation();
+    method public int getRelativeBegin();
+    method public int getRelativeBehaviour();
+    method public int getRelativeEnd();
+    method public float getRelativePercent();
+    method public boolean isPercent();
+    method public void setFinalValue(int);
+    method public void setGuideBegin(int);
+    method public void setGuideEnd(int);
+    method public void setGuidePercent(float);
+    method public void setGuidePercent(int);
+    method public void setMinimumPosition(int);
+    method public void setOrientation(int);
+    field public static final int HORIZONTAL = 0; // 0x0
+    field public static final int RELATIVE_BEGIN = 1; // 0x1
+    field public static final int RELATIVE_END = 2; // 0x2
+    field public static final int RELATIVE_PERCENT = 0; // 0x0
+    field public static final int RELATIVE_UNKNOWN = -1; // 0xffffffff
+    field public static final int VERTICAL = 1; // 0x1
+    field protected boolean mGuidelineUseRtl;
+    field protected int mRelativeBegin;
+    field protected int mRelativeEnd;
+    field protected float mRelativePercent;
+  }
+
+  public interface Helper {
+    method public void add(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public void removeAllIds();
+    method public void updateConstraints(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!);
+  }
+
+  public class HelperWidget extends androidx.constraintlayout.core.widgets.ConstraintWidget implements androidx.constraintlayout.core.widgets.Helper {
+    ctor public HelperWidget();
+    method public void add(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public void addDependents(java.util.ArrayList<androidx.constraintlayout.core.widgets.analyzer.WidgetGroup!>!, int, androidx.constraintlayout.core.widgets.analyzer.WidgetGroup!);
+    method public int findGroupInDependents(int);
+    method public void removeAllIds();
+    method public void updateConstraints(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!);
+    field public androidx.constraintlayout.core.widgets.ConstraintWidget![]! mWidgets;
+    field public int mWidgetsCount;
+  }
+
+  public class Optimizer {
+    ctor public Optimizer();
+    method public static final boolean enabled(int, int);
+    field public static final int OPTIMIZATION_BARRIER = 2; // 0x2
+    field public static final int OPTIMIZATION_CACHE_MEASURES = 256; // 0x100
+    field public static final int OPTIMIZATION_CHAIN = 4; // 0x4
+    field public static final int OPTIMIZATION_DEPENDENCY_ORDERING = 512; // 0x200
+    field public static final int OPTIMIZATION_DIMENSIONS = 8; // 0x8
+    field public static final int OPTIMIZATION_DIRECT = 1; // 0x1
+    field public static final int OPTIMIZATION_GRAPH = 64; // 0x40
+    field public static final int OPTIMIZATION_GRAPH_WRAP = 128; // 0x80
+    field public static final int OPTIMIZATION_GROUPING = 1024; // 0x400
+    field public static final int OPTIMIZATION_GROUPS = 32; // 0x20
+    field public static final int OPTIMIZATION_NONE = 0; // 0x0
+    field public static final int OPTIMIZATION_RATIO = 16; // 0x10
+    field public static final int OPTIMIZATION_STANDARD = 257; // 0x101
+  }
+
+  public class Placeholder extends androidx.constraintlayout.core.widgets.VirtualLayout {
+    ctor public Placeholder();
+  }
+
+  public class Rectangle {
+    ctor public Rectangle();
+    method public boolean contains(int, int);
+    method public int getCenterX();
+    method public int getCenterY();
+    method public void setBounds(int, int, int, int);
+    field public int height;
+    field public int width;
+    field public int x;
+    field public int y;
+  }
+
+  public class VirtualLayout extends androidx.constraintlayout.core.widgets.HelperWidget {
+    ctor public VirtualLayout();
+    method public void applyRtl(boolean);
+    method public void captureWidgets();
+    method public boolean contains(java.util.HashSet<androidx.constraintlayout.core.widgets.ConstraintWidget!>!);
+    method public int getMeasuredHeight();
+    method public int getMeasuredWidth();
+    method public int getPaddingBottom();
+    method public int getPaddingLeft();
+    method public int getPaddingRight();
+    method public int getPaddingTop();
+    method protected void measure(androidx.constraintlayout.core.widgets.ConstraintWidget!, androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour!, int, androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour!, int);
+    method public void measure(int, int, int, int);
+    method protected boolean measureChildren();
+    method public boolean needSolverPass();
+    method protected void needsCallbackFromSolver(boolean);
+    method public void setMeasure(int, int);
+    method public void setPadding(int);
+    method public void setPaddingBottom(int);
+    method public void setPaddingEnd(int);
+    method public void setPaddingLeft(int);
+    method public void setPaddingRight(int);
+    method public void setPaddingStart(int);
+    method public void setPaddingTop(int);
+    field protected androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.Measure! mMeasure;
+  }
+
+  public class WidgetContainer extends androidx.constraintlayout.core.widgets.ConstraintWidget {
+    ctor public WidgetContainer();
+    ctor public WidgetContainer(int, int);
+    ctor public WidgetContainer(int, int, int, int);
+    method public void add(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public void add(androidx.constraintlayout.core.widgets.ConstraintWidget!...!);
+    method public java.util.ArrayList<androidx.constraintlayout.core.widgets.ConstraintWidget!>! getChildren();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidgetContainer! getRootConstraintContainer();
+    method public void layout();
+    method public void remove(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public void removeAllChildren();
+    field public java.util.ArrayList<androidx.constraintlayout.core.widgets.ConstraintWidget!>! mChildren;
+  }
+
+}
+
+package androidx.constraintlayout.core.widgets.analyzer {
+
+  public class BasicMeasure {
+    ctor public BasicMeasure(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!);
+    method public long solverMeasure(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!, int, int, int, int, int, int, int, int, int);
+    method public void updateHierarchy(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!);
+    field public static final int AT_MOST = -2147483648; // 0x80000000
+    field public static final int EXACTLY = 1073741824; // 0x40000000
+    field public static final int FIXED = -3; // 0xfffffffd
+    field public static final int MATCH_PARENT = -1; // 0xffffffff
+    field public static final int UNSPECIFIED = 0; // 0x0
+    field public static final int WRAP_CONTENT = -2; // 0xfffffffe
+  }
+
+  public static class BasicMeasure.Measure {
+    ctor public BasicMeasure.Measure();
+    field public static int SELF_DIMENSIONS;
+    field public static int TRY_GIVEN_DIMENSIONS;
+    field public static int USE_GIVEN_DIMENSIONS;
+    field public androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour! horizontalBehavior;
+    field public int horizontalDimension;
+    field public int measureStrategy;
+    field public int measuredBaseline;
+    field public boolean measuredHasBaseline;
+    field public int measuredHeight;
+    field public boolean measuredNeedsSolverPass;
+    field public int measuredWidth;
+    field public androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour! verticalBehavior;
+    field public int verticalDimension;
+  }
+
+  public static interface BasicMeasure.Measurer {
+    method public void didMeasures();
+    method public void measure(androidx.constraintlayout.core.widgets.ConstraintWidget!, androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.Measure!);
+  }
+
+  public class ChainRun extends androidx.constraintlayout.core.widgets.analyzer.WidgetRun {
+    ctor public ChainRun(androidx.constraintlayout.core.widgets.ConstraintWidget!, int);
+    method public void applyToWidget();
+  }
+
+  public interface Dependency {
+    method public void update(androidx.constraintlayout.core.widgets.analyzer.Dependency!);
+  }
+
+  public class DependencyGraph {
+    ctor public DependencyGraph(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!);
+    method public void buildGraph();
+    method public void buildGraph(java.util.ArrayList<androidx.constraintlayout.core.widgets.analyzer.WidgetRun!>!);
+    method public void defineTerminalWidgets(androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour!, androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour!);
+    method public boolean directMeasure(boolean);
+    method public boolean directMeasureSetup(boolean);
+    method public boolean directMeasureWithOrientation(boolean, int);
+    method public void invalidateGraph();
+    method public void invalidateMeasures();
+    method public void measureWidgets();
+    method public void setMeasurer(androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.Measurer!);
+  }
+
+  public class DependencyNode implements androidx.constraintlayout.core.widgets.analyzer.Dependency {
+    ctor public DependencyNode(androidx.constraintlayout.core.widgets.analyzer.WidgetRun!);
+    method public void addDependency(androidx.constraintlayout.core.widgets.analyzer.Dependency!);
+    method public void clear();
+    method public String! name();
+    method public void resolve(int);
+    method public void update(androidx.constraintlayout.core.widgets.analyzer.Dependency!);
+    field public boolean delegateToWidgetRun;
+    field public boolean readyToSolve;
+    field public boolean resolved;
+    field public androidx.constraintlayout.core.widgets.analyzer.Dependency! updateDelegate;
+    field public int value;
+  }
+
+  public class Direct {
+    ctor public Direct();
+    method public static String! ls(int);
+    method public static boolean solveChain(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!, androidx.constraintlayout.core.LinearSystem!, int, int, androidx.constraintlayout.core.widgets.ChainHead!, boolean, boolean, boolean);
+    method public static void solvingPass(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!, androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.Measurer!);
+  }
+
+  public class Grouping {
+    ctor public Grouping();
+    method public static androidx.constraintlayout.core.widgets.analyzer.WidgetGroup! findDependents(androidx.constraintlayout.core.widgets.ConstraintWidget!, int, java.util.ArrayList<androidx.constraintlayout.core.widgets.analyzer.WidgetGroup!>!, androidx.constraintlayout.core.widgets.analyzer.WidgetGroup!);
+    method public static boolean simpleSolvingPass(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!, androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.Measurer!);
+    method public static boolean validInGroup(androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour!, androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour!, androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour!, androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour!);
+  }
+
+  public class HorizontalWidgetRun extends androidx.constraintlayout.core.widgets.analyzer.WidgetRun {
+    ctor public HorizontalWidgetRun(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public void applyToWidget();
+  }
+
+  public class VerticalWidgetRun extends androidx.constraintlayout.core.widgets.analyzer.WidgetRun {
+    ctor public VerticalWidgetRun(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public void applyToWidget();
+    field public androidx.constraintlayout.core.widgets.analyzer.DependencyNode! baseline;
+  }
+
+  public class WidgetGroup {
+    ctor public WidgetGroup(int);
+    method public boolean add(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method public void apply();
+    method public void cleanup(java.util.ArrayList<androidx.constraintlayout.core.widgets.analyzer.WidgetGroup!>!);
+    method public void clear();
+    method public int getId();
+    method public int getOrientation();
+    method public boolean intersectWith(androidx.constraintlayout.core.widgets.analyzer.WidgetGroup!);
+    method public boolean isAuthoritative();
+    method public int measureWrap(androidx.constraintlayout.core.LinearSystem!, int);
+    method public void moveTo(int, androidx.constraintlayout.core.widgets.analyzer.WidgetGroup!);
+    method public void setAuthoritative(boolean);
+    method public void setOrientation(int);
+    method public int size();
+  }
+
+  public abstract class WidgetRun implements androidx.constraintlayout.core.widgets.analyzer.Dependency {
+    ctor public WidgetRun(androidx.constraintlayout.core.widgets.ConstraintWidget!);
+    method protected final void addTarget(androidx.constraintlayout.core.widgets.analyzer.DependencyNode!, androidx.constraintlayout.core.widgets.analyzer.DependencyNode!, int);
+    method protected final void addTarget(androidx.constraintlayout.core.widgets.analyzer.DependencyNode!, androidx.constraintlayout.core.widgets.analyzer.DependencyNode!, int, androidx.constraintlayout.core.widgets.analyzer.DimensionDependency!);
+    method protected final int getLimitedDimension(int, int);
+    method protected final androidx.constraintlayout.core.widgets.analyzer.DependencyNode! getTarget(androidx.constraintlayout.core.widgets.ConstraintAnchor!);
+    method protected final androidx.constraintlayout.core.widgets.analyzer.DependencyNode! getTarget(androidx.constraintlayout.core.widgets.ConstraintAnchor!, int);
+    method public long getWrapDimension();
+    method public boolean isCenterConnection();
+    method public boolean isDimensionResolved();
+    method public boolean isResolved();
+    method public void update(androidx.constraintlayout.core.widgets.analyzer.Dependency!);
+    method protected void updateRunCenter(androidx.constraintlayout.core.widgets.analyzer.Dependency!, androidx.constraintlayout.core.widgets.ConstraintAnchor!, androidx.constraintlayout.core.widgets.ConstraintAnchor!, int);
+    method protected void updateRunEnd(androidx.constraintlayout.core.widgets.analyzer.Dependency!);
+    method protected void updateRunStart(androidx.constraintlayout.core.widgets.analyzer.Dependency!);
+    method public long wrapSize(int);
+    field public androidx.constraintlayout.core.widgets.analyzer.DependencyNode! end;
+    field protected androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour! mDimensionBehavior;
+    field protected androidx.constraintlayout.core.widgets.analyzer.WidgetRun.RunType! mRunType;
+    field public int matchConstraintsType;
+    field public int orientation;
+    field public androidx.constraintlayout.core.widgets.analyzer.DependencyNode! start;
+  }
+
+}
+
diff --git a/constraintlayout/constraintlayout-core/api/restricted_current.txt b/constraintlayout/constraintlayout-core/api/restricted_current.txt
index 0b2ac8fe..daaf9e5 100644
--- a/constraintlayout/constraintlayout-core/api/restricted_current.txt
+++ b/constraintlayout/constraintlayout-core/api/restricted_current.txt
@@ -2601,7 +2601,7 @@
     ctor public GridReference(androidx.constraintlayout.core.state.State, androidx.constraintlayout.core.state.State.Helper);
     method public String? getColumnWeights();
     method public int getColumnsSet();
-    method public int[] getFlags();
+    method public int getFlags();
     method public float getHorizontalGaps();
     method public int getOrientation();
     method public int getPaddingBottom();
@@ -2615,7 +2615,7 @@
     method public float getVerticalGaps();
     method public void setColumnWeights(String);
     method public void setColumnsSet(int);
-    method public void setFlags(int[]);
+    method public void setFlags(int);
     method public void setFlags(String);
     method public void setHorizontalGaps(float);
     method public void setOrientation(int);
@@ -2662,7 +2662,7 @@
     ctor public GridCore(int, int);
     method public String? getColumnWeights();
     method public androidx.constraintlayout.core.widgets.ConstraintWidgetContainer? getContainer();
-    method public int[] getFlags();
+    method public int getFlags();
     method public float getHorizontalGaps();
     method public int getOrientation();
     method public String? getRowWeights();
@@ -2670,7 +2670,7 @@
     method public void setColumnWeights(String);
     method public void setColumns(int);
     method public void setContainer(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer);
-    method public void setFlags(int[]);
+    method public void setFlags(int);
     method public void setHorizontalGaps(float);
     method public void setOrientation(int);
     method public void setRowWeights(String);
@@ -2679,8 +2679,8 @@
     method public void setSpans(CharSequence);
     method public void setVerticalGaps(float);
     field public static final int HORIZONTAL = 0; // 0x0
-    field public static final int SPANS_RESPECT_WIDGET_ORDER = 1; // 0x1
-    field public static final int SUB_GRID_BY_COL_ROW = 0; // 0x0
+    field public static final int SPANS_RESPECT_WIDGET_ORDER = 2; // 0x2
+    field public static final int SUB_GRID_BY_COL_ROW = 1; // 0x1
     field public static final int VERTICAL = 1; // 0x1
   }
 
diff --git a/constraintlayout/constraintlayout-core/src/main/java/androidx/constraintlayout/core/state/ConstraintSetParser.java b/constraintlayout/constraintlayout-core/src/main/java/androidx/constraintlayout/core/state/ConstraintSetParser.java
index 5f97bd2..efd960d 100644
--- a/constraintlayout/constraintlayout-core/src/main/java/androidx/constraintlayout/core/state/ConstraintSetParser.java
+++ b/constraintlayout/constraintlayout-core/src/main/java/androidx/constraintlayout/core/state/ConstraintSetParser.java
@@ -935,7 +935,6 @@
                                       String name,
                                       LayoutVariables layoutVariables,
                                       CLObject element) throws CLParsingException {
-
         GridReference grid = state.getGrid(name, gridType);
 
         for (String param : element.names()) {
@@ -1001,11 +1000,12 @@
                     }
                     break;
                 case "padding":
+                    // Note that padding is currently not properly handled in GridCore
                     CLElement paddingObject = element.get(param);
-                    int paddingStart = 0;
-                    int paddingTop = 0;
-                    int paddingEnd = 0;
-                    int paddingBottom = 0;
+                    float paddingStart = 0;
+                    float paddingTop = 0;
+                    float paddingEnd = 0;
+                    float paddingBottom = 0;
                     if (paddingObject instanceof CLArray && ((CLArray) paddingObject).size() > 1) {
                         paddingStart = ((CLArray) paddingObject).getInt(0);
                         paddingEnd = paddingStart;
@@ -1026,28 +1026,30 @@
                         paddingEnd = paddingStart;
                         paddingBottom = paddingStart;
                     }
-                    grid.setPaddingStart(paddingStart);
-                    grid.setPaddingTop(paddingTop);
-                    grid.setPaddingEnd(paddingEnd);
-                    grid.setPaddingBottom(paddingBottom);
+                    grid.setPaddingStart(Math.round(toPix(state, paddingStart)));
+                    grid.setPaddingTop(Math.round(toPix(state, paddingTop)));
+                    grid.setPaddingEnd(Math.round(toPix(state, paddingEnd)));
+                    grid.setPaddingBottom(Math.round(toPix(state, paddingBottom)));
                     break;
                 case "flags":
-                    String flags = element.get(param).content();
-                    if (flags != null && flags.length() > 0) {
+                    int flagValue = 0;
+                    String flags = "";
+                    try {
+                        CLElement obj  = element.get(param);
+                        if (obj instanceof CLNumber) {
+                            flagValue = obj.getInt();
+                        } else {
+                            flags = obj.content();
+                        }
+                    } catch (Exception ex) {
+                        System.err.println("Error parsing grid flags " + ex);
+                    }
+
+                    if (flags != null && !flags.isEmpty()) {
+                        // In older APIs, the flags may still be defined as a String
                         grid.setFlags(flags);
                     } else {
-                        CLArray flagArray = element.getArrayOrNull(param);
-                        flags = "";
-                        if (flagArray != null) {
-                            for (int i = 0; i < flagArray.size(); i++) {
-                                String flag = flagArray.get(i).content();
-                                flags += flag;
-                                if (i != flagArray.size() - 1) {
-                                    flags += "|";
-                                }
-                            }
-                            grid.setFlags(flags);
-                        }
+                        grid.setFlags(flagValue);
                     }
                     break;
                 default:
@@ -1160,10 +1162,10 @@
                     break;
                 case "padding":
                     CLElement paddingObject = element.get(param);
-                    int paddingLeft = 0;
-                    int paddingTop = 0;
-                    int paddingRight = 0;
-                    int paddingBottom = 0;
+                    float paddingLeft = 0;
+                    float paddingTop = 0;
+                    float paddingRight = 0;
+                    float paddingBottom = 0;
                     if (paddingObject instanceof CLArray && ((CLArray) paddingObject).size() > 1) {
                         paddingLeft = ((CLArray) paddingObject).getInt(0);
                         paddingRight = paddingLeft;
@@ -1184,10 +1186,10 @@
                         paddingRight = paddingLeft;
                         paddingBottom = paddingLeft;
                     }
-                    flow.setPaddingLeft(paddingLeft);
-                    flow.setPaddingTop(paddingTop);
-                    flow.setPaddingRight(paddingRight);
-                    flow.setPaddingBottom(paddingBottom);
+                    flow.setPaddingLeft(Math.round(toPix(state, paddingLeft)));
+                    flow.setPaddingTop(Math.round(toPix(state, paddingTop)));
+                    flow.setPaddingRight(Math.round(toPix(state, paddingRight)));
+                    flow.setPaddingBottom(Math.round(toPix(state, paddingBottom)));
                     break;
                 case "vAlign":
                     String vAlignValue = element.get(param).content();
diff --git a/constraintlayout/constraintlayout-core/src/main/java/androidx/constraintlayout/core/state/helpers/GridReference.java b/constraintlayout/constraintlayout-core/src/main/java/androidx/constraintlayout/core/state/helpers/GridReference.java
index 8942bfc..d2168ad 100644
--- a/constraintlayout/constraintlayout-core/src/main/java/androidx/constraintlayout/core/state/helpers/GridReference.java
+++ b/constraintlayout/constraintlayout-core/src/main/java/androidx/constraintlayout/core/state/helpers/GridReference.java
@@ -23,15 +23,13 @@
 import androidx.constraintlayout.core.utils.GridCore;
 import androidx.constraintlayout.core.widgets.HelperWidget;
 
-import java.util.ArrayList;
-
 /**
  * A HelperReference of a Grid Helper that helps enable Grid in Compose
  */
 public class GridReference extends HelperReference {
 
-    private static final String SPANS_RESPECT_WIDGET_ORDER = "spansrespectwidgetorder";
-    private static final String SUB_GRID_BY_COL_ROW = "subgridbycolrow";
+    private static final String SPANS_RESPECT_WIDGET_ORDER_STRING = "spansrespectwidgetorder";
+    private static final String SUB_GRID_BY_COL_ROW_STRING = "subgridbycolrow";
 
     public GridReference(@NonNull State state, @NonNull State.Helper type) {
         super(state, type);
@@ -113,9 +111,9 @@
     private String mSkips;
 
     /**
-     * All the flags of a Grid
+     * An int value containing flag information.
      */
-    private int[] mFlags;
+    private int mFlags;
 
     /**
      * get padding left
@@ -183,18 +181,17 @@
 
     /**
      * Get all the flags of a Grid
-     * @return a String array containing all the flags
+     * @return an int value containing flag information
      */
-    @NonNull
-    public int[] getFlags() {
+    public int getFlags() {
         return mFlags;
     }
 
     /**
      * Set flags of a Grid
-     * @param flags a String array containing all the flags
+     * @param flags an int value containing flag information
      */
-    public void setFlags(@NonNull int[] flags) {
+    public void setFlags(int flags) {
         mFlags = flags;
     }
 
@@ -203,29 +200,22 @@
      * @param flags a String containing all the flags
      */
     public void setFlags(@NonNull String flags) {
-        if (flags.length() == 0) {
+        if (flags.isEmpty()) {
             return;
         }
 
         String[] strArr = flags.split("\\|");
-        ArrayList<Integer> flagList = new ArrayList<>();
-        for (String flag: strArr) {
-            switch (flag.toLowerCase()) {
-                case SUB_GRID_BY_COL_ROW:
-                    flagList.add(0);
+        mFlags = 0;
+        for (String str: strArr) {
+            switch (str.toLowerCase()) {
+                case SUB_GRID_BY_COL_ROW_STRING:
+                    mFlags |= 1;
                     break;
-                case SPANS_RESPECT_WIDGET_ORDER:
-                    flagList.add(1);
+                case SPANS_RESPECT_WIDGET_ORDER_STRING:
+                    mFlags |= 2;
                     break;
             }
         }
-        int[] flagArr = new int[flagList.size()];
-        int i = 0;
-        for (int flag: flagList) {
-            flagArr[i++] = flag;
-        }
-
-        mFlags = flagArr;
     }
 
     /**
@@ -434,25 +424,28 @@
             mGrid.setVerticalGaps(mVerticalGaps);
         }
 
-        if (mRowWeights != null && !mRowWeights.equals("")) {
+        if (mRowWeights != null && !mRowWeights.isEmpty()) {
             mGrid.setRowWeights(mRowWeights);
         }
 
-        if (mColumnWeights != null && !mColumnWeights.equals("")) {
+        if (mColumnWeights != null && !mColumnWeights.isEmpty()) {
             mGrid.setColumnWeights(mColumnWeights);
         }
 
-        if (mSpans != null && !mSpans.equals("")) {
+        if (mSpans != null && !mSpans.isEmpty()) {
             mGrid.setSpans(mSpans);
         }
 
-        if (mSkips != null && !mSkips.equals("")) {
+        if (mSkips != null && !mSkips.isEmpty()) {
             mGrid.setSkips(mSkips);
         }
 
-        if (mFlags != null && mFlags.length > 0) {
-            mGrid.setFlags(mFlags);
-        }
+        mGrid.setFlags(mFlags);
+
+        mGrid.setPaddingStart(mPaddingStart);
+        mGrid.setPaddingEnd(mPaddingEnd);
+        mGrid.setPaddingTop(mPaddingTop);
+        mGrid.setPaddingBottom(mPaddingBottom);
 
         // General attributes of a widget
         applyBase();
diff --git a/constraintlayout/constraintlayout-core/src/main/java/androidx/constraintlayout/core/utils/GridCore.java b/constraintlayout/constraintlayout-core/src/main/java/androidx/constraintlayout/core/utils/GridCore.java
index 18d7efc..7424e64c 100644
--- a/constraintlayout/constraintlayout-core/src/main/java/androidx/constraintlayout/core/utils/GridCore.java
+++ b/constraintlayout/constraintlayout-core/src/main/java/androidx/constraintlayout/core/utils/GridCore.java
@@ -33,11 +33,16 @@
  * The Grid Helper in the Core library that helps to enable Grid in Compose
  */
 public class GridCore extends VirtualLayout {
+    // TODO: Handle padding from VirtualLayout. It should represent the padding applied around the
+    //  Grid itself. Usually decreasing its size.
 
     public static final int HORIZONTAL = 0;
     public static final int VERTICAL = 1;
-    public static final int SUB_GRID_BY_COL_ROW = 0;
-    public static final int SPANS_RESPECT_WIDGET_ORDER = 1;
+
+    // Flags using incremental bit positions
+    public static final int SUB_GRID_BY_COL_ROW = 1;
+    public static final int SPANS_RESPECT_WIDGET_ORDER = 2;
+
     private static final int DEFAULT_SIZE = 3; // default rows and columns.
     private static final int MAX_ROWS = 50; // maximum number of rows can be specified.
     private static final int MAX_COLUMNS = 50; // maximum number of columns can be specified.
@@ -137,9 +142,9 @@
     private int[][] mConstraintMatrix;
 
     /**
-     * A String array stores the flags
+     * An int value containing flag information.
      */
-    private int[] mFlags;
+    private int mFlags;
 
     /**
      * A int matrix to store the span related information
@@ -151,17 +156,6 @@
      */
     private int mSpanIndex = 0;
 
-    /**
-     * Flag to respect the order of the Widgets when arranging for span
-     */
-    private boolean mSpansRespectWidgetOrder = false;
-
-    /**
-     * Flag to reverse the order of width/height specified in span
-     * e.g., 1:3x2 -> 1:2x3
-     */
-    private boolean mSubGridByColRow = false;
-
     public GridCore() {
         updateActualRowsAndColumns();
         initMatrices();
@@ -391,18 +385,17 @@
 
     /**
      * Get all the flags of a Grid
-     * @return a int array containing all the flags
+     * @return an int value containing flag information
      */
-    @NonNull
-    public int[] getFlags() {
+    public int getFlags() {
         return mFlags;
     }
 
     /**
      * Set flags of a Grid
-     * @param flags a int array containing all the flags
+     * @param flags an int value containing flag information
      */
-    public void setFlags(@NonNull int[] flags) {
+    public void setFlags(int flags) {
         mFlags = flags;
     }
 
@@ -412,7 +405,7 @@
      * @param spansMatrix a int matrix that contains span information
      */
     private void handleSpans(int[][] spansMatrix) {
-        if (mSpansRespectWidgetOrder) {
+        if (isSpansRespectWidgetOrder()) {
             return;
         }
 
@@ -450,7 +443,7 @@
                 return;
             }
 
-            if (mSpansRespectWidgetOrder && mSpanMatrix != null) {
+            if (isSpansRespectWidgetOrder() && mSpanMatrix != null) {
                 if (mSpanIndex < mSpanMatrix.length && mSpanMatrix[mSpanIndex][0] == position) {
                     // when invoke getNextPosition this position would be set to false
                     mPositionMatrix[row][col] = true;
@@ -479,8 +472,6 @@
             return;
         }
 
-        handleFlags();
-
         if (isUpdate) {
             for (int i = 0; i < mPositionMatrix.length; i++) {
                 for (int j = 0; j < mPositionMatrix[0].length; j++) {
@@ -582,7 +573,9 @@
     }
 
     /**
-     * parse the weights/pads in the string format into a float array
+     * Parse the weights/pads in the string format into a float array. Note that weight are
+     * normally expected to match the size. But in case they don't, we trim or pad the weight with
+     * trailing 1 to match the expected size.
      *
      * @param size size of the return array
      * @param str  weights/pads in a string format
@@ -594,13 +587,22 @@
         }
 
         String[] values = str.split(",");
-        if (values.length != size) {
-            return null;
-        }
 
+        // Return array must be of the expected size, effectively trimming excess weights
         float[] arr = new float[size];
         for (int i = 0; i < arr.length; i++) {
-            arr[i] = Float.parseFloat(values[i].trim());
+            if (i < values.length) {
+                try {
+                    arr[i] = Float.parseFloat(values[i]);
+                } catch (Exception e) {
+                    System.err.println("Error parsing `" + values[i] + "`: " + e.getMessage());
+                    // Fallback to 1f.
+                    arr[i] = 1f;
+                }
+            } else {
+                // Fill in missing weights with 1f
+                arr[i] = 1f;
+            }
         }
         return arr;
     }
@@ -912,7 +914,7 @@
                     indexAndSpan = spans[i].trim().split(":");
                     rowAndCol = indexAndSpan[1].split("x");
                     spanMatrix[i][0] = Integer.parseInt(indexAndSpan[0]);
-                    if (mSubGridByColRow) {
+                    if (isSubGridByColRow()) {
                         spanMatrix[i][1] = Integer.parseInt(rowAndCol[1]);
                         spanMatrix[i][2] = Integer.parseInt(rowAndCol[0]);
                     } else {
@@ -983,23 +985,18 @@
     }
 
     /**
-     * If flags are given, set the values of the corresponding variables to true.
+     * Flag to implicitly reverse the order of width/height specified in spans & skips.
+     * E.g.: 1:3x2 is read as 1:2x3
      */
-    private void handleFlags() {
-        if (mFlags == null) {
-            return;
-        }
+    private boolean isSubGridByColRow() {
+        return (mFlags & SUB_GRID_BY_COL_ROW) > 0;
+    }
 
-        for (int flag: mFlags) {
-            switch (flag) {
-                case SPANS_RESPECT_WIDGET_ORDER:
-                    mSpansRespectWidgetOrder = true;
-                    break;
-                case SUB_GRID_BY_COL_ROW:
-                    mSubGridByColRow = true;
-                    break;
-            }
-        }
+    /**
+     * Flag to respect the order of the Widgets when arranging for spans.
+     */
+    private boolean isSpansRespectWidgetOrder() {
+        return (mFlags & SPANS_RESPECT_WIDGET_ORDER) > 0;
     }
 
     @Override
diff --git a/constraintlayout/constraintlayout/api/2.2.0-beta01.txt b/constraintlayout/constraintlayout/api/2.2.0-beta01.txt
new file mode 100644
index 0000000..2d187a8
--- /dev/null
+++ b/constraintlayout/constraintlayout/api/2.2.0-beta01.txt
@@ -0,0 +1,1714 @@
+// Signature format: 4.0
+package androidx.constraintlayout.helper.widget {
+
+  public class Carousel extends androidx.constraintlayout.motion.widget.MotionHelper {
+    ctor public Carousel(android.content.Context!);
+    ctor public Carousel(android.content.Context!, android.util.AttributeSet!);
+    ctor public Carousel(android.content.Context!, android.util.AttributeSet!, int);
+    method public int getCount();
+    method public int getCurrentIndex();
+    method public boolean isInfinite();
+    method public void jumpToIndex(int);
+    method public void refresh();
+    method public void setAdapter(androidx.constraintlayout.helper.widget.Carousel.Adapter!);
+    method public void setInfinite(boolean);
+    method public void transitionToIndex(int, int);
+    field public static final int TOUCH_UP_CARRY_ON = 2; // 0x2
+    field public static final int TOUCH_UP_IMMEDIATE_STOP = 1; // 0x1
+  }
+
+  public static interface Carousel.Adapter {
+    method public int count();
+    method public void onNewItem(int);
+    method public void populate(android.view.View!, int);
+  }
+
+  public class CircularFlow extends androidx.constraintlayout.widget.VirtualLayout {
+    ctor public CircularFlow(android.content.Context!);
+    ctor public CircularFlow(android.content.Context!, android.util.AttributeSet!);
+    ctor public CircularFlow(android.content.Context!, android.util.AttributeSet!, int);
+    method public void addViewToCircularFlow(android.view.View!, int, float);
+    method public float[]! getAngles();
+    method public int[]! getRadius();
+    method public boolean isUpdatable(android.view.View!);
+    method public void setDefaultAngle(float);
+    method public void setDefaultRadius(int);
+    method public void updateAngle(android.view.View!, float);
+    method public void updateRadius(android.view.View!, int);
+    method public void updateReference(android.view.View!, int, float);
+  }
+
+  public class Flow extends androidx.constraintlayout.widget.VirtualLayout {
+    ctor public Flow(android.content.Context!);
+    ctor public Flow(android.content.Context!, android.util.AttributeSet!);
+    ctor public Flow(android.content.Context!, android.util.AttributeSet!, int);
+    method public void setFirstHorizontalBias(float);
+    method public void setFirstHorizontalStyle(int);
+    method public void setFirstVerticalBias(float);
+    method public void setFirstVerticalStyle(int);
+    method public void setHorizontalAlign(int);
+    method public void setHorizontalBias(float);
+    method public void setHorizontalGap(int);
+    method public void setHorizontalStyle(int);
+    method public void setLastHorizontalBias(float);
+    method public void setLastHorizontalStyle(int);
+    method public void setLastVerticalBias(float);
+    method public void setLastVerticalStyle(int);
+    method public void setMaxElementsWrap(int);
+    method public void setOrientation(int);
+    method public void setPadding(int);
+    method public void setPaddingBottom(int);
+    method public void setPaddingLeft(int);
+    method public void setPaddingRight(int);
+    method public void setPaddingTop(int);
+    method public void setVerticalAlign(int);
+    method public void setVerticalBias(float);
+    method public void setVerticalGap(int);
+    method public void setVerticalStyle(int);
+    method public void setWrapMode(int);
+    field public static final int CHAIN_PACKED = 2; // 0x2
+    field public static final int CHAIN_SPREAD = 0; // 0x0
+    field public static final int CHAIN_SPREAD_INSIDE = 1; // 0x1
+    field public static final int HORIZONTAL = 0; // 0x0
+    field public static final int HORIZONTAL_ALIGN_CENTER = 2; // 0x2
+    field public static final int HORIZONTAL_ALIGN_END = 1; // 0x1
+    field public static final int HORIZONTAL_ALIGN_START = 0; // 0x0
+    field public static final int VERTICAL = 1; // 0x1
+    field public static final int VERTICAL_ALIGN_BASELINE = 3; // 0x3
+    field public static final int VERTICAL_ALIGN_BOTTOM = 1; // 0x1
+    field public static final int VERTICAL_ALIGN_CENTER = 2; // 0x2
+    field public static final int VERTICAL_ALIGN_TOP = 0; // 0x0
+    field public static final int WRAP_ALIGNED = 2; // 0x2
+    field public static final int WRAP_CHAIN = 1; // 0x1
+    field public static final int WRAP_NONE = 0; // 0x0
+  }
+
+  public class Grid extends androidx.constraintlayout.widget.VirtualLayout {
+    ctor public Grid(android.content.Context!);
+    ctor public Grid(android.content.Context!, android.util.AttributeSet!);
+    ctor public Grid(android.content.Context!, android.util.AttributeSet!, int);
+    method public String! getColumnWeights();
+    method public int getColumns();
+    method public float getHorizontalGaps();
+    method public int getOrientation();
+    method public String! getRowWeights();
+    method public int getRows();
+    method public String! getSkips();
+    method public String! getSpans();
+    method public float getVerticalGaps();
+    method public void setColumnWeights(String!);
+    method public void setColumns(int);
+    method public void setHorizontalGaps(float);
+    method public void setOrientation(int);
+    method public void setRowWeights(String!);
+    method public void setRows(int);
+    method public void setSkips(String!);
+    method public void setSpans(CharSequence!);
+    method public void setVerticalGaps(float);
+    field public static final int HORIZONTAL = 0; // 0x0
+    field public static final int VERTICAL = 1; // 0x1
+  }
+
+  public class Layer extends androidx.constraintlayout.widget.ConstraintHelper {
+    ctor public Layer(android.content.Context!);
+    ctor public Layer(android.content.Context!, android.util.AttributeSet!);
+    ctor public Layer(android.content.Context!, android.util.AttributeSet!, int);
+    method protected void calcCenters();
+    field protected float mComputedCenterX;
+    field protected float mComputedCenterY;
+    field protected float mComputedMaxX;
+    field protected float mComputedMaxY;
+    field protected float mComputedMinX;
+    field protected float mComputedMinY;
+  }
+
+  public class MotionEffect extends androidx.constraintlayout.motion.widget.MotionHelper {
+    ctor public MotionEffect(android.content.Context!);
+    ctor public MotionEffect(android.content.Context!, android.util.AttributeSet!);
+    ctor public MotionEffect(android.content.Context!, android.util.AttributeSet!, int);
+    field public static final int AUTO = -1; // 0xffffffff
+    field public static final int EAST = 2; // 0x2
+    field public static final int NORTH = 0; // 0x0
+    field public static final int SOUTH = 1; // 0x1
+    field public static final String TAG = "FadeMove";
+    field public static final int WEST = 3; // 0x3
+  }
+
+  public class MotionPlaceholder extends androidx.constraintlayout.widget.VirtualLayout {
+    ctor public MotionPlaceholder(android.content.Context!);
+    ctor public MotionPlaceholder(android.content.Context!, android.util.AttributeSet!);
+    ctor public MotionPlaceholder(android.content.Context!, android.util.AttributeSet!, int);
+    ctor public MotionPlaceholder(android.content.Context!, android.util.AttributeSet!, int, int);
+  }
+
+}
+
+package androidx.constraintlayout.motion.utils {
+
+  public class CustomSupport {
+    ctor public CustomSupport();
+    method public static void setInterpolatedValue(androidx.constraintlayout.widget.ConstraintAttribute!, android.view.View!, float[]!);
+  }
+
+  public class StopLogic extends androidx.constraintlayout.motion.widget.MotionInterpolator {
+    ctor public StopLogic();
+    method public void config(float, float, float, float, float, float);
+    method public String! debug(String!, float);
+    method public float getInterpolation(float);
+    method public float getVelocity();
+    method public float getVelocity(float);
+    method public boolean isStopped();
+    method public void springConfig(float, float, float, float, float, float, float, int);
+  }
+
+  public abstract class ViewOscillator extends androidx.constraintlayout.core.motion.utils.KeyCycleOscillator {
+    ctor public ViewOscillator();
+    method public static androidx.constraintlayout.motion.utils.ViewOscillator! makeSpline(String!);
+    method public abstract void setProperty(android.view.View!, float);
+  }
+
+  public static class ViewOscillator.PathRotateSet extends androidx.constraintlayout.motion.utils.ViewOscillator {
+    ctor public ViewOscillator.PathRotateSet();
+    method public void setPathRotate(android.view.View!, float, double, double);
+    method public void setProperty(android.view.View!, float);
+  }
+
+  public abstract class ViewSpline extends androidx.constraintlayout.core.motion.utils.SplineSet {
+    ctor public ViewSpline();
+    method public static androidx.constraintlayout.motion.utils.ViewSpline! makeCustomSpline(String!, android.util.SparseArray<androidx.constraintlayout.widget.ConstraintAttribute!>!);
+    method public static androidx.constraintlayout.motion.utils.ViewSpline! makeSpline(String!);
+    method public abstract void setProperty(android.view.View!, float);
+  }
+
+  public static class ViewSpline.CustomSet extends androidx.constraintlayout.motion.utils.ViewSpline {
+    ctor public ViewSpline.CustomSet(String!, android.util.SparseArray<androidx.constraintlayout.widget.ConstraintAttribute!>!);
+    method public void setPoint(int, androidx.constraintlayout.widget.ConstraintAttribute!);
+    method public void setProperty(android.view.View!, float);
+  }
+
+  public static class ViewSpline.PathRotate extends androidx.constraintlayout.motion.utils.ViewSpline {
+    ctor public ViewSpline.PathRotate();
+    method public void setPathRotate(android.view.View!, float, double, double);
+    method public void setProperty(android.view.View!, float);
+  }
+
+  public class ViewState {
+    ctor public ViewState();
+    method public void getState(android.view.View!);
+    method public int height();
+    method public int width();
+    field public int bottom;
+    field public int left;
+    field public int right;
+    field public float rotation;
+    field public int top;
+  }
+
+  public abstract class ViewTimeCycle extends androidx.constraintlayout.core.motion.utils.TimeCycleSplineSet {
+    ctor public ViewTimeCycle();
+    method public float get(float, long, android.view.View!, androidx.constraintlayout.core.motion.utils.KeyCache!);
+    method public static androidx.constraintlayout.motion.utils.ViewTimeCycle! makeCustomSpline(String!, android.util.SparseArray<androidx.constraintlayout.widget.ConstraintAttribute!>!);
+    method public static androidx.constraintlayout.motion.utils.ViewTimeCycle! makeSpline(String!, long);
+    method public abstract boolean setProperty(android.view.View!, float, long, androidx.constraintlayout.core.motion.utils.KeyCache!);
+  }
+
+  public static class ViewTimeCycle.CustomSet extends androidx.constraintlayout.motion.utils.ViewTimeCycle {
+    ctor public ViewTimeCycle.CustomSet(String!, android.util.SparseArray<androidx.constraintlayout.widget.ConstraintAttribute!>!);
+    method public void setPoint(int, androidx.constraintlayout.widget.ConstraintAttribute!, float, int, float);
+    method public boolean setProperty(android.view.View!, float, long, androidx.constraintlayout.core.motion.utils.KeyCache!);
+  }
+
+  public static class ViewTimeCycle.PathRotate extends androidx.constraintlayout.motion.utils.ViewTimeCycle {
+    ctor public ViewTimeCycle.PathRotate();
+    method public boolean setPathRotate(android.view.View!, androidx.constraintlayout.core.motion.utils.KeyCache!, float, long, double, double);
+    method public boolean setProperty(android.view.View!, float, long, androidx.constraintlayout.core.motion.utils.KeyCache!);
+  }
+
+}
+
+package androidx.constraintlayout.motion.widget {
+
+  public interface Animatable {
+    method public float getProgress();
+    method public void setProgress(float);
+  }
+
+  public interface CustomFloatAttributes {
+    method public float get(String!);
+    method public String![]! getListOfAttributes();
+    method public void set(String!, float);
+  }
+
+  public class Debug {
+    ctor public Debug();
+    method public static void dumpLayoutParams(android.view.ViewGroup!, String!);
+    method public static void dumpLayoutParams(android.view.ViewGroup.LayoutParams!, String!);
+    method public static void dumpPoc(Object!);
+    method public static String! getActionType(android.view.MotionEvent!);
+    method public static String! getCallFrom(int);
+    method public static String! getLoc();
+    method public static String! getLocation();
+    method public static String! getLocation2();
+    method public static String! getName(android.content.Context!, int);
+    method public static String! getName(android.content.Context!, int[]!);
+    method public static String! getName(android.view.View!);
+    method public static String! getState(androidx.constraintlayout.motion.widget.MotionLayout!, int);
+    method public static String! getState(androidx.constraintlayout.motion.widget.MotionLayout!, int, int);
+    method public static void logStack(String!, String!, int);
+    method public static void printStack(String!, int);
+  }
+
+  public class DesignTool {
+    ctor public DesignTool(androidx.constraintlayout.motion.widget.MotionLayout!);
+    method public int designAccess(int, String!, Object!, float[]!, int, float[]!, int);
+    method public void disableAutoTransition(boolean);
+    method public void dumpConstraintSet(String!);
+    method public int getAnimationKeyFrames(Object!, float[]!);
+    method public int getAnimationPath(Object!, float[]!, int);
+    method public void getAnimationRectangles(Object!, float[]!);
+    method public String! getEndState();
+    method public int getKeyFrameInfo(Object!, int, int[]!);
+    method public float getKeyFramePosition(Object!, int, float, float);
+    method public int getKeyFramePositions(Object!, int[]!, float[]!);
+    method public Object! getKeyframe(int, int, int);
+    method public Object! getKeyframe(Object!, int, int);
+    method public Object! getKeyframeAtLocation(Object!, float, float);
+    method public Boolean! getPositionKeyframe(Object!, Object!, float, float, String![]!, float[]!);
+    method public float getProgress();
+    method public String! getStartState();
+    method public String! getState();
+    method public long getTransitionTimeMs();
+    method public boolean isInTransition();
+    method public void setAttributes(int, String!, Object!, Object!);
+    method public void setKeyFrame(Object!, int, String!, Object!);
+    method public boolean setKeyFramePosition(Object!, int, int, float, float);
+    method public void setKeyframe(Object!, String!, Object!);
+    method public void setState(String!);
+    method public void setToolPosition(float);
+    method public void setTransition(String!, String!);
+    method public void setViewDebug(Object!, int);
+  }
+
+  public interface FloatLayout {
+    method public void layout(float, float, float, float);
+  }
+
+  public abstract class Key {
+    ctor public Key();
+    method public abstract void addValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.motion.utils.ViewSpline!>!);
+    method public abstract androidx.constraintlayout.motion.widget.Key! clone();
+    method public androidx.constraintlayout.motion.widget.Key! copy(androidx.constraintlayout.motion.widget.Key!);
+    method public int getFramePosition();
+    method public void setFramePosition(int);
+    method public void setInterpolation(java.util.HashMap<java.lang.String!,java.lang.Integer!>!);
+    method public abstract void setValue(String!, Object!);
+    method public androidx.constraintlayout.motion.widget.Key! setViewId(int);
+    field public static final String ALPHA = "alpha";
+    field public static final String CURVEFIT = "curveFit";
+    field public static final String CUSTOM = "CUSTOM";
+    field public static final String ELEVATION = "elevation";
+    field public static final String MOTIONPROGRESS = "motionProgress";
+    field public static final String PIVOT_X = "transformPivotX";
+    field public static final String PIVOT_Y = "transformPivotY";
+    field public static final String PROGRESS = "progress";
+    field public static final String ROTATION = "rotation";
+    field public static final String ROTATION_X = "rotationX";
+    field public static final String ROTATION_Y = "rotationY";
+    field public static final String SCALE_X = "scaleX";
+    field public static final String SCALE_Y = "scaleY";
+    field public static final String TRANSITIONEASING = "transitionEasing";
+    field public static final String TRANSITION_PATH_ROTATE = "transitionPathRotate";
+    field public static final String TRANSLATION_X = "translationX";
+    field public static final String TRANSLATION_Y = "translationY";
+    field public static final String TRANSLATION_Z = "translationZ";
+    field public static int UNSET;
+    field public static final String VISIBILITY = "visibility";
+    field public static final String WAVE_OFFSET = "waveOffset";
+    field public static final String WAVE_PERIOD = "wavePeriod";
+    field public static final String WAVE_PHASE = "wavePhase";
+    field public static final String WAVE_VARIES_BY = "waveVariesBy";
+    field protected int mType;
+  }
+
+  public class KeyAttributes extends androidx.constraintlayout.motion.widget.Key {
+    ctor public KeyAttributes();
+    method public void addValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.motion.utils.ViewSpline!>!);
+    method public androidx.constraintlayout.motion.widget.Key! clone();
+    method public void getAttributeNames(java.util.HashSet<java.lang.String!>!);
+    method public void load(android.content.Context!, android.util.AttributeSet!);
+    method public void setValue(String!, Object!);
+    field public static final int KEY_TYPE = 1; // 0x1
+  }
+
+  public class KeyCycle extends androidx.constraintlayout.motion.widget.Key {
+    ctor public KeyCycle();
+    method public void addCycleValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.motion.utils.ViewOscillator!>!);
+    method public void addValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.motion.utils.ViewSpline!>!);
+    method public androidx.constraintlayout.motion.widget.Key! clone();
+    method public void getAttributeNames(java.util.HashSet<java.lang.String!>!);
+    method public float getValue(String!);
+    method public void load(android.content.Context!, android.util.AttributeSet!);
+    method public void setValue(String!, Object!);
+    field public static final int KEY_TYPE = 4; // 0x4
+    field public static final int SHAPE_BOUNCE = 6; // 0x6
+    field public static final int SHAPE_COS_WAVE = 5; // 0x5
+    field public static final int SHAPE_REVERSE_SAW_WAVE = 4; // 0x4
+    field public static final int SHAPE_SAW_WAVE = 3; // 0x3
+    field public static final int SHAPE_SIN_WAVE = 0; // 0x0
+    field public static final int SHAPE_SQUARE_WAVE = 1; // 0x1
+    field public static final int SHAPE_TRIANGLE_WAVE = 2; // 0x2
+    field public static final String WAVE_OFFSET = "waveOffset";
+    field public static final String WAVE_PERIOD = "wavePeriod";
+    field public static final String WAVE_PHASE = "wavePhase";
+    field public static final String WAVE_SHAPE = "waveShape";
+  }
+
+  public class KeyFrames {
+    ctor public KeyFrames();
+    ctor public KeyFrames(android.content.Context!, org.xmlpull.v1.XmlPullParser!);
+    method public void addAllFrames(androidx.constraintlayout.motion.widget.MotionController!);
+    method public void addFrames(androidx.constraintlayout.motion.widget.MotionController!);
+    method public void addKey(androidx.constraintlayout.motion.widget.Key!);
+    method public java.util.ArrayList<androidx.constraintlayout.motion.widget.Key!>! getKeyFramesForView(int);
+    method public java.util.Set<java.lang.Integer!>! getKeys();
+    field public static final int UNSET = -1; // 0xffffffff
+  }
+
+  public class KeyPosition extends androidx.constraintlayout.motion.widget.Key {
+    ctor public KeyPosition();
+    method public void addValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.motion.utils.ViewSpline!>!);
+    method public androidx.constraintlayout.motion.widget.Key! clone();
+    method public boolean intersects(int, int, android.graphics.RectF!, android.graphics.RectF!, float, float);
+    method public void load(android.content.Context!, android.util.AttributeSet!);
+    method public void positionAttributes(android.view.View!, android.graphics.RectF!, android.graphics.RectF!, float, float, String![]!, float[]!);
+    method public void setType(int);
+    method public void setValue(String!, Object!);
+    field public static final String DRAWPATH = "drawPath";
+    field public static final String PERCENT_HEIGHT = "percentHeight";
+    field public static final String PERCENT_WIDTH = "percentWidth";
+    field public static final String PERCENT_X = "percentX";
+    field public static final String PERCENT_Y = "percentY";
+    field public static final String SIZE_PERCENT = "sizePercent";
+    field public static final String TRANSITION_EASING = "transitionEasing";
+    field public static final int TYPE_AXIS = 3; // 0x3
+    field public static final int TYPE_CARTESIAN = 0; // 0x0
+    field public static final int TYPE_PATH = 1; // 0x1
+    field public static final int TYPE_SCREEN = 2; // 0x2
+  }
+
+  public class KeyTimeCycle extends androidx.constraintlayout.motion.widget.Key {
+    ctor public KeyTimeCycle();
+    method public void addTimeValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.motion.utils.ViewTimeCycle!>!);
+    method public void addValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.motion.utils.ViewSpline!>!);
+    method public androidx.constraintlayout.motion.widget.Key! clone();
+    method public void getAttributeNames(java.util.HashSet<java.lang.String!>!);
+    method public void load(android.content.Context!, android.util.AttributeSet!);
+    method public void setValue(String!, Object!);
+    field public static final int KEY_TYPE = 3; // 0x3
+    field public static final int SHAPE_BOUNCE = 6; // 0x6
+    field public static final int SHAPE_COS_WAVE = 5; // 0x5
+    field public static final int SHAPE_REVERSE_SAW_WAVE = 4; // 0x4
+    field public static final int SHAPE_SAW_WAVE = 3; // 0x3
+    field public static final int SHAPE_SIN_WAVE = 0; // 0x0
+    field public static final int SHAPE_SQUARE_WAVE = 1; // 0x1
+    field public static final int SHAPE_TRIANGLE_WAVE = 2; // 0x2
+    field public static final String WAVE_OFFSET = "waveOffset";
+    field public static final String WAVE_PERIOD = "wavePeriod";
+    field public static final String WAVE_SHAPE = "waveShape";
+  }
+
+  public class KeyTrigger extends androidx.constraintlayout.motion.widget.Key {
+    ctor public KeyTrigger();
+    method public void addValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.motion.utils.ViewSpline!>!);
+    method public androidx.constraintlayout.motion.widget.Key! clone();
+    method public void conditionallyFire(float, android.view.View!);
+    method public void getAttributeNames(java.util.HashSet<java.lang.String!>!);
+    method public void load(android.content.Context!, android.util.AttributeSet!);
+    method public void setValue(String!, Object!);
+    field public static final String CROSS = "CROSS";
+    field public static final int KEY_TYPE = 5; // 0x5
+    field public static final String NEGATIVE_CROSS = "negativeCross";
+    field public static final String POSITIVE_CROSS = "positiveCross";
+    field public static final String POST_LAYOUT = "postLayout";
+    field public static final String TRIGGER_COLLISION_ID = "triggerCollisionId";
+    field public static final String TRIGGER_COLLISION_VIEW = "triggerCollisionView";
+    field public static final String TRIGGER_ID = "triggerID";
+    field public static final String TRIGGER_RECEIVER = "triggerReceiver";
+    field public static final String TRIGGER_SLACK = "triggerSlack";
+    field public static final String VIEW_TRANSITION_ON_CROSS = "viewTransitionOnCross";
+    field public static final String VIEW_TRANSITION_ON_NEGATIVE_CROSS = "viewTransitionOnNegativeCross";
+    field public static final String VIEW_TRANSITION_ON_POSITIVE_CROSS = "viewTransitionOnPositiveCross";
+  }
+
+  public class MotionController {
+    method public void addKey(androidx.constraintlayout.motion.widget.Key!);
+    method public int getAnimateRelativeTo();
+    method public void getCenter(double, float[]!, float[]!);
+    method public float getCenterX();
+    method public float getCenterY();
+    method public int getDrawPath();
+    method public float getFinalHeight();
+    method public float getFinalWidth();
+    method public float getFinalX();
+    method public float getFinalY();
+    method public int getKeyFrameInfo(int, int[]!);
+    method public int getKeyFramePositions(int[]!, float[]!);
+    method public float getStartHeight();
+    method public float getStartWidth();
+    method public float getStartX();
+    method public float getStartY();
+    method public int getTransformPivotTarget();
+    method public android.view.View! getView();
+    method public void remeasure();
+    method public void setDrawPath(int);
+    method public void setPathMotionArc(int);
+    method public void setStartState(androidx.constraintlayout.motion.utils.ViewState!, android.view.View!, int, int, int);
+    method public void setTransformPivotTarget(int);
+    method public void setView(android.view.View!);
+    method public void setup(int, int, float, long);
+    method public void setupRelative(androidx.constraintlayout.motion.widget.MotionController!);
+    field public static final int DRAW_PATH_AS_CONFIGURED = 4; // 0x4
+    field public static final int DRAW_PATH_BASIC = 1; // 0x1
+    field public static final int DRAW_PATH_CARTESIAN = 3; // 0x3
+    field public static final int DRAW_PATH_NONE = 0; // 0x0
+    field public static final int DRAW_PATH_RECTANGLE = 5; // 0x5
+    field public static final int DRAW_PATH_RELATIVE = 2; // 0x2
+    field public static final int DRAW_PATH_SCREEN = 6; // 0x6
+    field public static final int HORIZONTAL_PATH_X = 2; // 0x2
+    field public static final int HORIZONTAL_PATH_Y = 3; // 0x3
+    field public static final int PATH_PERCENT = 0; // 0x0
+    field public static final int PATH_PERPENDICULAR = 1; // 0x1
+    field public static final int ROTATION_LEFT = 2; // 0x2
+    field public static final int ROTATION_RIGHT = 1; // 0x1
+    field public static final int VERTICAL_PATH_X = 4; // 0x4
+    field public static final int VERTICAL_PATH_Y = 5; // 0x5
+  }
+
+  public class MotionHelper extends androidx.constraintlayout.widget.ConstraintHelper implements androidx.constraintlayout.motion.widget.MotionHelperInterface {
+    ctor public MotionHelper(android.content.Context!);
+    ctor public MotionHelper(android.content.Context!, android.util.AttributeSet!);
+    ctor public MotionHelper(android.content.Context!, android.util.AttributeSet!, int);
+    method public float getProgress();
+    method public boolean isDecorator();
+    method public boolean isUseOnHide();
+    method public boolean isUsedOnShow();
+    method public void onFinishedMotionScene(androidx.constraintlayout.motion.widget.MotionLayout!);
+    method public void onPostDraw(android.graphics.Canvas!);
+    method public void onPreDraw(android.graphics.Canvas!);
+    method public void onPreSetup(androidx.constraintlayout.motion.widget.MotionLayout!, java.util.HashMap<android.view.View!,androidx.constraintlayout.motion.widget.MotionController!>!);
+    method public void onTransitionChange(androidx.constraintlayout.motion.widget.MotionLayout!, int, int, float);
+    method public void onTransitionCompleted(androidx.constraintlayout.motion.widget.MotionLayout!, int);
+    method public void onTransitionStarted(androidx.constraintlayout.motion.widget.MotionLayout!, int, int);
+    method public void onTransitionTrigger(androidx.constraintlayout.motion.widget.MotionLayout!, int, boolean, float);
+    method public void setProgress(android.view.View!, float);
+    method public void setProgress(float);
+    field protected android.view.View![]! views;
+  }
+
+  public interface MotionHelperInterface extends androidx.constraintlayout.motion.widget.Animatable androidx.constraintlayout.motion.widget.MotionLayout.TransitionListener {
+    method public boolean isDecorator();
+    method public boolean isUseOnHide();
+    method public boolean isUsedOnShow();
+    method public void onFinishedMotionScene(androidx.constraintlayout.motion.widget.MotionLayout!);
+    method public void onPostDraw(android.graphics.Canvas!);
+    method public void onPreDraw(android.graphics.Canvas!);
+    method public void onPreSetup(androidx.constraintlayout.motion.widget.MotionLayout!, java.util.HashMap<android.view.View!,androidx.constraintlayout.motion.widget.MotionController!>!);
+  }
+
+  public abstract class MotionInterpolator implements android.view.animation.Interpolator {
+    ctor public MotionInterpolator();
+    method public abstract float getVelocity();
+  }
+
+  public class MotionLayout extends androidx.constraintlayout.widget.ConstraintLayout implements androidx.core.view.NestedScrollingParent3 {
+    ctor public MotionLayout(android.content.Context);
+    ctor public MotionLayout(android.content.Context, android.util.AttributeSet?);
+    ctor public MotionLayout(android.content.Context, android.util.AttributeSet?, int);
+    method public void addTransitionListener(androidx.constraintlayout.motion.widget.MotionLayout.TransitionListener!);
+    method public boolean applyViewTransition(int, androidx.constraintlayout.motion.widget.MotionController!);
+    method public androidx.constraintlayout.widget.ConstraintSet! cloneConstraintSet(int);
+    method public void enableTransition(int, boolean);
+    method public void enableViewTransition(int, boolean);
+    method protected void fireTransitionCompleted();
+    method public void fireTrigger(int, boolean, float);
+    method public androidx.constraintlayout.widget.ConstraintSet! getConstraintSet(int);
+    method @IdRes public int[]! getConstraintSetIds();
+    method public int getCurrentState();
+    method public java.util.ArrayList<androidx.constraintlayout.motion.widget.MotionScene.Transition!>! getDefinedTransitions();
+    method public androidx.constraintlayout.motion.widget.DesignTool! getDesignTool();
+    method public int getEndState();
+    method public int[]! getMatchingConstraintSetIds(java.lang.String!...!);
+    method protected long getNanoTime();
+    method public float getProgress();
+    method public androidx.constraintlayout.motion.widget.MotionScene! getScene();
+    method public int getStartState();
+    method public float getTargetPosition();
+    method public androidx.constraintlayout.motion.widget.MotionScene.Transition! getTransition(int);
+    method public android.os.Bundle! getTransitionState();
+    method public long getTransitionTimeMs();
+    method public float getVelocity();
+    method public void getViewVelocity(android.view.View!, float, float, float[]!, int);
+    method public boolean isDelayedApplicationOfInitialState();
+    method public boolean isInRotation();
+    method public boolean isInteractionEnabled();
+    method public boolean isViewTransitionEnabled(int);
+    method public void jumpToState(int);
+    method protected androidx.constraintlayout.motion.widget.MotionLayout.MotionTracker! obtainVelocityTracker();
+    method public void onNestedPreScroll(android.view.View, int, int, int[], int);
+    method public void onNestedScroll(android.view.View, int, int, int, int, int);
+    method public void onNestedScroll(android.view.View, int, int, int, int, int, int[]!);
+    method public void onNestedScrollAccepted(android.view.View, android.view.View, int, int);
+    method public boolean onStartNestedScroll(android.view.View, android.view.View, int, int);
+    method public void onStopNestedScroll(android.view.View, int);
+    method @Deprecated public void rebuildMotion();
+    method public void rebuildScene();
+    method public boolean removeTransitionListener(androidx.constraintlayout.motion.widget.MotionLayout.TransitionListener!);
+    method public void rotateTo(int, int);
+    method public void scheduleTransitionTo(int);
+    method public void setDebugMode(int);
+    method public void setDelayedApplicationOfInitialState(boolean);
+    method public void setInteractionEnabled(boolean);
+    method public void setInterpolatedProgress(float);
+    method public void setOnHide(float);
+    method public void setOnShow(float);
+    method public void setProgress(float);
+    method public void setProgress(float, float);
+    method public void setScene(androidx.constraintlayout.motion.widget.MotionScene!);
+    method protected void setTransition(androidx.constraintlayout.motion.widget.MotionScene.Transition!);
+    method public void setTransition(int);
+    method public void setTransition(int, int);
+    method public void setTransitionDuration(int);
+    method public void setTransitionListener(androidx.constraintlayout.motion.widget.MotionLayout.TransitionListener!);
+    method public void setTransitionState(android.os.Bundle!);
+    method public void touchAnimateTo(int, float, float);
+    method public void touchSpringTo(float, float);
+    method public void transitionToEnd();
+    method public void transitionToEnd(Runnable!);
+    method public void transitionToStart();
+    method public void transitionToStart(Runnable!);
+    method public void transitionToState(int);
+    method public void transitionToState(int, int);
+    method public void transitionToState(int, int, int);
+    method public void transitionToState(int, int, int, int);
+    method public void updateState();
+    method public void updateState(int, androidx.constraintlayout.widget.ConstraintSet!);
+    method public void updateStateAnimate(int, androidx.constraintlayout.widget.ConstraintSet!, int);
+    method public void viewTransition(int, android.view.View!...!);
+    field public static final int DEBUG_SHOW_NONE = 0; // 0x0
+    field public static final int DEBUG_SHOW_PATH = 2; // 0x2
+    field public static final int DEBUG_SHOW_PROGRESS = 1; // 0x1
+    field public static boolean IS_IN_EDIT_MODE;
+    field public static final int TOUCH_UP_COMPLETE = 0; // 0x0
+    field public static final int TOUCH_UP_COMPLETE_TO_END = 2; // 0x2
+    field public static final int TOUCH_UP_COMPLETE_TO_START = 1; // 0x1
+    field public static final int TOUCH_UP_DECELERATE = 4; // 0x4
+    field public static final int TOUCH_UP_DECELERATE_AND_COMPLETE = 5; // 0x5
+    field public static final int TOUCH_UP_NEVER_TO_END = 7; // 0x7
+    field public static final int TOUCH_UP_NEVER_TO_START = 6; // 0x6
+    field public static final int TOUCH_UP_STOP = 3; // 0x3
+    field public static final int VELOCITY_LAYOUT = 1; // 0x1
+    field public static final int VELOCITY_POST_LAYOUT = 0; // 0x0
+    field public static final int VELOCITY_STATIC_LAYOUT = 3; // 0x3
+    field public static final int VELOCITY_STATIC_POST_LAYOUT = 2; // 0x2
+    field protected boolean mMeasureDuringTransition;
+  }
+
+  protected static interface MotionLayout.MotionTracker {
+    method public void addMovement(android.view.MotionEvent!);
+    method public void clear();
+    method public void computeCurrentVelocity(int);
+    method public void computeCurrentVelocity(int, float);
+    method public float getXVelocity();
+    method public float getXVelocity(int);
+    method public float getYVelocity();
+    method public float getYVelocity(int);
+    method public void recycle();
+  }
+
+  public static interface MotionLayout.TransitionListener {
+    method public void onTransitionChange(androidx.constraintlayout.motion.widget.MotionLayout!, int, int, float);
+    method public void onTransitionCompleted(androidx.constraintlayout.motion.widget.MotionLayout!, int);
+    method public void onTransitionStarted(androidx.constraintlayout.motion.widget.MotionLayout!, int, int);
+    method public void onTransitionTrigger(androidx.constraintlayout.motion.widget.MotionLayout!, int, boolean, float);
+  }
+
+  public class MotionScene {
+    ctor public MotionScene(androidx.constraintlayout.motion.widget.MotionLayout!);
+    method public void addOnClickListeners(androidx.constraintlayout.motion.widget.MotionLayout!, int);
+    method public void addTransition(androidx.constraintlayout.motion.widget.MotionScene.Transition!);
+    method public boolean applyViewTransition(int, androidx.constraintlayout.motion.widget.MotionController!);
+    method public androidx.constraintlayout.motion.widget.MotionScene.Transition! bestTransitionFor(int, float, float, android.view.MotionEvent!);
+    method public void disableAutoTransition(boolean);
+    method public void enableViewTransition(int, boolean);
+    method public int gatPathMotionArc();
+    method public androidx.constraintlayout.widget.ConstraintSet! getConstraintSet(android.content.Context!, String!);
+    method public int[]! getConstraintSetIds();
+    method public java.util.ArrayList<androidx.constraintlayout.motion.widget.MotionScene.Transition!>! getDefinedTransitions();
+    method public int getDuration();
+    method public android.view.animation.Interpolator! getInterpolator();
+    method public void getKeyFrames(androidx.constraintlayout.motion.widget.MotionController!);
+    method public int[]! getMatchingStateLabels(java.lang.String!...!);
+    method public float getPathPercent(android.view.View!, int);
+    method public float getStaggered();
+    method public androidx.constraintlayout.motion.widget.MotionScene.Transition! getTransitionById(int);
+    method public java.util.List<androidx.constraintlayout.motion.widget.MotionScene.Transition!>! getTransitionsWithState(int);
+    method public boolean isViewTransitionEnabled(int);
+    method public int lookUpConstraintId(String!);
+    method public String! lookUpConstraintName(int);
+    method protected void onLayout(boolean, int, int, int, int);
+    method public void removeTransition(androidx.constraintlayout.motion.widget.MotionScene.Transition!);
+    method public void setConstraintSet(int, androidx.constraintlayout.widget.ConstraintSet!);
+    method public void setDuration(int);
+    method public void setKeyframe(android.view.View!, int, String!, Object!);
+    method public void setRtl(boolean);
+    method public void setTransition(androidx.constraintlayout.motion.widget.MotionScene.Transition!);
+    method public static String! stripID(String!);
+    method public boolean validateLayout(androidx.constraintlayout.motion.widget.MotionLayout!);
+    method public void viewTransition(int, android.view.View!...!);
+    field public static final int LAYOUT_CALL_MEASURE = 2; // 0x2
+    field public static final int LAYOUT_HONOR_REQUEST = 1; // 0x1
+    field public static final int LAYOUT_IGNORE_REQUEST = 0; // 0x0
+    field public static final int UNSET = -1; // 0xffffffff
+  }
+
+  public static class MotionScene.Transition {
+    ctor public MotionScene.Transition(int, androidx.constraintlayout.motion.widget.MotionScene!, int, int);
+    method public void addKeyFrame(androidx.constraintlayout.motion.widget.KeyFrames!);
+    method public void addOnClick(android.content.Context!, org.xmlpull.v1.XmlPullParser!);
+    method public void addOnClick(int, int);
+    method public String! debugString(android.content.Context!);
+    method public int getAutoTransition();
+    method public int getDuration();
+    method public int getEndConstraintSetId();
+    method public int getId();
+    method public java.util.List<androidx.constraintlayout.motion.widget.KeyFrames!>! getKeyFrameList();
+    method public int getLayoutDuringTransition();
+    method public java.util.List<androidx.constraintlayout.motion.widget.MotionScene.Transition.TransitionOnClick!>! getOnClickList();
+    method public int getPathMotionArc();
+    method public float getStagger();
+    method public int getStartConstraintSetId();
+    method public androidx.constraintlayout.motion.widget.TouchResponse! getTouchResponse();
+    method public boolean isEnabled();
+    method public boolean isTransitionFlag(int);
+    method public void removeOnClick(int);
+    method public void setAutoTransition(int);
+    method public void setDuration(int);
+    method public void setEnabled(boolean);
+    method public void setInterpolatorInfo(int, String!, int);
+    method public void setLayoutDuringTransition(int);
+    method public void setOnSwipe(androidx.constraintlayout.motion.widget.OnSwipe!);
+    method public void setOnTouchUp(int);
+    method public void setPathMotionArc(int);
+    method public void setStagger(float);
+    method public void setTransitionFlag(int);
+    field public static final int AUTO_ANIMATE_TO_END = 4; // 0x4
+    field public static final int AUTO_ANIMATE_TO_START = 3; // 0x3
+    field public static final int AUTO_JUMP_TO_END = 2; // 0x2
+    field public static final int AUTO_JUMP_TO_START = 1; // 0x1
+    field public static final int AUTO_NONE = 0; // 0x0
+    field public static final int INTERPOLATE_ANTICIPATE = 6; // 0x6
+    field public static final int INTERPOLATE_BOUNCE = 4; // 0x4
+    field public static final int INTERPOLATE_EASE_IN = 1; // 0x1
+    field public static final int INTERPOLATE_EASE_IN_OUT = 0; // 0x0
+    field public static final int INTERPOLATE_EASE_OUT = 2; // 0x2
+    field public static final int INTERPOLATE_LINEAR = 3; // 0x3
+    field public static final int INTERPOLATE_OVERSHOOT = 5; // 0x5
+    field public static final int INTERPOLATE_REFERENCE_ID = -2; // 0xfffffffe
+    field public static final int INTERPOLATE_SPLINE_STRING = -1; // 0xffffffff
+  }
+
+  public static class MotionScene.Transition.TransitionOnClick implements android.view.View.OnClickListener {
+    ctor public MotionScene.Transition.TransitionOnClick(android.content.Context!, androidx.constraintlayout.motion.widget.MotionScene.Transition!, org.xmlpull.v1.XmlPullParser!);
+    ctor public MotionScene.Transition.TransitionOnClick(androidx.constraintlayout.motion.widget.MotionScene.Transition!, int, int);
+    method public void addOnClickListeners(androidx.constraintlayout.motion.widget.MotionLayout!, int, androidx.constraintlayout.motion.widget.MotionScene.Transition!);
+    method public void onClick(android.view.View!);
+    method public void removeOnClickListeners(androidx.constraintlayout.motion.widget.MotionLayout!);
+    field public static final int ANIM_TOGGLE = 17; // 0x11
+    field public static final int ANIM_TO_END = 1; // 0x1
+    field public static final int ANIM_TO_START = 16; // 0x10
+    field public static final int JUMP_TO_END = 256; // 0x100
+    field public static final int JUMP_TO_START = 4096; // 0x1000
+  }
+
+  public class OnSwipe {
+    ctor public OnSwipe();
+    method public int getAutoCompleteMode();
+    method public int getDragDirection();
+    method public float getDragScale();
+    method public float getDragThreshold();
+    method public int getLimitBoundsTo();
+    method public float getMaxAcceleration();
+    method public float getMaxVelocity();
+    method public boolean getMoveWhenScrollAtTop();
+    method public int getNestedScrollFlags();
+    method public int getOnTouchUp();
+    method public int getRotationCenterId();
+    method public int getSpringBoundary();
+    method public float getSpringDamping();
+    method public float getSpringMass();
+    method public float getSpringStiffness();
+    method public float getSpringStopThreshold();
+    method public int getTouchAnchorId();
+    method public int getTouchAnchorSide();
+    method public int getTouchRegionId();
+    method public void setAutoCompleteMode(int);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setDragDirection(int);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setDragScale(int);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setDragThreshold(int);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setLimitBoundsTo(int);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setMaxAcceleration(int);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setMaxVelocity(int);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setMoveWhenScrollAtTop(boolean);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setNestedScrollFlags(int);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setOnTouchUp(int);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setRotateCenter(int);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setSpringBoundary(int);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setSpringDamping(float);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setSpringMass(float);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setSpringStiffness(float);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setSpringStopThreshold(float);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setTouchAnchorId(int);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setTouchAnchorSide(int);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setTouchRegionId(int);
+    field public static final int COMPLETE_MODE_CONTINUOUS_VELOCITY = 0; // 0x0
+    field public static final int COMPLETE_MODE_SPRING = 1; // 0x1
+    field public static final int DRAG_ANTICLOCKWISE = 7; // 0x7
+    field public static final int DRAG_CLOCKWISE = 6; // 0x6
+    field public static final int DRAG_DOWN = 1; // 0x1
+    field public static final int DRAG_END = 5; // 0x5
+    field public static final int DRAG_LEFT = 2; // 0x2
+    field public static final int DRAG_RIGHT = 3; // 0x3
+    field public static final int DRAG_START = 4; // 0x4
+    field public static final int DRAG_UP = 0; // 0x0
+    field public static final int FLAG_DISABLE_POST_SCROLL = 1; // 0x1
+    field public static final int FLAG_DISABLE_SCROLL = 2; // 0x2
+    field public static final int ON_UP_AUTOCOMPLETE = 0; // 0x0
+    field public static final int ON_UP_AUTOCOMPLETE_TO_END = 2; // 0x2
+    field public static final int ON_UP_AUTOCOMPLETE_TO_START = 1; // 0x1
+    field public static final int ON_UP_DECELERATE = 4; // 0x4
+    field public static final int ON_UP_DECELERATE_AND_COMPLETE = 5; // 0x5
+    field public static final int ON_UP_NEVER_TO_END = 7; // 0x7
+    field public static final int ON_UP_NEVER_TO_START = 6; // 0x6
+    field public static final int ON_UP_STOP = 3; // 0x3
+    field public static final int SIDE_BOTTOM = 3; // 0x3
+    field public static final int SIDE_END = 6; // 0x6
+    field public static final int SIDE_LEFT = 1; // 0x1
+    field public static final int SIDE_MIDDLE = 4; // 0x4
+    field public static final int SIDE_RIGHT = 2; // 0x2
+    field public static final int SIDE_START = 5; // 0x5
+    field public static final int SIDE_TOP = 0; // 0x0
+    field public static final int SPRING_BOUNDARY_BOUNCEBOTH = 3; // 0x3
+    field public static final int SPRING_BOUNDARY_BOUNCEEND = 2; // 0x2
+    field public static final int SPRING_BOUNDARY_BOUNCESTART = 1; // 0x1
+    field public static final int SPRING_BOUNDARY_OVERSHOOT = 0; // 0x0
+  }
+
+  public abstract class TransitionAdapter implements androidx.constraintlayout.motion.widget.MotionLayout.TransitionListener {
+    ctor public TransitionAdapter();
+    method public void onTransitionChange(androidx.constraintlayout.motion.widget.MotionLayout!, int, int, float);
+    method public void onTransitionCompleted(androidx.constraintlayout.motion.widget.MotionLayout!, int);
+    method public void onTransitionStarted(androidx.constraintlayout.motion.widget.MotionLayout!, int, int);
+    method public void onTransitionTrigger(androidx.constraintlayout.motion.widget.MotionLayout!, int, boolean, float);
+  }
+
+  public class TransitionBuilder {
+    ctor public TransitionBuilder();
+    method public static androidx.constraintlayout.motion.widget.MotionScene.Transition! buildTransition(androidx.constraintlayout.motion.widget.MotionScene!, int, int, androidx.constraintlayout.widget.ConstraintSet!, int, androidx.constraintlayout.widget.ConstraintSet!);
+    method public static void validate(androidx.constraintlayout.motion.widget.MotionLayout!);
+  }
+
+  public class ViewTransition {
+    method public int getSharedValue();
+    method public int getSharedValueCurrent();
+    method public int getSharedValueID();
+    method public int getStateTransition();
+    method public void setSharedValue(int);
+    method public void setSharedValueCurrent(int);
+    method public void setSharedValueID(int);
+    method public void setStateTransition(int);
+    field public static final String CONSTRAINT_OVERRIDE = "ConstraintOverride";
+    field public static final String CUSTOM_ATTRIBUTE = "CustomAttribute";
+    field public static final String CUSTOM_METHOD = "CustomMethod";
+    field public static final String KEY_FRAME_SET_TAG = "KeyFrameSet";
+    field public static final int ONSTATE_ACTION_DOWN = 1; // 0x1
+    field public static final int ONSTATE_ACTION_DOWN_UP = 3; // 0x3
+    field public static final int ONSTATE_ACTION_UP = 2; // 0x2
+    field public static final int ONSTATE_SHARED_VALUE_SET = 4; // 0x4
+    field public static final int ONSTATE_SHARED_VALUE_UNSET = 5; // 0x5
+    field public static final String VIEW_TRANSITION_TAG = "ViewTransition";
+  }
+
+  public class ViewTransitionController {
+    ctor public ViewTransitionController(androidx.constraintlayout.motion.widget.MotionLayout!);
+    method public void add(androidx.constraintlayout.motion.widget.ViewTransition!);
+  }
+
+}
+
+package androidx.constraintlayout.utils.widget {
+
+  public class ImageFilterButton extends androidx.appcompat.widget.AppCompatImageButton {
+    ctor public ImageFilterButton(android.content.Context!);
+    ctor public ImageFilterButton(android.content.Context!, android.util.AttributeSet!);
+    ctor public ImageFilterButton(android.content.Context!, android.util.AttributeSet!, int);
+    method public float getContrast();
+    method public float getCrossfade();
+    method public float getImagePanX();
+    method public float getImagePanY();
+    method public float getImageRotate();
+    method public float getImageZoom();
+    method public float getRound();
+    method public float getRoundPercent();
+    method public float getSaturation();
+    method public float getWarmth();
+    method public void setAltImageResource(int);
+    method public void setBrightness(float);
+    method public void setContrast(float);
+    method public void setCrossfade(float);
+    method public void setImagePanX(float);
+    method public void setImagePanY(float);
+    method public void setImageRotate(float);
+    method public void setImageZoom(float);
+    method @RequiresApi(android.os.Build.VERSION_CODES.LOLLIPOP) public void setRound(float);
+    method @RequiresApi(android.os.Build.VERSION_CODES.LOLLIPOP) public void setRoundPercent(float);
+    method public void setSaturation(float);
+    method public void setWarmth(float);
+  }
+
+  public class ImageFilterView extends androidx.appcompat.widget.AppCompatImageView {
+    ctor public ImageFilterView(android.content.Context!);
+    ctor public ImageFilterView(android.content.Context!, android.util.AttributeSet!);
+    ctor public ImageFilterView(android.content.Context!, android.util.AttributeSet!, int);
+    method public float getBrightness();
+    method public float getContrast();
+    method public float getCrossfade();
+    method public float getImagePanX();
+    method public float getImagePanY();
+    method public float getImageRotate();
+    method public float getImageZoom();
+    method public float getRound();
+    method public float getRoundPercent();
+    method public float getSaturation();
+    method public float getWarmth();
+    method public void setAltImageDrawable(android.graphics.drawable.Drawable!);
+    method public void setAltImageResource(int);
+    method public void setBrightness(float);
+    method public void setContrast(float);
+    method public void setCrossfade(float);
+    method public void setImagePanX(float);
+    method public void setImagePanY(float);
+    method public void setImageRotate(float);
+    method public void setImageZoom(float);
+    method @RequiresApi(android.os.Build.VERSION_CODES.LOLLIPOP) public void setRound(float);
+    method @RequiresApi(android.os.Build.VERSION_CODES.LOLLIPOP) public void setRoundPercent(float);
+    method public void setSaturation(float);
+    method public void setWarmth(float);
+  }
+
+  public class MockView extends android.view.View {
+    ctor public MockView(android.content.Context!);
+    ctor public MockView(android.content.Context!, android.util.AttributeSet!);
+    ctor public MockView(android.content.Context!, android.util.AttributeSet!, int);
+    method public void onDraw(android.graphics.Canvas);
+    field protected String! mText;
+  }
+
+  public class MotionButton extends androidx.appcompat.widget.AppCompatButton {
+    ctor public MotionButton(android.content.Context!);
+    ctor public MotionButton(android.content.Context!, android.util.AttributeSet!);
+    ctor public MotionButton(android.content.Context!, android.util.AttributeSet!, int);
+    method public float getRound();
+    method public float getRoundPercent();
+    method @RequiresApi(android.os.Build.VERSION_CODES.LOLLIPOP) public void setRound(float);
+    method @RequiresApi(android.os.Build.VERSION_CODES.LOLLIPOP) public void setRoundPercent(float);
+  }
+
+  public class MotionLabel extends android.view.View implements androidx.constraintlayout.motion.widget.FloatLayout {
+    ctor public MotionLabel(android.content.Context!);
+    ctor public MotionLabel(android.content.Context!, android.util.AttributeSet?);
+    ctor public MotionLabel(android.content.Context!, android.util.AttributeSet?, int);
+    method public float getRound();
+    method public float getRoundPercent();
+    method public float getScaleFromTextSize();
+    method public float getTextBackgroundPanX();
+    method public float getTextBackgroundPanY();
+    method public float getTextBackgroundRotate();
+    method public float getTextBackgroundZoom();
+    method public int getTextOutlineColor();
+    method public float getTextPanX();
+    method public float getTextPanY();
+    method public float getTextureHeight();
+    method public float getTextureWidth();
+    method public android.graphics.Typeface! getTypeface();
+    method public void layout(float, float, float, float);
+    method public void setGravity(int);
+    method @RequiresApi(android.os.Build.VERSION_CODES.LOLLIPOP) public void setRound(float);
+    method @RequiresApi(android.os.Build.VERSION_CODES.LOLLIPOP) public void setRoundPercent(float);
+    method public void setScaleFromTextSize(float);
+    method public void setText(CharSequence!);
+    method public void setTextBackgroundPanX(float);
+    method public void setTextBackgroundPanY(float);
+    method public void setTextBackgroundRotate(float);
+    method public void setTextBackgroundZoom(float);
+    method public void setTextFillColor(int);
+    method public void setTextOutlineColor(int);
+    method public void setTextOutlineThickness(float);
+    method public void setTextPanX(float);
+    method public void setTextPanY(float);
+    method public void setTextSize(float);
+    method public void setTextureHeight(float);
+    method public void setTextureWidth(float);
+    method public void setTypeface(android.graphics.Typeface!);
+  }
+
+  public class MotionTelltales extends androidx.constraintlayout.utils.widget.MockView {
+    ctor public MotionTelltales(android.content.Context!);
+    ctor public MotionTelltales(android.content.Context!, android.util.AttributeSet!);
+    ctor public MotionTelltales(android.content.Context!, android.util.AttributeSet!, int);
+    method public void setText(CharSequence!);
+  }
+
+}
+
+package androidx.constraintlayout.widget {
+
+  public class Barrier extends androidx.constraintlayout.widget.ConstraintHelper {
+    ctor public Barrier(android.content.Context!);
+    ctor public Barrier(android.content.Context!, android.util.AttributeSet!);
+    ctor public Barrier(android.content.Context!, android.util.AttributeSet!, int);
+    method @Deprecated public boolean allowsGoneWidget();
+    method public boolean getAllowsGoneWidget();
+    method public int getMargin();
+    method public int getType();
+    method public void setAllowsGoneWidget(boolean);
+    method public void setDpMargin(int);
+    method public void setMargin(int);
+    method public void setType(int);
+    field public static final int BOTTOM = 3; // 0x3
+    field public static final int END = 6; // 0x6
+    field public static final int LEFT = 0; // 0x0
+    field public static final int RIGHT = 1; // 0x1
+    field public static final int START = 5; // 0x5
+    field public static final int TOP = 2; // 0x2
+  }
+
+  public class ConstraintAttribute {
+    ctor public ConstraintAttribute(androidx.constraintlayout.widget.ConstraintAttribute!, Object!);
+    ctor public ConstraintAttribute(String!, androidx.constraintlayout.widget.ConstraintAttribute.AttributeType!);
+    ctor public ConstraintAttribute(String!, androidx.constraintlayout.widget.ConstraintAttribute.AttributeType!, Object!, boolean);
+    method public void applyCustom(android.view.View!);
+    method public boolean diff(androidx.constraintlayout.widget.ConstraintAttribute!);
+    method public static java.util.HashMap<java.lang.String!,androidx.constraintlayout.widget.ConstraintAttribute!>! extractAttributes(java.util.HashMap<java.lang.String!,androidx.constraintlayout.widget.ConstraintAttribute!>!, android.view.View!);
+    method public int getColorValue();
+    method public float getFloatValue();
+    method public int getIntegerValue();
+    method public String! getName();
+    method public String! getStringValue();
+    method public androidx.constraintlayout.widget.ConstraintAttribute.AttributeType! getType();
+    method public float getValueToInterpolate();
+    method public void getValuesToInterpolate(float[]!);
+    method public boolean isBooleanValue();
+    method public boolean isContinuous();
+    method public boolean isMethod();
+    method public int numberOfInterpolatedValues();
+    method public static void parse(android.content.Context!, org.xmlpull.v1.XmlPullParser!, java.util.HashMap<java.lang.String!,androidx.constraintlayout.widget.ConstraintAttribute!>!);
+    method public static void setAttributes(android.view.View!, java.util.HashMap<java.lang.String!,androidx.constraintlayout.widget.ConstraintAttribute!>!);
+    method public void setColorValue(int);
+    method public void setFloatValue(float);
+    method public void setIntValue(int);
+    method public void setStringValue(String!);
+    method public void setValue(float[]!);
+    method public void setValue(Object!);
+  }
+
+  public enum ConstraintAttribute.AttributeType {
+    enum_constant public static final androidx.constraintlayout.widget.ConstraintAttribute.AttributeType BOOLEAN_TYPE;
+    enum_constant public static final androidx.constraintlayout.widget.ConstraintAttribute.AttributeType COLOR_DRAWABLE_TYPE;
+    enum_constant public static final androidx.constraintlayout.widget.ConstraintAttribute.AttributeType COLOR_TYPE;
+    enum_constant public static final androidx.constraintlayout.widget.ConstraintAttribute.AttributeType DIMENSION_TYPE;
+    enum_constant public static final androidx.constraintlayout.widget.ConstraintAttribute.AttributeType FLOAT_TYPE;
+    enum_constant public static final androidx.constraintlayout.widget.ConstraintAttribute.AttributeType INT_TYPE;
+    enum_constant public static final androidx.constraintlayout.widget.ConstraintAttribute.AttributeType REFERENCE_TYPE;
+    enum_constant public static final androidx.constraintlayout.widget.ConstraintAttribute.AttributeType STRING_TYPE;
+  }
+
+  public abstract class ConstraintHelper extends android.view.View {
+    ctor public ConstraintHelper(android.content.Context!);
+    ctor public ConstraintHelper(android.content.Context!, android.util.AttributeSet!);
+    ctor public ConstraintHelper(android.content.Context!, android.util.AttributeSet!, int);
+    method public void addView(android.view.View!);
+    method public void applyHelperParams();
+    method protected void applyLayoutFeatures();
+    method protected void applyLayoutFeatures(androidx.constraintlayout.widget.ConstraintLayout!);
+    method protected void applyLayoutFeaturesInConstraintSet(androidx.constraintlayout.widget.ConstraintLayout!);
+    method public boolean containsId(int);
+    method public int[]! getReferencedIds();
+    method protected android.view.View![]! getViews(androidx.constraintlayout.widget.ConstraintLayout!);
+    method public int indexFromId(int);
+    method protected void init(android.util.AttributeSet!);
+    method public static boolean isChildOfHelper(android.view.View!);
+    method public void loadParameters(androidx.constraintlayout.widget.ConstraintSet.Constraint!, androidx.constraintlayout.core.widgets.HelperWidget!, androidx.constraintlayout.widget.ConstraintLayout.LayoutParams!, android.util.SparseArray<androidx.constraintlayout.core.widgets.ConstraintWidget!>!);
+    method public void onDraw(android.graphics.Canvas);
+    method public int removeView(android.view.View!);
+    method public void resolveRtl(androidx.constraintlayout.core.widgets.ConstraintWidget!, boolean);
+    method protected void setIds(String!);
+    method protected void setReferenceTags(String!);
+    method public void setReferencedIds(int[]!);
+    method public void updatePostConstraints(androidx.constraintlayout.widget.ConstraintLayout!);
+    method public void updatePostLayout(androidx.constraintlayout.widget.ConstraintLayout!);
+    method public void updatePostMeasure(androidx.constraintlayout.widget.ConstraintLayout!);
+    method public void updatePreDraw(androidx.constraintlayout.widget.ConstraintLayout!);
+    method public void updatePreLayout(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!, androidx.constraintlayout.core.widgets.Helper!, android.util.SparseArray<androidx.constraintlayout.core.widgets.ConstraintWidget!>!);
+    method public void updatePreLayout(androidx.constraintlayout.widget.ConstraintLayout!);
+    method public void validateParams();
+    field protected static final String CHILD_TAG = "CONSTRAINT_LAYOUT_HELPER_CHILD";
+    field protected int mCount;
+    field protected androidx.constraintlayout.core.widgets.Helper! mHelperWidget;
+    field protected int[]! mIds;
+    field protected java.util.HashMap<java.lang.Integer!,java.lang.String!>! mMap;
+    field protected String! mReferenceIds;
+    field protected String! mReferenceTags;
+    field protected boolean mUseViewMeasure;
+    field protected android.content.Context! myContext;
+  }
+
+  public class ConstraintLayout extends android.view.ViewGroup {
+    ctor public ConstraintLayout(android.content.Context);
+    ctor public ConstraintLayout(android.content.Context, android.util.AttributeSet?);
+    ctor public ConstraintLayout(android.content.Context, android.util.AttributeSet?, int);
+    ctor public ConstraintLayout(android.content.Context, android.util.AttributeSet?, int, int);
+    method public void addValueModifier(androidx.constraintlayout.widget.ConstraintLayout.ValueModifier!);
+    method protected void applyConstraintsFromLayoutParams(boolean, android.view.View!, androidx.constraintlayout.core.widgets.ConstraintWidget!, androidx.constraintlayout.widget.ConstraintLayout.LayoutParams!, android.util.SparseArray<androidx.constraintlayout.core.widgets.ConstraintWidget!>!);
+    method protected boolean dynamicUpdateConstraints(int, int);
+    method public void fillMetrics(androidx.constraintlayout.core.Metrics!);
+    method protected androidx.constraintlayout.widget.ConstraintLayout.LayoutParams! generateDefaultLayoutParams();
+    method public androidx.constraintlayout.widget.ConstraintLayout.LayoutParams! generateLayoutParams(android.util.AttributeSet!);
+    method public Object! getDesignInformation(int, Object!);
+    method public int getMaxHeight();
+    method public int getMaxWidth();
+    method public int getMinHeight();
+    method public int getMinWidth();
+    method public int getOptimizationLevel();
+    method public String! getSceneString();
+    method public static androidx.constraintlayout.widget.SharedValues! getSharedValues();
+    method public android.view.View! getViewById(int);
+    method public final androidx.constraintlayout.core.widgets.ConstraintWidget! getViewWidget(android.view.View!);
+    method protected boolean isRtl();
+    method public void loadLayoutDescription(int);
+    method protected void parseLayoutDescription(int);
+    method protected void resolveMeasuredDimension(int, int, int, int, boolean, boolean);
+    method protected void resolveSystem(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!, int, int, int);
+    method public void setConstraintSet(androidx.constraintlayout.widget.ConstraintSet!);
+    method public void setDesignInformation(int, Object!, Object!);
+    method public void setMaxHeight(int);
+    method public void setMaxWidth(int);
+    method public void setMinHeight(int);
+    method public void setMinWidth(int);
+    method public void setOnConstraintsChanged(androidx.constraintlayout.widget.ConstraintsChangedListener!);
+    method public void setOptimizationLevel(int);
+    method protected void setSelfDimensionBehaviour(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!, int, int, int, int);
+    method public void setState(int, int, int);
+    field public static final int DESIGN_INFO_ID = 0; // 0x0
+    field public static final String VERSION = "ConstraintLayout-2.2.0-alpha04";
+    field protected androidx.constraintlayout.widget.ConstraintLayoutStates! mConstraintLayoutSpec;
+    field protected boolean mDirtyHierarchy;
+    field protected androidx.constraintlayout.core.widgets.ConstraintWidgetContainer! mLayoutWidget;
+  }
+
+  public static class ConstraintLayout.LayoutParams extends android.view.ViewGroup.MarginLayoutParams {
+    ctor public ConstraintLayout.LayoutParams(android.content.Context!, android.util.AttributeSet!);
+    ctor public ConstraintLayout.LayoutParams(android.view.ViewGroup.LayoutParams!);
+    ctor public ConstraintLayout.LayoutParams(int, int);
+    method public String! getConstraintTag();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getConstraintWidget();
+    method public void reset();
+    method public void setWidgetDebugName(String!);
+    method public void validate();
+    field public static final int BASELINE = 5; // 0x5
+    field public static final int BOTTOM = 4; // 0x4
+    field public static final int CHAIN_PACKED = 2; // 0x2
+    field public static final int CHAIN_SPREAD = 0; // 0x0
+    field public static final int CHAIN_SPREAD_INSIDE = 1; // 0x1
+    field public static final int CIRCLE = 8; // 0x8
+    field public static final int END = 7; // 0x7
+    field public static final int GONE_UNSET = -2147483648; // 0x80000000
+    field public static final int HORIZONTAL = 0; // 0x0
+    field public static final int LEFT = 1; // 0x1
+    field public static final int MATCH_CONSTRAINT = 0; // 0x0
+    field public static final int MATCH_CONSTRAINT_PERCENT = 2; // 0x2
+    field public static final int MATCH_CONSTRAINT_SPREAD = 0; // 0x0
+    field public static final int MATCH_CONSTRAINT_WRAP = 1; // 0x1
+    field public static final int PARENT_ID = 0; // 0x0
+    field public static final int RIGHT = 2; // 0x2
+    field public static final int START = 6; // 0x6
+    field public static final int TOP = 3; // 0x3
+    field public static final int UNSET = -1; // 0xffffffff
+    field public static final int VERTICAL = 1; // 0x1
+    field public static final int WRAP_BEHAVIOR_HORIZONTAL_ONLY = 1; // 0x1
+    field public static final int WRAP_BEHAVIOR_INCLUDED = 0; // 0x0
+    field public static final int WRAP_BEHAVIOR_SKIPPED = 3; // 0x3
+    field public static final int WRAP_BEHAVIOR_VERTICAL_ONLY = 2; // 0x2
+    field public int baselineMargin;
+    field public int baselineToBaseline;
+    field public int baselineToBottom;
+    field public int baselineToTop;
+    field public int bottomToBottom;
+    field public int bottomToTop;
+    field public float circleAngle;
+    field public int circleConstraint;
+    field public int circleRadius;
+    field public boolean constrainedHeight;
+    field public boolean constrainedWidth;
+    field public String! constraintTag;
+    field public String! dimensionRatio;
+    field public int editorAbsoluteX;
+    field public int editorAbsoluteY;
+    field public int endToEnd;
+    field public int endToStart;
+    field public int goneBaselineMargin;
+    field public int goneBottomMargin;
+    field public int goneEndMargin;
+    field public int goneLeftMargin;
+    field public int goneRightMargin;
+    field public int goneStartMargin;
+    field public int goneTopMargin;
+    field public int guideBegin;
+    field public int guideEnd;
+    field public float guidePercent;
+    field public boolean guidelineUseRtl;
+    field public boolean helped;
+    field public float horizontalBias;
+    field public int horizontalChainStyle;
+    field public float horizontalWeight;
+    field public int leftToLeft;
+    field public int leftToRight;
+    field public int matchConstraintDefaultHeight;
+    field public int matchConstraintDefaultWidth;
+    field public int matchConstraintMaxHeight;
+    field public int matchConstraintMaxWidth;
+    field public int matchConstraintMinHeight;
+    field public int matchConstraintMinWidth;
+    field public float matchConstraintPercentHeight;
+    field public float matchConstraintPercentWidth;
+    field public int orientation;
+    field public int rightToLeft;
+    field public int rightToRight;
+    field public int startToEnd;
+    field public int startToStart;
+    field public int topToBottom;
+    field public int topToTop;
+    field public float verticalBias;
+    field public int verticalChainStyle;
+    field public float verticalWeight;
+    field public int wrapBehaviorInParent;
+  }
+
+  public static interface ConstraintLayout.ValueModifier {
+    method public boolean update(int, int, int, android.view.View!, androidx.constraintlayout.widget.ConstraintLayout.LayoutParams!);
+  }
+
+  public class ConstraintLayoutStates {
+    method public boolean needsToChange(int, float, float);
+    method public void setOnConstraintsChanged(androidx.constraintlayout.widget.ConstraintsChangedListener!);
+    method public void updateConstraints(int, float, float);
+    field public static final String TAG = "ConstraintLayoutStates";
+  }
+
+  public class ConstraintLayoutStatistics {
+    ctor public ConstraintLayoutStatistics(androidx.constraintlayout.widget.ConstraintLayout!);
+    ctor public ConstraintLayoutStatistics(androidx.constraintlayout.widget.ConstraintLayoutStatistics!);
+    method public void attach(androidx.constraintlayout.widget.ConstraintLayout!);
+    method public androidx.constraintlayout.widget.ConstraintLayoutStatistics! clone();
+    method public void detach();
+    method public long getValue(int);
+    method public void logSummary(String!);
+    method public void logSummary(String!, androidx.constraintlayout.widget.ConstraintLayoutStatistics!);
+    method public void reset();
+    field public static final int DURATION_OF_CHILD_MEASURES = 5; // 0x5
+    field public static final int DURATION_OF_LAYOUT = 7; // 0x7
+    field public static final int DURATION_OF_MEASURES = 6; // 0x6
+    field public static final int NUMBER_OF_CHILD_MEASURES = 4; // 0x4
+    field public static final int NUMBER_OF_CHILD_VIEWS = 3; // 0x3
+    field public static final int NUMBER_OF_EQUATIONS = 9; // 0x9
+    field public static final int NUMBER_OF_LAYOUTS = 1; // 0x1
+    field public static final int NUMBER_OF_ON_MEASURES = 2; // 0x2
+    field public static final int NUMBER_OF_SIMPLE_EQUATIONS = 10; // 0xa
+    field public static final int NUMBER_OF_VARIABLES = 8; // 0x8
+  }
+
+  public class ConstraintProperties {
+    ctor public ConstraintProperties(android.view.View!);
+    method public androidx.constraintlayout.widget.ConstraintProperties! addToHorizontalChain(int, int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! addToHorizontalChainRTL(int, int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! addToVerticalChain(int, int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! alpha(float);
+    method public void apply();
+    method public androidx.constraintlayout.widget.ConstraintProperties! center(int, int, int, int, int, int, float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! centerHorizontally(int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! centerHorizontally(int, int, int, int, int, int, float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! centerHorizontallyRtl(int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! centerHorizontallyRtl(int, int, int, int, int, int, float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! centerVertically(int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! centerVertically(int, int, int, int, int, int, float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! connect(int, int, int, int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! constrainDefaultHeight(int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! constrainDefaultWidth(int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! constrainHeight(int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! constrainMaxHeight(int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! constrainMaxWidth(int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! constrainMinHeight(int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! constrainMinWidth(int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! constrainWidth(int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! dimensionRatio(String!);
+    method public androidx.constraintlayout.widget.ConstraintProperties! elevation(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! goneMargin(int, int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! horizontalBias(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! horizontalChainStyle(int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! horizontalWeight(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! margin(int, int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! removeConstraints(int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! removeFromHorizontalChain();
+    method public androidx.constraintlayout.widget.ConstraintProperties! removeFromVerticalChain();
+    method public androidx.constraintlayout.widget.ConstraintProperties! rotation(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! rotationX(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! rotationY(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! scaleX(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! scaleY(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! transformPivot(float, float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! transformPivotX(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! transformPivotY(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! translation(float, float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! translationX(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! translationY(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! translationZ(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! verticalBias(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! verticalChainStyle(int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! verticalWeight(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! visibility(int);
+    field public static final int BASELINE = 5; // 0x5
+    field public static final int BOTTOM = 4; // 0x4
+    field public static final int END = 7; // 0x7
+    field public static final int LEFT = 1; // 0x1
+    field public static final int MATCH_CONSTRAINT = 0; // 0x0
+    field public static final int MATCH_CONSTRAINT_SPREAD = 0; // 0x0
+    field public static final int MATCH_CONSTRAINT_WRAP = 1; // 0x1
+    field public static final int PARENT_ID = 0; // 0x0
+    field public static final int RIGHT = 2; // 0x2
+    field public static final int START = 6; // 0x6
+    field public static final int TOP = 3; // 0x3
+    field public static final int UNSET = -1; // 0xffffffff
+    field public static final int WRAP_CONTENT = -2; // 0xfffffffe
+  }
+
+  public class ConstraintSet {
+    ctor public ConstraintSet();
+    method public void addColorAttributes(java.lang.String!...!);
+    method public void addFloatAttributes(java.lang.String!...!);
+    method public void addIntAttributes(java.lang.String!...!);
+    method public void addStringAttributes(java.lang.String!...!);
+    method public void addToHorizontalChain(int, int, int);
+    method public void addToHorizontalChainRTL(int, int, int);
+    method public void addToVerticalChain(int, int, int);
+    method public void applyCustomAttributes(androidx.constraintlayout.widget.ConstraintLayout!);
+    method public void applyDeltaFrom(androidx.constraintlayout.widget.ConstraintSet!);
+    method public void applyTo(androidx.constraintlayout.widget.ConstraintLayout!);
+    method public void applyToHelper(androidx.constraintlayout.widget.ConstraintHelper!, androidx.constraintlayout.core.widgets.ConstraintWidget!, androidx.constraintlayout.widget.ConstraintLayout.LayoutParams!, android.util.SparseArray<androidx.constraintlayout.core.widgets.ConstraintWidget!>!);
+    method public void applyToLayoutParams(int, androidx.constraintlayout.widget.ConstraintLayout.LayoutParams!);
+    method public void applyToWithoutCustom(androidx.constraintlayout.widget.ConstraintLayout!);
+    method public static androidx.constraintlayout.widget.ConstraintSet.Constraint! buildDelta(android.content.Context!, org.xmlpull.v1.XmlPullParser!);
+    method public void center(int, int, int, int, int, int, int, float);
+    method public void centerHorizontally(int, int);
+    method public void centerHorizontally(int, int, int, int, int, int, int, float);
+    method public void centerHorizontallyRtl(int, int);
+    method public void centerHorizontallyRtl(int, int, int, int, int, int, int, float);
+    method public void centerVertically(int, int);
+    method public void centerVertically(int, int, int, int, int, int, int, float);
+    method public void clear(int);
+    method public void clear(int, int);
+    method public void clone(android.content.Context!, int);
+    method public void clone(androidx.constraintlayout.widget.ConstraintLayout!);
+    method public void clone(androidx.constraintlayout.widget.Constraints!);
+    method public void clone(androidx.constraintlayout.widget.ConstraintSet!);
+    method public void connect(int, int, int, int);
+    method public void connect(int, int, int, int, int);
+    method public void constrainCircle(int, int, int, float);
+    method public void constrainDefaultHeight(int, int);
+    method public void constrainDefaultWidth(int, int);
+    method public void constrainHeight(int, int);
+    method public void constrainMaxHeight(int, int);
+    method public void constrainMaxWidth(int, int);
+    method public void constrainMinHeight(int, int);
+    method public void constrainMinWidth(int, int);
+    method public void constrainPercentHeight(int, float);
+    method public void constrainPercentWidth(int, float);
+    method public void constrainWidth(int, int);
+    method public void constrainedHeight(int, boolean);
+    method public void constrainedWidth(int, boolean);
+    method public void create(int, int);
+    method public void createBarrier(int, int, int, int...!);
+    method public void createHorizontalChain(int, int, int, int, int[]!, float[]!, int);
+    method public void createHorizontalChainRtl(int, int, int, int, int[]!, float[]!, int);
+    method public void createVerticalChain(int, int, int, int, int[]!, float[]!, int);
+    method public void dump(androidx.constraintlayout.motion.widget.MotionScene!, int...!);
+    method public boolean getApplyElevation(int);
+    method public androidx.constraintlayout.widget.ConstraintSet.Constraint! getConstraint(int);
+    method public java.util.HashMap<java.lang.String!,androidx.constraintlayout.widget.ConstraintAttribute!>! getCustomAttributeSet();
+    method public int getHeight(int);
+    method public int[]! getKnownIds();
+    method public androidx.constraintlayout.widget.ConstraintSet.Constraint! getParameters(int);
+    method public int[]! getReferencedIds(int);
+    method public String![]! getStateLabels();
+    method public int getVisibility(int);
+    method public int getVisibilityMode(int);
+    method public int getWidth(int);
+    method public boolean isForceId();
+    method public boolean isValidateOnParse();
+    method public void load(android.content.Context!, int);
+    method public void load(android.content.Context!, org.xmlpull.v1.XmlPullParser!);
+    method public boolean matchesLabels(java.lang.String!...!);
+    method public void parseColorAttributes(androidx.constraintlayout.widget.ConstraintSet.Constraint!, String!);
+    method public void parseFloatAttributes(androidx.constraintlayout.widget.ConstraintSet.Constraint!, String!);
+    method public void parseIntAttributes(androidx.constraintlayout.widget.ConstraintSet.Constraint!, String!);
+    method public void parseStringAttributes(androidx.constraintlayout.widget.ConstraintSet.Constraint!, String!);
+    method public void readFallback(androidx.constraintlayout.widget.ConstraintLayout!);
+    method public void readFallback(androidx.constraintlayout.widget.ConstraintSet!);
+    method public void removeAttribute(String!);
+    method public void removeFromHorizontalChain(int);
+    method public void removeFromVerticalChain(int);
+    method public void setAlpha(int, float);
+    method public void setApplyElevation(int, boolean);
+    method public void setBarrierType(int, int);
+    method public void setColorValue(int, String!, int);
+    method public void setDimensionRatio(int, String!);
+    method public void setEditorAbsoluteX(int, int);
+    method public void setEditorAbsoluteY(int, int);
+    method public void setElevation(int, float);
+    method public void setFloatValue(int, String!, float);
+    method public void setForceId(boolean);
+    method public void setGoneMargin(int, int, int);
+    method public void setGuidelineBegin(int, int);
+    method public void setGuidelineEnd(int, int);
+    method public void setGuidelinePercent(int, float);
+    method public void setHorizontalBias(int, float);
+    method public void setHorizontalChainStyle(int, int);
+    method public void setHorizontalWeight(int, float);
+    method public void setIntValue(int, String!, int);
+    method public void setLayoutWrapBehavior(int, int);
+    method public void setMargin(int, int, int);
+    method public void setReferencedIds(int, int...!);
+    method public void setRotation(int, float);
+    method public void setRotationX(int, float);
+    method public void setRotationY(int, float);
+    method public void setScaleX(int, float);
+    method public void setScaleY(int, float);
+    method public void setStateLabels(String!);
+    method public void setStateLabelsList(java.lang.String!...!);
+    method public void setStringValue(int, String!, String!);
+    method public void setTransformPivot(int, float, float);
+    method public void setTransformPivotX(int, float);
+    method public void setTransformPivotY(int, float);
+    method public void setTranslation(int, float, float);
+    method public void setTranslationX(int, float);
+    method public void setTranslationY(int, float);
+    method public void setTranslationZ(int, float);
+    method public void setValidateOnParse(boolean);
+    method public void setVerticalBias(int, float);
+    method public void setVerticalChainStyle(int, int);
+    method public void setVerticalWeight(int, float);
+    method public void setVisibility(int, int);
+    method public void setVisibilityMode(int, int);
+    method public void writeState(java.io.Writer!, androidx.constraintlayout.widget.ConstraintLayout!, int) throws java.io.IOException;
+    field public static final int BASELINE = 5; // 0x5
+    field public static final int BOTTOM = 4; // 0x4
+    field public static final int CHAIN_PACKED = 2; // 0x2
+    field public static final int CHAIN_SPREAD = 0; // 0x0
+    field public static final int CHAIN_SPREAD_INSIDE = 1; // 0x1
+    field public static final int CIRCLE_REFERENCE = 8; // 0x8
+    field public static final int END = 7; // 0x7
+    field public static final int GONE = 8; // 0x8
+    field public static final int HORIZONTAL = 0; // 0x0
+    field public static final int HORIZONTAL_GUIDELINE = 0; // 0x0
+    field public static final int INVISIBLE = 4; // 0x4
+    field public static final int LEFT = 1; // 0x1
+    field public static final int MATCH_CONSTRAINT = 0; // 0x0
+    field public static final int MATCH_CONSTRAINT_PERCENT = 2; // 0x2
+    field public static final int MATCH_CONSTRAINT_SPREAD = 0; // 0x0
+    field public static final int MATCH_CONSTRAINT_WRAP = 1; // 0x1
+    field public static final int PARENT_ID = 0; // 0x0
+    field public static final int RIGHT = 2; // 0x2
+    field public static final int ROTATE_LEFT_OF_PORTRATE = 4; // 0x4
+    field public static final int ROTATE_NONE = 0; // 0x0
+    field public static final int ROTATE_PORTRATE_OF_LEFT = 2; // 0x2
+    field public static final int ROTATE_PORTRATE_OF_RIGHT = 1; // 0x1
+    field public static final int ROTATE_RIGHT_OF_PORTRATE = 3; // 0x3
+    field public static final int START = 6; // 0x6
+    field public static final int TOP = 3; // 0x3
+    field public static final int UNSET = -1; // 0xffffffff
+    field public static final int VERTICAL = 1; // 0x1
+    field public static final int VERTICAL_GUIDELINE = 1; // 0x1
+    field public static final int VISIBILITY_MODE_IGNORE = 1; // 0x1
+    field public static final int VISIBILITY_MODE_NORMAL = 0; // 0x0
+    field public static final int VISIBLE = 0; // 0x0
+    field public static final int WRAP_CONTENT = -2; // 0xfffffffe
+    field public String! derivedState;
+    field public String! mIdString;
+    field public int mRotate;
+  }
+
+  public static class ConstraintSet.Constraint {
+    ctor public ConstraintSet.Constraint();
+    method public void applyDelta(androidx.constraintlayout.widget.ConstraintSet.Constraint!);
+    method public void applyTo(androidx.constraintlayout.widget.ConstraintLayout.LayoutParams!);
+    method public androidx.constraintlayout.widget.ConstraintSet.Constraint! clone();
+    method public void printDelta(String!);
+    field public final androidx.constraintlayout.widget.ConstraintSet.Layout! layout;
+    field public java.util.HashMap<java.lang.String!,androidx.constraintlayout.widget.ConstraintAttribute!>! mCustomConstraints;
+    field public final androidx.constraintlayout.widget.ConstraintSet.Motion! motion;
+    field public final androidx.constraintlayout.widget.ConstraintSet.PropertySet! propertySet;
+    field public final androidx.constraintlayout.widget.ConstraintSet.Transform! transform;
+  }
+
+  public static class ConstraintSet.Layout {
+    ctor public ConstraintSet.Layout();
+    method public void copyFrom(androidx.constraintlayout.widget.ConstraintSet.Layout!);
+    method public void dump(androidx.constraintlayout.motion.widget.MotionScene!, StringBuilder!);
+    field public static final int UNSET = -1; // 0xffffffff
+    field public static final int UNSET_GONE_MARGIN = -2147483648; // 0x80000000
+    field public int baselineMargin;
+    field public int baselineToBaseline;
+    field public int baselineToBottom;
+    field public int baselineToTop;
+    field public int bottomMargin;
+    field public int bottomToBottom;
+    field public int bottomToTop;
+    field public float circleAngle;
+    field public int circleConstraint;
+    field public int circleRadius;
+    field public boolean constrainedHeight;
+    field public boolean constrainedWidth;
+    field public String! dimensionRatio;
+    field public int editorAbsoluteX;
+    field public int editorAbsoluteY;
+    field public int endMargin;
+    field public int endToEnd;
+    field public int endToStart;
+    field public int goneBaselineMargin;
+    field public int goneBottomMargin;
+    field public int goneEndMargin;
+    field public int goneLeftMargin;
+    field public int goneRightMargin;
+    field public int goneStartMargin;
+    field public int goneTopMargin;
+    field public int guideBegin;
+    field public int guideEnd;
+    field public float guidePercent;
+    field public boolean guidelineUseRtl;
+    field public int heightDefault;
+    field public int heightMax;
+    field public int heightMin;
+    field public float heightPercent;
+    field public float horizontalBias;
+    field public int horizontalChainStyle;
+    field public float horizontalWeight;
+    field public int leftMargin;
+    field public int leftToLeft;
+    field public int leftToRight;
+    field public boolean mApply;
+    field public boolean mBarrierAllowsGoneWidgets;
+    field public int mBarrierDirection;
+    field public int mBarrierMargin;
+    field public String! mConstraintTag;
+    field public int mHeight;
+    field public int mHelperType;
+    field public boolean mIsGuideline;
+    field public boolean mOverride;
+    field public String! mReferenceIdString;
+    field public int[]! mReferenceIds;
+    field public int mWidth;
+    field public int mWrapBehavior;
+    field public int orientation;
+    field public int rightMargin;
+    field public int rightToLeft;
+    field public int rightToRight;
+    field public int startMargin;
+    field public int startToEnd;
+    field public int startToStart;
+    field public int topMargin;
+    field public int topToBottom;
+    field public int topToTop;
+    field public float verticalBias;
+    field public int verticalChainStyle;
+    field public float verticalWeight;
+    field public int widthDefault;
+    field public int widthMax;
+    field public int widthMin;
+    field public float widthPercent;
+  }
+
+  public static class ConstraintSet.Motion {
+    ctor public ConstraintSet.Motion();
+    method public void copyFrom(androidx.constraintlayout.widget.ConstraintSet.Motion!);
+    field public int mAnimateCircleAngleTo;
+    field public int mAnimateRelativeTo;
+    field public boolean mApply;
+    field public int mDrawPath;
+    field public float mMotionStagger;
+    field public int mPathMotionArc;
+    field public float mPathRotate;
+    field public int mPolarRelativeTo;
+    field public int mQuantizeInterpolatorID;
+    field public String! mQuantizeInterpolatorString;
+    field public int mQuantizeInterpolatorType;
+    field public float mQuantizeMotionPhase;
+    field public int mQuantizeMotionSteps;
+    field public String! mTransitionEasing;
+  }
+
+  public static class ConstraintSet.PropertySet {
+    ctor public ConstraintSet.PropertySet();
+    method public void copyFrom(androidx.constraintlayout.widget.ConstraintSet.PropertySet!);
+    field public float alpha;
+    field public boolean mApply;
+    field public float mProgress;
+    field public int mVisibilityMode;
+    field public int visibility;
+  }
+
+  public static class ConstraintSet.Transform {
+    ctor public ConstraintSet.Transform();
+    method public void copyFrom(androidx.constraintlayout.widget.ConstraintSet.Transform!);
+    field public boolean applyElevation;
+    field public float elevation;
+    field public boolean mApply;
+    field public float rotation;
+    field public float rotationX;
+    field public float rotationY;
+    field public float scaleX;
+    field public float scaleY;
+    field public int transformPivotTarget;
+    field public float transformPivotX;
+    field public float transformPivotY;
+    field public float translationX;
+    field public float translationY;
+    field public float translationZ;
+  }
+
+  public class Constraints extends android.view.ViewGroup {
+    ctor public Constraints(android.content.Context!);
+    ctor public Constraints(android.content.Context!, android.util.AttributeSet!);
+    ctor public Constraints(android.content.Context!, android.util.AttributeSet!, int);
+    method protected androidx.constraintlayout.widget.Constraints.LayoutParams! generateDefaultLayoutParams();
+    method public androidx.constraintlayout.widget.Constraints.LayoutParams! generateLayoutParams(android.util.AttributeSet!);
+    method public androidx.constraintlayout.widget.ConstraintSet! getConstraintSet();
+    field public static final String TAG = "Constraints";
+  }
+
+  public static class Constraints.LayoutParams extends androidx.constraintlayout.widget.ConstraintLayout.LayoutParams {
+    ctor public Constraints.LayoutParams(android.content.Context!, android.util.AttributeSet!);
+    ctor public Constraints.LayoutParams(androidx.constraintlayout.widget.Constraints.LayoutParams!);
+    ctor public Constraints.LayoutParams(int, int);
+    field public float alpha;
+    field public boolean applyElevation;
+    field public float elevation;
+    field public float rotation;
+    field public float rotationX;
+    field public float rotationY;
+    field public float scaleX;
+    field public float scaleY;
+    field public float transformPivotX;
+    field public float transformPivotY;
+    field public float translationX;
+    field public float translationY;
+    field public float translationZ;
+  }
+
+  public abstract class ConstraintsChangedListener {
+    ctor public ConstraintsChangedListener();
+    method public void postLayoutChange(int, int);
+    method public void preLayoutChange(int, int);
+  }
+
+  public class Group extends androidx.constraintlayout.widget.ConstraintHelper {
+    ctor public Group(android.content.Context!);
+    ctor public Group(android.content.Context!, android.util.AttributeSet!);
+    ctor public Group(android.content.Context!, android.util.AttributeSet!, int);
+    method public void onAttachedToWindow();
+  }
+
+  public class Guideline extends android.view.View {
+    ctor public Guideline(android.content.Context!);
+    ctor public Guideline(android.content.Context!, android.util.AttributeSet!);
+    ctor public Guideline(android.content.Context!, android.util.AttributeSet!, int);
+    ctor public Guideline(android.content.Context!, android.util.AttributeSet!, int, int);
+    method public void setFilterRedundantCalls(boolean);
+    method public void setGuidelineBegin(int);
+    method public void setGuidelineEnd(int);
+    method public void setGuidelinePercent(float);
+  }
+
+  public class Placeholder extends android.view.View {
+    ctor public Placeholder(android.content.Context!);
+    ctor public Placeholder(android.content.Context!, android.util.AttributeSet!);
+    ctor public Placeholder(android.content.Context!, android.util.AttributeSet!, int);
+    ctor public Placeholder(android.content.Context!, android.util.AttributeSet!, int, int);
+    method public android.view.View! getContent();
+    method public int getEmptyVisibility();
+    method public void onDraw(android.graphics.Canvas);
+    method public void setContentId(int);
+    method public void setEmptyVisibility(int);
+    method public void updatePostMeasure(androidx.constraintlayout.widget.ConstraintLayout!);
+    method public void updatePreLayout(androidx.constraintlayout.widget.ConstraintLayout!);
+  }
+
+  public class ReactiveGuide extends android.view.View implements androidx.constraintlayout.widget.SharedValues.SharedValuesListener {
+    ctor public ReactiveGuide(android.content.Context!);
+    ctor public ReactiveGuide(android.content.Context!, android.util.AttributeSet!);
+    ctor public ReactiveGuide(android.content.Context!, android.util.AttributeSet!, int);
+    ctor public ReactiveGuide(android.content.Context!, android.util.AttributeSet!, int, int);
+    method public int getApplyToConstraintSetId();
+    method public int getAttributeId();
+    method public boolean isAnimatingChange();
+    method public void onNewValue(int, int, int);
+    method public void setAnimateChange(boolean);
+    method public void setApplyToConstraintSetId(int);
+    method public void setAttributeId(int);
+    method public void setGuidelineBegin(int);
+    method public void setGuidelineEnd(int);
+    method public void setGuidelinePercent(float);
+  }
+
+  public class SharedValues {
+    ctor public SharedValues();
+    method public void addListener(int, androidx.constraintlayout.widget.SharedValues.SharedValuesListener!);
+    method public void clearListeners();
+    method public void fireNewValue(int, int);
+    method public int getValue(int);
+    method public void removeListener(androidx.constraintlayout.widget.SharedValues.SharedValuesListener!);
+    method public void removeListener(int, androidx.constraintlayout.widget.SharedValues.SharedValuesListener!);
+    field public static final int UNSET = -1; // 0xffffffff
+  }
+
+  public static interface SharedValues.SharedValuesListener {
+    method public void onNewValue(int, int, int);
+  }
+
+  public class StateSet {
+    ctor public StateSet(android.content.Context!, org.xmlpull.v1.XmlPullParser!);
+    method public int convertToConstraintSet(int, int, float, float);
+    method public boolean needsToChange(int, float, float);
+    method public void setOnConstraintsChanged(androidx.constraintlayout.widget.ConstraintsChangedListener!);
+    method public int stateGetConstraintID(int, int, int);
+    method public int updateConstraints(int, int, float, float);
+    field public static final String TAG = "ConstraintLayoutStates";
+  }
+
+  public abstract class VirtualLayout extends androidx.constraintlayout.widget.ConstraintHelper {
+    ctor public VirtualLayout(android.content.Context!);
+    ctor public VirtualLayout(android.content.Context!, android.util.AttributeSet!);
+    ctor public VirtualLayout(android.content.Context!, android.util.AttributeSet!, int);
+    method public void onAttachedToWindow();
+    method public void onMeasure(androidx.constraintlayout.core.widgets.VirtualLayout!, int, int);
+  }
+
+}
+
diff --git a/constraintlayout/constraintlayout/api/res-2.2.0-beta01.txt b/constraintlayout/constraintlayout/api/res-2.2.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/constraintlayout/constraintlayout/api/res-2.2.0-beta01.txt
diff --git a/constraintlayout/constraintlayout/api/restricted_2.2.0-beta01.txt b/constraintlayout/constraintlayout/api/restricted_2.2.0-beta01.txt
new file mode 100644
index 0000000..2d187a8
--- /dev/null
+++ b/constraintlayout/constraintlayout/api/restricted_2.2.0-beta01.txt
@@ -0,0 +1,1714 @@
+// Signature format: 4.0
+package androidx.constraintlayout.helper.widget {
+
+  public class Carousel extends androidx.constraintlayout.motion.widget.MotionHelper {
+    ctor public Carousel(android.content.Context!);
+    ctor public Carousel(android.content.Context!, android.util.AttributeSet!);
+    ctor public Carousel(android.content.Context!, android.util.AttributeSet!, int);
+    method public int getCount();
+    method public int getCurrentIndex();
+    method public boolean isInfinite();
+    method public void jumpToIndex(int);
+    method public void refresh();
+    method public void setAdapter(androidx.constraintlayout.helper.widget.Carousel.Adapter!);
+    method public void setInfinite(boolean);
+    method public void transitionToIndex(int, int);
+    field public static final int TOUCH_UP_CARRY_ON = 2; // 0x2
+    field public static final int TOUCH_UP_IMMEDIATE_STOP = 1; // 0x1
+  }
+
+  public static interface Carousel.Adapter {
+    method public int count();
+    method public void onNewItem(int);
+    method public void populate(android.view.View!, int);
+  }
+
+  public class CircularFlow extends androidx.constraintlayout.widget.VirtualLayout {
+    ctor public CircularFlow(android.content.Context!);
+    ctor public CircularFlow(android.content.Context!, android.util.AttributeSet!);
+    ctor public CircularFlow(android.content.Context!, android.util.AttributeSet!, int);
+    method public void addViewToCircularFlow(android.view.View!, int, float);
+    method public float[]! getAngles();
+    method public int[]! getRadius();
+    method public boolean isUpdatable(android.view.View!);
+    method public void setDefaultAngle(float);
+    method public void setDefaultRadius(int);
+    method public void updateAngle(android.view.View!, float);
+    method public void updateRadius(android.view.View!, int);
+    method public void updateReference(android.view.View!, int, float);
+  }
+
+  public class Flow extends androidx.constraintlayout.widget.VirtualLayout {
+    ctor public Flow(android.content.Context!);
+    ctor public Flow(android.content.Context!, android.util.AttributeSet!);
+    ctor public Flow(android.content.Context!, android.util.AttributeSet!, int);
+    method public void setFirstHorizontalBias(float);
+    method public void setFirstHorizontalStyle(int);
+    method public void setFirstVerticalBias(float);
+    method public void setFirstVerticalStyle(int);
+    method public void setHorizontalAlign(int);
+    method public void setHorizontalBias(float);
+    method public void setHorizontalGap(int);
+    method public void setHorizontalStyle(int);
+    method public void setLastHorizontalBias(float);
+    method public void setLastHorizontalStyle(int);
+    method public void setLastVerticalBias(float);
+    method public void setLastVerticalStyle(int);
+    method public void setMaxElementsWrap(int);
+    method public void setOrientation(int);
+    method public void setPadding(int);
+    method public void setPaddingBottom(int);
+    method public void setPaddingLeft(int);
+    method public void setPaddingRight(int);
+    method public void setPaddingTop(int);
+    method public void setVerticalAlign(int);
+    method public void setVerticalBias(float);
+    method public void setVerticalGap(int);
+    method public void setVerticalStyle(int);
+    method public void setWrapMode(int);
+    field public static final int CHAIN_PACKED = 2; // 0x2
+    field public static final int CHAIN_SPREAD = 0; // 0x0
+    field public static final int CHAIN_SPREAD_INSIDE = 1; // 0x1
+    field public static final int HORIZONTAL = 0; // 0x0
+    field public static final int HORIZONTAL_ALIGN_CENTER = 2; // 0x2
+    field public static final int HORIZONTAL_ALIGN_END = 1; // 0x1
+    field public static final int HORIZONTAL_ALIGN_START = 0; // 0x0
+    field public static final int VERTICAL = 1; // 0x1
+    field public static final int VERTICAL_ALIGN_BASELINE = 3; // 0x3
+    field public static final int VERTICAL_ALIGN_BOTTOM = 1; // 0x1
+    field public static final int VERTICAL_ALIGN_CENTER = 2; // 0x2
+    field public static final int VERTICAL_ALIGN_TOP = 0; // 0x0
+    field public static final int WRAP_ALIGNED = 2; // 0x2
+    field public static final int WRAP_CHAIN = 1; // 0x1
+    field public static final int WRAP_NONE = 0; // 0x0
+  }
+
+  public class Grid extends androidx.constraintlayout.widget.VirtualLayout {
+    ctor public Grid(android.content.Context!);
+    ctor public Grid(android.content.Context!, android.util.AttributeSet!);
+    ctor public Grid(android.content.Context!, android.util.AttributeSet!, int);
+    method public String! getColumnWeights();
+    method public int getColumns();
+    method public float getHorizontalGaps();
+    method public int getOrientation();
+    method public String! getRowWeights();
+    method public int getRows();
+    method public String! getSkips();
+    method public String! getSpans();
+    method public float getVerticalGaps();
+    method public void setColumnWeights(String!);
+    method public void setColumns(int);
+    method public void setHorizontalGaps(float);
+    method public void setOrientation(int);
+    method public void setRowWeights(String!);
+    method public void setRows(int);
+    method public void setSkips(String!);
+    method public void setSpans(CharSequence!);
+    method public void setVerticalGaps(float);
+    field public static final int HORIZONTAL = 0; // 0x0
+    field public static final int VERTICAL = 1; // 0x1
+  }
+
+  public class Layer extends androidx.constraintlayout.widget.ConstraintHelper {
+    ctor public Layer(android.content.Context!);
+    ctor public Layer(android.content.Context!, android.util.AttributeSet!);
+    ctor public Layer(android.content.Context!, android.util.AttributeSet!, int);
+    method protected void calcCenters();
+    field protected float mComputedCenterX;
+    field protected float mComputedCenterY;
+    field protected float mComputedMaxX;
+    field protected float mComputedMaxY;
+    field protected float mComputedMinX;
+    field protected float mComputedMinY;
+  }
+
+  public class MotionEffect extends androidx.constraintlayout.motion.widget.MotionHelper {
+    ctor public MotionEffect(android.content.Context!);
+    ctor public MotionEffect(android.content.Context!, android.util.AttributeSet!);
+    ctor public MotionEffect(android.content.Context!, android.util.AttributeSet!, int);
+    field public static final int AUTO = -1; // 0xffffffff
+    field public static final int EAST = 2; // 0x2
+    field public static final int NORTH = 0; // 0x0
+    field public static final int SOUTH = 1; // 0x1
+    field public static final String TAG = "FadeMove";
+    field public static final int WEST = 3; // 0x3
+  }
+
+  public class MotionPlaceholder extends androidx.constraintlayout.widget.VirtualLayout {
+    ctor public MotionPlaceholder(android.content.Context!);
+    ctor public MotionPlaceholder(android.content.Context!, android.util.AttributeSet!);
+    ctor public MotionPlaceholder(android.content.Context!, android.util.AttributeSet!, int);
+    ctor public MotionPlaceholder(android.content.Context!, android.util.AttributeSet!, int, int);
+  }
+
+}
+
+package androidx.constraintlayout.motion.utils {
+
+  public class CustomSupport {
+    ctor public CustomSupport();
+    method public static void setInterpolatedValue(androidx.constraintlayout.widget.ConstraintAttribute!, android.view.View!, float[]!);
+  }
+
+  public class StopLogic extends androidx.constraintlayout.motion.widget.MotionInterpolator {
+    ctor public StopLogic();
+    method public void config(float, float, float, float, float, float);
+    method public String! debug(String!, float);
+    method public float getInterpolation(float);
+    method public float getVelocity();
+    method public float getVelocity(float);
+    method public boolean isStopped();
+    method public void springConfig(float, float, float, float, float, float, float, int);
+  }
+
+  public abstract class ViewOscillator extends androidx.constraintlayout.core.motion.utils.KeyCycleOscillator {
+    ctor public ViewOscillator();
+    method public static androidx.constraintlayout.motion.utils.ViewOscillator! makeSpline(String!);
+    method public abstract void setProperty(android.view.View!, float);
+  }
+
+  public static class ViewOscillator.PathRotateSet extends androidx.constraintlayout.motion.utils.ViewOscillator {
+    ctor public ViewOscillator.PathRotateSet();
+    method public void setPathRotate(android.view.View!, float, double, double);
+    method public void setProperty(android.view.View!, float);
+  }
+
+  public abstract class ViewSpline extends androidx.constraintlayout.core.motion.utils.SplineSet {
+    ctor public ViewSpline();
+    method public static androidx.constraintlayout.motion.utils.ViewSpline! makeCustomSpline(String!, android.util.SparseArray<androidx.constraintlayout.widget.ConstraintAttribute!>!);
+    method public static androidx.constraintlayout.motion.utils.ViewSpline! makeSpline(String!);
+    method public abstract void setProperty(android.view.View!, float);
+  }
+
+  public static class ViewSpline.CustomSet extends androidx.constraintlayout.motion.utils.ViewSpline {
+    ctor public ViewSpline.CustomSet(String!, android.util.SparseArray<androidx.constraintlayout.widget.ConstraintAttribute!>!);
+    method public void setPoint(int, androidx.constraintlayout.widget.ConstraintAttribute!);
+    method public void setProperty(android.view.View!, float);
+  }
+
+  public static class ViewSpline.PathRotate extends androidx.constraintlayout.motion.utils.ViewSpline {
+    ctor public ViewSpline.PathRotate();
+    method public void setPathRotate(android.view.View!, float, double, double);
+    method public void setProperty(android.view.View!, float);
+  }
+
+  public class ViewState {
+    ctor public ViewState();
+    method public void getState(android.view.View!);
+    method public int height();
+    method public int width();
+    field public int bottom;
+    field public int left;
+    field public int right;
+    field public float rotation;
+    field public int top;
+  }
+
+  public abstract class ViewTimeCycle extends androidx.constraintlayout.core.motion.utils.TimeCycleSplineSet {
+    ctor public ViewTimeCycle();
+    method public float get(float, long, android.view.View!, androidx.constraintlayout.core.motion.utils.KeyCache!);
+    method public static androidx.constraintlayout.motion.utils.ViewTimeCycle! makeCustomSpline(String!, android.util.SparseArray<androidx.constraintlayout.widget.ConstraintAttribute!>!);
+    method public static androidx.constraintlayout.motion.utils.ViewTimeCycle! makeSpline(String!, long);
+    method public abstract boolean setProperty(android.view.View!, float, long, androidx.constraintlayout.core.motion.utils.KeyCache!);
+  }
+
+  public static class ViewTimeCycle.CustomSet extends androidx.constraintlayout.motion.utils.ViewTimeCycle {
+    ctor public ViewTimeCycle.CustomSet(String!, android.util.SparseArray<androidx.constraintlayout.widget.ConstraintAttribute!>!);
+    method public void setPoint(int, androidx.constraintlayout.widget.ConstraintAttribute!, float, int, float);
+    method public boolean setProperty(android.view.View!, float, long, androidx.constraintlayout.core.motion.utils.KeyCache!);
+  }
+
+  public static class ViewTimeCycle.PathRotate extends androidx.constraintlayout.motion.utils.ViewTimeCycle {
+    ctor public ViewTimeCycle.PathRotate();
+    method public boolean setPathRotate(android.view.View!, androidx.constraintlayout.core.motion.utils.KeyCache!, float, long, double, double);
+    method public boolean setProperty(android.view.View!, float, long, androidx.constraintlayout.core.motion.utils.KeyCache!);
+  }
+
+}
+
+package androidx.constraintlayout.motion.widget {
+
+  public interface Animatable {
+    method public float getProgress();
+    method public void setProgress(float);
+  }
+
+  public interface CustomFloatAttributes {
+    method public float get(String!);
+    method public String![]! getListOfAttributes();
+    method public void set(String!, float);
+  }
+
+  public class Debug {
+    ctor public Debug();
+    method public static void dumpLayoutParams(android.view.ViewGroup!, String!);
+    method public static void dumpLayoutParams(android.view.ViewGroup.LayoutParams!, String!);
+    method public static void dumpPoc(Object!);
+    method public static String! getActionType(android.view.MotionEvent!);
+    method public static String! getCallFrom(int);
+    method public static String! getLoc();
+    method public static String! getLocation();
+    method public static String! getLocation2();
+    method public static String! getName(android.content.Context!, int);
+    method public static String! getName(android.content.Context!, int[]!);
+    method public static String! getName(android.view.View!);
+    method public static String! getState(androidx.constraintlayout.motion.widget.MotionLayout!, int);
+    method public static String! getState(androidx.constraintlayout.motion.widget.MotionLayout!, int, int);
+    method public static void logStack(String!, String!, int);
+    method public static void printStack(String!, int);
+  }
+
+  public class DesignTool {
+    ctor public DesignTool(androidx.constraintlayout.motion.widget.MotionLayout!);
+    method public int designAccess(int, String!, Object!, float[]!, int, float[]!, int);
+    method public void disableAutoTransition(boolean);
+    method public void dumpConstraintSet(String!);
+    method public int getAnimationKeyFrames(Object!, float[]!);
+    method public int getAnimationPath(Object!, float[]!, int);
+    method public void getAnimationRectangles(Object!, float[]!);
+    method public String! getEndState();
+    method public int getKeyFrameInfo(Object!, int, int[]!);
+    method public float getKeyFramePosition(Object!, int, float, float);
+    method public int getKeyFramePositions(Object!, int[]!, float[]!);
+    method public Object! getKeyframe(int, int, int);
+    method public Object! getKeyframe(Object!, int, int);
+    method public Object! getKeyframeAtLocation(Object!, float, float);
+    method public Boolean! getPositionKeyframe(Object!, Object!, float, float, String![]!, float[]!);
+    method public float getProgress();
+    method public String! getStartState();
+    method public String! getState();
+    method public long getTransitionTimeMs();
+    method public boolean isInTransition();
+    method public void setAttributes(int, String!, Object!, Object!);
+    method public void setKeyFrame(Object!, int, String!, Object!);
+    method public boolean setKeyFramePosition(Object!, int, int, float, float);
+    method public void setKeyframe(Object!, String!, Object!);
+    method public void setState(String!);
+    method public void setToolPosition(float);
+    method public void setTransition(String!, String!);
+    method public void setViewDebug(Object!, int);
+  }
+
+  public interface FloatLayout {
+    method public void layout(float, float, float, float);
+  }
+
+  public abstract class Key {
+    ctor public Key();
+    method public abstract void addValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.motion.utils.ViewSpline!>!);
+    method public abstract androidx.constraintlayout.motion.widget.Key! clone();
+    method public androidx.constraintlayout.motion.widget.Key! copy(androidx.constraintlayout.motion.widget.Key!);
+    method public int getFramePosition();
+    method public void setFramePosition(int);
+    method public void setInterpolation(java.util.HashMap<java.lang.String!,java.lang.Integer!>!);
+    method public abstract void setValue(String!, Object!);
+    method public androidx.constraintlayout.motion.widget.Key! setViewId(int);
+    field public static final String ALPHA = "alpha";
+    field public static final String CURVEFIT = "curveFit";
+    field public static final String CUSTOM = "CUSTOM";
+    field public static final String ELEVATION = "elevation";
+    field public static final String MOTIONPROGRESS = "motionProgress";
+    field public static final String PIVOT_X = "transformPivotX";
+    field public static final String PIVOT_Y = "transformPivotY";
+    field public static final String PROGRESS = "progress";
+    field public static final String ROTATION = "rotation";
+    field public static final String ROTATION_X = "rotationX";
+    field public static final String ROTATION_Y = "rotationY";
+    field public static final String SCALE_X = "scaleX";
+    field public static final String SCALE_Y = "scaleY";
+    field public static final String TRANSITIONEASING = "transitionEasing";
+    field public static final String TRANSITION_PATH_ROTATE = "transitionPathRotate";
+    field public static final String TRANSLATION_X = "translationX";
+    field public static final String TRANSLATION_Y = "translationY";
+    field public static final String TRANSLATION_Z = "translationZ";
+    field public static int UNSET;
+    field public static final String VISIBILITY = "visibility";
+    field public static final String WAVE_OFFSET = "waveOffset";
+    field public static final String WAVE_PERIOD = "wavePeriod";
+    field public static final String WAVE_PHASE = "wavePhase";
+    field public static final String WAVE_VARIES_BY = "waveVariesBy";
+    field protected int mType;
+  }
+
+  public class KeyAttributes extends androidx.constraintlayout.motion.widget.Key {
+    ctor public KeyAttributes();
+    method public void addValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.motion.utils.ViewSpline!>!);
+    method public androidx.constraintlayout.motion.widget.Key! clone();
+    method public void getAttributeNames(java.util.HashSet<java.lang.String!>!);
+    method public void load(android.content.Context!, android.util.AttributeSet!);
+    method public void setValue(String!, Object!);
+    field public static final int KEY_TYPE = 1; // 0x1
+  }
+
+  public class KeyCycle extends androidx.constraintlayout.motion.widget.Key {
+    ctor public KeyCycle();
+    method public void addCycleValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.motion.utils.ViewOscillator!>!);
+    method public void addValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.motion.utils.ViewSpline!>!);
+    method public androidx.constraintlayout.motion.widget.Key! clone();
+    method public void getAttributeNames(java.util.HashSet<java.lang.String!>!);
+    method public float getValue(String!);
+    method public void load(android.content.Context!, android.util.AttributeSet!);
+    method public void setValue(String!, Object!);
+    field public static final int KEY_TYPE = 4; // 0x4
+    field public static final int SHAPE_BOUNCE = 6; // 0x6
+    field public static final int SHAPE_COS_WAVE = 5; // 0x5
+    field public static final int SHAPE_REVERSE_SAW_WAVE = 4; // 0x4
+    field public static final int SHAPE_SAW_WAVE = 3; // 0x3
+    field public static final int SHAPE_SIN_WAVE = 0; // 0x0
+    field public static final int SHAPE_SQUARE_WAVE = 1; // 0x1
+    field public static final int SHAPE_TRIANGLE_WAVE = 2; // 0x2
+    field public static final String WAVE_OFFSET = "waveOffset";
+    field public static final String WAVE_PERIOD = "wavePeriod";
+    field public static final String WAVE_PHASE = "wavePhase";
+    field public static final String WAVE_SHAPE = "waveShape";
+  }
+
+  public class KeyFrames {
+    ctor public KeyFrames();
+    ctor public KeyFrames(android.content.Context!, org.xmlpull.v1.XmlPullParser!);
+    method public void addAllFrames(androidx.constraintlayout.motion.widget.MotionController!);
+    method public void addFrames(androidx.constraintlayout.motion.widget.MotionController!);
+    method public void addKey(androidx.constraintlayout.motion.widget.Key!);
+    method public java.util.ArrayList<androidx.constraintlayout.motion.widget.Key!>! getKeyFramesForView(int);
+    method public java.util.Set<java.lang.Integer!>! getKeys();
+    field public static final int UNSET = -1; // 0xffffffff
+  }
+
+  public class KeyPosition extends androidx.constraintlayout.motion.widget.Key {
+    ctor public KeyPosition();
+    method public void addValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.motion.utils.ViewSpline!>!);
+    method public androidx.constraintlayout.motion.widget.Key! clone();
+    method public boolean intersects(int, int, android.graphics.RectF!, android.graphics.RectF!, float, float);
+    method public void load(android.content.Context!, android.util.AttributeSet!);
+    method public void positionAttributes(android.view.View!, android.graphics.RectF!, android.graphics.RectF!, float, float, String![]!, float[]!);
+    method public void setType(int);
+    method public void setValue(String!, Object!);
+    field public static final String DRAWPATH = "drawPath";
+    field public static final String PERCENT_HEIGHT = "percentHeight";
+    field public static final String PERCENT_WIDTH = "percentWidth";
+    field public static final String PERCENT_X = "percentX";
+    field public static final String PERCENT_Y = "percentY";
+    field public static final String SIZE_PERCENT = "sizePercent";
+    field public static final String TRANSITION_EASING = "transitionEasing";
+    field public static final int TYPE_AXIS = 3; // 0x3
+    field public static final int TYPE_CARTESIAN = 0; // 0x0
+    field public static final int TYPE_PATH = 1; // 0x1
+    field public static final int TYPE_SCREEN = 2; // 0x2
+  }
+
+  public class KeyTimeCycle extends androidx.constraintlayout.motion.widget.Key {
+    ctor public KeyTimeCycle();
+    method public void addTimeValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.motion.utils.ViewTimeCycle!>!);
+    method public void addValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.motion.utils.ViewSpline!>!);
+    method public androidx.constraintlayout.motion.widget.Key! clone();
+    method public void getAttributeNames(java.util.HashSet<java.lang.String!>!);
+    method public void load(android.content.Context!, android.util.AttributeSet!);
+    method public void setValue(String!, Object!);
+    field public static final int KEY_TYPE = 3; // 0x3
+    field public static final int SHAPE_BOUNCE = 6; // 0x6
+    field public static final int SHAPE_COS_WAVE = 5; // 0x5
+    field public static final int SHAPE_REVERSE_SAW_WAVE = 4; // 0x4
+    field public static final int SHAPE_SAW_WAVE = 3; // 0x3
+    field public static final int SHAPE_SIN_WAVE = 0; // 0x0
+    field public static final int SHAPE_SQUARE_WAVE = 1; // 0x1
+    field public static final int SHAPE_TRIANGLE_WAVE = 2; // 0x2
+    field public static final String WAVE_OFFSET = "waveOffset";
+    field public static final String WAVE_PERIOD = "wavePeriod";
+    field public static final String WAVE_SHAPE = "waveShape";
+  }
+
+  public class KeyTrigger extends androidx.constraintlayout.motion.widget.Key {
+    ctor public KeyTrigger();
+    method public void addValues(java.util.HashMap<java.lang.String!,androidx.constraintlayout.motion.utils.ViewSpline!>!);
+    method public androidx.constraintlayout.motion.widget.Key! clone();
+    method public void conditionallyFire(float, android.view.View!);
+    method public void getAttributeNames(java.util.HashSet<java.lang.String!>!);
+    method public void load(android.content.Context!, android.util.AttributeSet!);
+    method public void setValue(String!, Object!);
+    field public static final String CROSS = "CROSS";
+    field public static final int KEY_TYPE = 5; // 0x5
+    field public static final String NEGATIVE_CROSS = "negativeCross";
+    field public static final String POSITIVE_CROSS = "positiveCross";
+    field public static final String POST_LAYOUT = "postLayout";
+    field public static final String TRIGGER_COLLISION_ID = "triggerCollisionId";
+    field public static final String TRIGGER_COLLISION_VIEW = "triggerCollisionView";
+    field public static final String TRIGGER_ID = "triggerID";
+    field public static final String TRIGGER_RECEIVER = "triggerReceiver";
+    field public static final String TRIGGER_SLACK = "triggerSlack";
+    field public static final String VIEW_TRANSITION_ON_CROSS = "viewTransitionOnCross";
+    field public static final String VIEW_TRANSITION_ON_NEGATIVE_CROSS = "viewTransitionOnNegativeCross";
+    field public static final String VIEW_TRANSITION_ON_POSITIVE_CROSS = "viewTransitionOnPositiveCross";
+  }
+
+  public class MotionController {
+    method public void addKey(androidx.constraintlayout.motion.widget.Key!);
+    method public int getAnimateRelativeTo();
+    method public void getCenter(double, float[]!, float[]!);
+    method public float getCenterX();
+    method public float getCenterY();
+    method public int getDrawPath();
+    method public float getFinalHeight();
+    method public float getFinalWidth();
+    method public float getFinalX();
+    method public float getFinalY();
+    method public int getKeyFrameInfo(int, int[]!);
+    method public int getKeyFramePositions(int[]!, float[]!);
+    method public float getStartHeight();
+    method public float getStartWidth();
+    method public float getStartX();
+    method public float getStartY();
+    method public int getTransformPivotTarget();
+    method public android.view.View! getView();
+    method public void remeasure();
+    method public void setDrawPath(int);
+    method public void setPathMotionArc(int);
+    method public void setStartState(androidx.constraintlayout.motion.utils.ViewState!, android.view.View!, int, int, int);
+    method public void setTransformPivotTarget(int);
+    method public void setView(android.view.View!);
+    method public void setup(int, int, float, long);
+    method public void setupRelative(androidx.constraintlayout.motion.widget.MotionController!);
+    field public static final int DRAW_PATH_AS_CONFIGURED = 4; // 0x4
+    field public static final int DRAW_PATH_BASIC = 1; // 0x1
+    field public static final int DRAW_PATH_CARTESIAN = 3; // 0x3
+    field public static final int DRAW_PATH_NONE = 0; // 0x0
+    field public static final int DRAW_PATH_RECTANGLE = 5; // 0x5
+    field public static final int DRAW_PATH_RELATIVE = 2; // 0x2
+    field public static final int DRAW_PATH_SCREEN = 6; // 0x6
+    field public static final int HORIZONTAL_PATH_X = 2; // 0x2
+    field public static final int HORIZONTAL_PATH_Y = 3; // 0x3
+    field public static final int PATH_PERCENT = 0; // 0x0
+    field public static final int PATH_PERPENDICULAR = 1; // 0x1
+    field public static final int ROTATION_LEFT = 2; // 0x2
+    field public static final int ROTATION_RIGHT = 1; // 0x1
+    field public static final int VERTICAL_PATH_X = 4; // 0x4
+    field public static final int VERTICAL_PATH_Y = 5; // 0x5
+  }
+
+  public class MotionHelper extends androidx.constraintlayout.widget.ConstraintHelper implements androidx.constraintlayout.motion.widget.MotionHelperInterface {
+    ctor public MotionHelper(android.content.Context!);
+    ctor public MotionHelper(android.content.Context!, android.util.AttributeSet!);
+    ctor public MotionHelper(android.content.Context!, android.util.AttributeSet!, int);
+    method public float getProgress();
+    method public boolean isDecorator();
+    method public boolean isUseOnHide();
+    method public boolean isUsedOnShow();
+    method public void onFinishedMotionScene(androidx.constraintlayout.motion.widget.MotionLayout!);
+    method public void onPostDraw(android.graphics.Canvas!);
+    method public void onPreDraw(android.graphics.Canvas!);
+    method public void onPreSetup(androidx.constraintlayout.motion.widget.MotionLayout!, java.util.HashMap<android.view.View!,androidx.constraintlayout.motion.widget.MotionController!>!);
+    method public void onTransitionChange(androidx.constraintlayout.motion.widget.MotionLayout!, int, int, float);
+    method public void onTransitionCompleted(androidx.constraintlayout.motion.widget.MotionLayout!, int);
+    method public void onTransitionStarted(androidx.constraintlayout.motion.widget.MotionLayout!, int, int);
+    method public void onTransitionTrigger(androidx.constraintlayout.motion.widget.MotionLayout!, int, boolean, float);
+    method public void setProgress(android.view.View!, float);
+    method public void setProgress(float);
+    field protected android.view.View![]! views;
+  }
+
+  public interface MotionHelperInterface extends androidx.constraintlayout.motion.widget.Animatable androidx.constraintlayout.motion.widget.MotionLayout.TransitionListener {
+    method public boolean isDecorator();
+    method public boolean isUseOnHide();
+    method public boolean isUsedOnShow();
+    method public void onFinishedMotionScene(androidx.constraintlayout.motion.widget.MotionLayout!);
+    method public void onPostDraw(android.graphics.Canvas!);
+    method public void onPreDraw(android.graphics.Canvas!);
+    method public void onPreSetup(androidx.constraintlayout.motion.widget.MotionLayout!, java.util.HashMap<android.view.View!,androidx.constraintlayout.motion.widget.MotionController!>!);
+  }
+
+  public abstract class MotionInterpolator implements android.view.animation.Interpolator {
+    ctor public MotionInterpolator();
+    method public abstract float getVelocity();
+  }
+
+  public class MotionLayout extends androidx.constraintlayout.widget.ConstraintLayout implements androidx.core.view.NestedScrollingParent3 {
+    ctor public MotionLayout(android.content.Context);
+    ctor public MotionLayout(android.content.Context, android.util.AttributeSet?);
+    ctor public MotionLayout(android.content.Context, android.util.AttributeSet?, int);
+    method public void addTransitionListener(androidx.constraintlayout.motion.widget.MotionLayout.TransitionListener!);
+    method public boolean applyViewTransition(int, androidx.constraintlayout.motion.widget.MotionController!);
+    method public androidx.constraintlayout.widget.ConstraintSet! cloneConstraintSet(int);
+    method public void enableTransition(int, boolean);
+    method public void enableViewTransition(int, boolean);
+    method protected void fireTransitionCompleted();
+    method public void fireTrigger(int, boolean, float);
+    method public androidx.constraintlayout.widget.ConstraintSet! getConstraintSet(int);
+    method @IdRes public int[]! getConstraintSetIds();
+    method public int getCurrentState();
+    method public java.util.ArrayList<androidx.constraintlayout.motion.widget.MotionScene.Transition!>! getDefinedTransitions();
+    method public androidx.constraintlayout.motion.widget.DesignTool! getDesignTool();
+    method public int getEndState();
+    method public int[]! getMatchingConstraintSetIds(java.lang.String!...!);
+    method protected long getNanoTime();
+    method public float getProgress();
+    method public androidx.constraintlayout.motion.widget.MotionScene! getScene();
+    method public int getStartState();
+    method public float getTargetPosition();
+    method public androidx.constraintlayout.motion.widget.MotionScene.Transition! getTransition(int);
+    method public android.os.Bundle! getTransitionState();
+    method public long getTransitionTimeMs();
+    method public float getVelocity();
+    method public void getViewVelocity(android.view.View!, float, float, float[]!, int);
+    method public boolean isDelayedApplicationOfInitialState();
+    method public boolean isInRotation();
+    method public boolean isInteractionEnabled();
+    method public boolean isViewTransitionEnabled(int);
+    method public void jumpToState(int);
+    method protected androidx.constraintlayout.motion.widget.MotionLayout.MotionTracker! obtainVelocityTracker();
+    method public void onNestedPreScroll(android.view.View, int, int, int[], int);
+    method public void onNestedScroll(android.view.View, int, int, int, int, int);
+    method public void onNestedScroll(android.view.View, int, int, int, int, int, int[]!);
+    method public void onNestedScrollAccepted(android.view.View, android.view.View, int, int);
+    method public boolean onStartNestedScroll(android.view.View, android.view.View, int, int);
+    method public void onStopNestedScroll(android.view.View, int);
+    method @Deprecated public void rebuildMotion();
+    method public void rebuildScene();
+    method public boolean removeTransitionListener(androidx.constraintlayout.motion.widget.MotionLayout.TransitionListener!);
+    method public void rotateTo(int, int);
+    method public void scheduleTransitionTo(int);
+    method public void setDebugMode(int);
+    method public void setDelayedApplicationOfInitialState(boolean);
+    method public void setInteractionEnabled(boolean);
+    method public void setInterpolatedProgress(float);
+    method public void setOnHide(float);
+    method public void setOnShow(float);
+    method public void setProgress(float);
+    method public void setProgress(float, float);
+    method public void setScene(androidx.constraintlayout.motion.widget.MotionScene!);
+    method protected void setTransition(androidx.constraintlayout.motion.widget.MotionScene.Transition!);
+    method public void setTransition(int);
+    method public void setTransition(int, int);
+    method public void setTransitionDuration(int);
+    method public void setTransitionListener(androidx.constraintlayout.motion.widget.MotionLayout.TransitionListener!);
+    method public void setTransitionState(android.os.Bundle!);
+    method public void touchAnimateTo(int, float, float);
+    method public void touchSpringTo(float, float);
+    method public void transitionToEnd();
+    method public void transitionToEnd(Runnable!);
+    method public void transitionToStart();
+    method public void transitionToStart(Runnable!);
+    method public void transitionToState(int);
+    method public void transitionToState(int, int);
+    method public void transitionToState(int, int, int);
+    method public void transitionToState(int, int, int, int);
+    method public void updateState();
+    method public void updateState(int, androidx.constraintlayout.widget.ConstraintSet!);
+    method public void updateStateAnimate(int, androidx.constraintlayout.widget.ConstraintSet!, int);
+    method public void viewTransition(int, android.view.View!...!);
+    field public static final int DEBUG_SHOW_NONE = 0; // 0x0
+    field public static final int DEBUG_SHOW_PATH = 2; // 0x2
+    field public static final int DEBUG_SHOW_PROGRESS = 1; // 0x1
+    field public static boolean IS_IN_EDIT_MODE;
+    field public static final int TOUCH_UP_COMPLETE = 0; // 0x0
+    field public static final int TOUCH_UP_COMPLETE_TO_END = 2; // 0x2
+    field public static final int TOUCH_UP_COMPLETE_TO_START = 1; // 0x1
+    field public static final int TOUCH_UP_DECELERATE = 4; // 0x4
+    field public static final int TOUCH_UP_DECELERATE_AND_COMPLETE = 5; // 0x5
+    field public static final int TOUCH_UP_NEVER_TO_END = 7; // 0x7
+    field public static final int TOUCH_UP_NEVER_TO_START = 6; // 0x6
+    field public static final int TOUCH_UP_STOP = 3; // 0x3
+    field public static final int VELOCITY_LAYOUT = 1; // 0x1
+    field public static final int VELOCITY_POST_LAYOUT = 0; // 0x0
+    field public static final int VELOCITY_STATIC_LAYOUT = 3; // 0x3
+    field public static final int VELOCITY_STATIC_POST_LAYOUT = 2; // 0x2
+    field protected boolean mMeasureDuringTransition;
+  }
+
+  protected static interface MotionLayout.MotionTracker {
+    method public void addMovement(android.view.MotionEvent!);
+    method public void clear();
+    method public void computeCurrentVelocity(int);
+    method public void computeCurrentVelocity(int, float);
+    method public float getXVelocity();
+    method public float getXVelocity(int);
+    method public float getYVelocity();
+    method public float getYVelocity(int);
+    method public void recycle();
+  }
+
+  public static interface MotionLayout.TransitionListener {
+    method public void onTransitionChange(androidx.constraintlayout.motion.widget.MotionLayout!, int, int, float);
+    method public void onTransitionCompleted(androidx.constraintlayout.motion.widget.MotionLayout!, int);
+    method public void onTransitionStarted(androidx.constraintlayout.motion.widget.MotionLayout!, int, int);
+    method public void onTransitionTrigger(androidx.constraintlayout.motion.widget.MotionLayout!, int, boolean, float);
+  }
+
+  public class MotionScene {
+    ctor public MotionScene(androidx.constraintlayout.motion.widget.MotionLayout!);
+    method public void addOnClickListeners(androidx.constraintlayout.motion.widget.MotionLayout!, int);
+    method public void addTransition(androidx.constraintlayout.motion.widget.MotionScene.Transition!);
+    method public boolean applyViewTransition(int, androidx.constraintlayout.motion.widget.MotionController!);
+    method public androidx.constraintlayout.motion.widget.MotionScene.Transition! bestTransitionFor(int, float, float, android.view.MotionEvent!);
+    method public void disableAutoTransition(boolean);
+    method public void enableViewTransition(int, boolean);
+    method public int gatPathMotionArc();
+    method public androidx.constraintlayout.widget.ConstraintSet! getConstraintSet(android.content.Context!, String!);
+    method public int[]! getConstraintSetIds();
+    method public java.util.ArrayList<androidx.constraintlayout.motion.widget.MotionScene.Transition!>! getDefinedTransitions();
+    method public int getDuration();
+    method public android.view.animation.Interpolator! getInterpolator();
+    method public void getKeyFrames(androidx.constraintlayout.motion.widget.MotionController!);
+    method public int[]! getMatchingStateLabels(java.lang.String!...!);
+    method public float getPathPercent(android.view.View!, int);
+    method public float getStaggered();
+    method public androidx.constraintlayout.motion.widget.MotionScene.Transition! getTransitionById(int);
+    method public java.util.List<androidx.constraintlayout.motion.widget.MotionScene.Transition!>! getTransitionsWithState(int);
+    method public boolean isViewTransitionEnabled(int);
+    method public int lookUpConstraintId(String!);
+    method public String! lookUpConstraintName(int);
+    method protected void onLayout(boolean, int, int, int, int);
+    method public void removeTransition(androidx.constraintlayout.motion.widget.MotionScene.Transition!);
+    method public void setConstraintSet(int, androidx.constraintlayout.widget.ConstraintSet!);
+    method public void setDuration(int);
+    method public void setKeyframe(android.view.View!, int, String!, Object!);
+    method public void setRtl(boolean);
+    method public void setTransition(androidx.constraintlayout.motion.widget.MotionScene.Transition!);
+    method public static String! stripID(String!);
+    method public boolean validateLayout(androidx.constraintlayout.motion.widget.MotionLayout!);
+    method public void viewTransition(int, android.view.View!...!);
+    field public static final int LAYOUT_CALL_MEASURE = 2; // 0x2
+    field public static final int LAYOUT_HONOR_REQUEST = 1; // 0x1
+    field public static final int LAYOUT_IGNORE_REQUEST = 0; // 0x0
+    field public static final int UNSET = -1; // 0xffffffff
+  }
+
+  public static class MotionScene.Transition {
+    ctor public MotionScene.Transition(int, androidx.constraintlayout.motion.widget.MotionScene!, int, int);
+    method public void addKeyFrame(androidx.constraintlayout.motion.widget.KeyFrames!);
+    method public void addOnClick(android.content.Context!, org.xmlpull.v1.XmlPullParser!);
+    method public void addOnClick(int, int);
+    method public String! debugString(android.content.Context!);
+    method public int getAutoTransition();
+    method public int getDuration();
+    method public int getEndConstraintSetId();
+    method public int getId();
+    method public java.util.List<androidx.constraintlayout.motion.widget.KeyFrames!>! getKeyFrameList();
+    method public int getLayoutDuringTransition();
+    method public java.util.List<androidx.constraintlayout.motion.widget.MotionScene.Transition.TransitionOnClick!>! getOnClickList();
+    method public int getPathMotionArc();
+    method public float getStagger();
+    method public int getStartConstraintSetId();
+    method public androidx.constraintlayout.motion.widget.TouchResponse! getTouchResponse();
+    method public boolean isEnabled();
+    method public boolean isTransitionFlag(int);
+    method public void removeOnClick(int);
+    method public void setAutoTransition(int);
+    method public void setDuration(int);
+    method public void setEnabled(boolean);
+    method public void setInterpolatorInfo(int, String!, int);
+    method public void setLayoutDuringTransition(int);
+    method public void setOnSwipe(androidx.constraintlayout.motion.widget.OnSwipe!);
+    method public void setOnTouchUp(int);
+    method public void setPathMotionArc(int);
+    method public void setStagger(float);
+    method public void setTransitionFlag(int);
+    field public static final int AUTO_ANIMATE_TO_END = 4; // 0x4
+    field public static final int AUTO_ANIMATE_TO_START = 3; // 0x3
+    field public static final int AUTO_JUMP_TO_END = 2; // 0x2
+    field public static final int AUTO_JUMP_TO_START = 1; // 0x1
+    field public static final int AUTO_NONE = 0; // 0x0
+    field public static final int INTERPOLATE_ANTICIPATE = 6; // 0x6
+    field public static final int INTERPOLATE_BOUNCE = 4; // 0x4
+    field public static final int INTERPOLATE_EASE_IN = 1; // 0x1
+    field public static final int INTERPOLATE_EASE_IN_OUT = 0; // 0x0
+    field public static final int INTERPOLATE_EASE_OUT = 2; // 0x2
+    field public static final int INTERPOLATE_LINEAR = 3; // 0x3
+    field public static final int INTERPOLATE_OVERSHOOT = 5; // 0x5
+    field public static final int INTERPOLATE_REFERENCE_ID = -2; // 0xfffffffe
+    field public static final int INTERPOLATE_SPLINE_STRING = -1; // 0xffffffff
+  }
+
+  public static class MotionScene.Transition.TransitionOnClick implements android.view.View.OnClickListener {
+    ctor public MotionScene.Transition.TransitionOnClick(android.content.Context!, androidx.constraintlayout.motion.widget.MotionScene.Transition!, org.xmlpull.v1.XmlPullParser!);
+    ctor public MotionScene.Transition.TransitionOnClick(androidx.constraintlayout.motion.widget.MotionScene.Transition!, int, int);
+    method public void addOnClickListeners(androidx.constraintlayout.motion.widget.MotionLayout!, int, androidx.constraintlayout.motion.widget.MotionScene.Transition!);
+    method public void onClick(android.view.View!);
+    method public void removeOnClickListeners(androidx.constraintlayout.motion.widget.MotionLayout!);
+    field public static final int ANIM_TOGGLE = 17; // 0x11
+    field public static final int ANIM_TO_END = 1; // 0x1
+    field public static final int ANIM_TO_START = 16; // 0x10
+    field public static final int JUMP_TO_END = 256; // 0x100
+    field public static final int JUMP_TO_START = 4096; // 0x1000
+  }
+
+  public class OnSwipe {
+    ctor public OnSwipe();
+    method public int getAutoCompleteMode();
+    method public int getDragDirection();
+    method public float getDragScale();
+    method public float getDragThreshold();
+    method public int getLimitBoundsTo();
+    method public float getMaxAcceleration();
+    method public float getMaxVelocity();
+    method public boolean getMoveWhenScrollAtTop();
+    method public int getNestedScrollFlags();
+    method public int getOnTouchUp();
+    method public int getRotationCenterId();
+    method public int getSpringBoundary();
+    method public float getSpringDamping();
+    method public float getSpringMass();
+    method public float getSpringStiffness();
+    method public float getSpringStopThreshold();
+    method public int getTouchAnchorId();
+    method public int getTouchAnchorSide();
+    method public int getTouchRegionId();
+    method public void setAutoCompleteMode(int);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setDragDirection(int);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setDragScale(int);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setDragThreshold(int);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setLimitBoundsTo(int);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setMaxAcceleration(int);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setMaxVelocity(int);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setMoveWhenScrollAtTop(boolean);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setNestedScrollFlags(int);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setOnTouchUp(int);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setRotateCenter(int);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setSpringBoundary(int);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setSpringDamping(float);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setSpringMass(float);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setSpringStiffness(float);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setSpringStopThreshold(float);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setTouchAnchorId(int);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setTouchAnchorSide(int);
+    method public androidx.constraintlayout.motion.widget.OnSwipe! setTouchRegionId(int);
+    field public static final int COMPLETE_MODE_CONTINUOUS_VELOCITY = 0; // 0x0
+    field public static final int COMPLETE_MODE_SPRING = 1; // 0x1
+    field public static final int DRAG_ANTICLOCKWISE = 7; // 0x7
+    field public static final int DRAG_CLOCKWISE = 6; // 0x6
+    field public static final int DRAG_DOWN = 1; // 0x1
+    field public static final int DRAG_END = 5; // 0x5
+    field public static final int DRAG_LEFT = 2; // 0x2
+    field public static final int DRAG_RIGHT = 3; // 0x3
+    field public static final int DRAG_START = 4; // 0x4
+    field public static final int DRAG_UP = 0; // 0x0
+    field public static final int FLAG_DISABLE_POST_SCROLL = 1; // 0x1
+    field public static final int FLAG_DISABLE_SCROLL = 2; // 0x2
+    field public static final int ON_UP_AUTOCOMPLETE = 0; // 0x0
+    field public static final int ON_UP_AUTOCOMPLETE_TO_END = 2; // 0x2
+    field public static final int ON_UP_AUTOCOMPLETE_TO_START = 1; // 0x1
+    field public static final int ON_UP_DECELERATE = 4; // 0x4
+    field public static final int ON_UP_DECELERATE_AND_COMPLETE = 5; // 0x5
+    field public static final int ON_UP_NEVER_TO_END = 7; // 0x7
+    field public static final int ON_UP_NEVER_TO_START = 6; // 0x6
+    field public static final int ON_UP_STOP = 3; // 0x3
+    field public static final int SIDE_BOTTOM = 3; // 0x3
+    field public static final int SIDE_END = 6; // 0x6
+    field public static final int SIDE_LEFT = 1; // 0x1
+    field public static final int SIDE_MIDDLE = 4; // 0x4
+    field public static final int SIDE_RIGHT = 2; // 0x2
+    field public static final int SIDE_START = 5; // 0x5
+    field public static final int SIDE_TOP = 0; // 0x0
+    field public static final int SPRING_BOUNDARY_BOUNCEBOTH = 3; // 0x3
+    field public static final int SPRING_BOUNDARY_BOUNCEEND = 2; // 0x2
+    field public static final int SPRING_BOUNDARY_BOUNCESTART = 1; // 0x1
+    field public static final int SPRING_BOUNDARY_OVERSHOOT = 0; // 0x0
+  }
+
+  public abstract class TransitionAdapter implements androidx.constraintlayout.motion.widget.MotionLayout.TransitionListener {
+    ctor public TransitionAdapter();
+    method public void onTransitionChange(androidx.constraintlayout.motion.widget.MotionLayout!, int, int, float);
+    method public void onTransitionCompleted(androidx.constraintlayout.motion.widget.MotionLayout!, int);
+    method public void onTransitionStarted(androidx.constraintlayout.motion.widget.MotionLayout!, int, int);
+    method public void onTransitionTrigger(androidx.constraintlayout.motion.widget.MotionLayout!, int, boolean, float);
+  }
+
+  public class TransitionBuilder {
+    ctor public TransitionBuilder();
+    method public static androidx.constraintlayout.motion.widget.MotionScene.Transition! buildTransition(androidx.constraintlayout.motion.widget.MotionScene!, int, int, androidx.constraintlayout.widget.ConstraintSet!, int, androidx.constraintlayout.widget.ConstraintSet!);
+    method public static void validate(androidx.constraintlayout.motion.widget.MotionLayout!);
+  }
+
+  public class ViewTransition {
+    method public int getSharedValue();
+    method public int getSharedValueCurrent();
+    method public int getSharedValueID();
+    method public int getStateTransition();
+    method public void setSharedValue(int);
+    method public void setSharedValueCurrent(int);
+    method public void setSharedValueID(int);
+    method public void setStateTransition(int);
+    field public static final String CONSTRAINT_OVERRIDE = "ConstraintOverride";
+    field public static final String CUSTOM_ATTRIBUTE = "CustomAttribute";
+    field public static final String CUSTOM_METHOD = "CustomMethod";
+    field public static final String KEY_FRAME_SET_TAG = "KeyFrameSet";
+    field public static final int ONSTATE_ACTION_DOWN = 1; // 0x1
+    field public static final int ONSTATE_ACTION_DOWN_UP = 3; // 0x3
+    field public static final int ONSTATE_ACTION_UP = 2; // 0x2
+    field public static final int ONSTATE_SHARED_VALUE_SET = 4; // 0x4
+    field public static final int ONSTATE_SHARED_VALUE_UNSET = 5; // 0x5
+    field public static final String VIEW_TRANSITION_TAG = "ViewTransition";
+  }
+
+  public class ViewTransitionController {
+    ctor public ViewTransitionController(androidx.constraintlayout.motion.widget.MotionLayout!);
+    method public void add(androidx.constraintlayout.motion.widget.ViewTransition!);
+  }
+
+}
+
+package androidx.constraintlayout.utils.widget {
+
+  public class ImageFilterButton extends androidx.appcompat.widget.AppCompatImageButton {
+    ctor public ImageFilterButton(android.content.Context!);
+    ctor public ImageFilterButton(android.content.Context!, android.util.AttributeSet!);
+    ctor public ImageFilterButton(android.content.Context!, android.util.AttributeSet!, int);
+    method public float getContrast();
+    method public float getCrossfade();
+    method public float getImagePanX();
+    method public float getImagePanY();
+    method public float getImageRotate();
+    method public float getImageZoom();
+    method public float getRound();
+    method public float getRoundPercent();
+    method public float getSaturation();
+    method public float getWarmth();
+    method public void setAltImageResource(int);
+    method public void setBrightness(float);
+    method public void setContrast(float);
+    method public void setCrossfade(float);
+    method public void setImagePanX(float);
+    method public void setImagePanY(float);
+    method public void setImageRotate(float);
+    method public void setImageZoom(float);
+    method @RequiresApi(android.os.Build.VERSION_CODES.LOLLIPOP) public void setRound(float);
+    method @RequiresApi(android.os.Build.VERSION_CODES.LOLLIPOP) public void setRoundPercent(float);
+    method public void setSaturation(float);
+    method public void setWarmth(float);
+  }
+
+  public class ImageFilterView extends androidx.appcompat.widget.AppCompatImageView {
+    ctor public ImageFilterView(android.content.Context!);
+    ctor public ImageFilterView(android.content.Context!, android.util.AttributeSet!);
+    ctor public ImageFilterView(android.content.Context!, android.util.AttributeSet!, int);
+    method public float getBrightness();
+    method public float getContrast();
+    method public float getCrossfade();
+    method public float getImagePanX();
+    method public float getImagePanY();
+    method public float getImageRotate();
+    method public float getImageZoom();
+    method public float getRound();
+    method public float getRoundPercent();
+    method public float getSaturation();
+    method public float getWarmth();
+    method public void setAltImageDrawable(android.graphics.drawable.Drawable!);
+    method public void setAltImageResource(int);
+    method public void setBrightness(float);
+    method public void setContrast(float);
+    method public void setCrossfade(float);
+    method public void setImagePanX(float);
+    method public void setImagePanY(float);
+    method public void setImageRotate(float);
+    method public void setImageZoom(float);
+    method @RequiresApi(android.os.Build.VERSION_CODES.LOLLIPOP) public void setRound(float);
+    method @RequiresApi(android.os.Build.VERSION_CODES.LOLLIPOP) public void setRoundPercent(float);
+    method public void setSaturation(float);
+    method public void setWarmth(float);
+  }
+
+  public class MockView extends android.view.View {
+    ctor public MockView(android.content.Context!);
+    ctor public MockView(android.content.Context!, android.util.AttributeSet!);
+    ctor public MockView(android.content.Context!, android.util.AttributeSet!, int);
+    method public void onDraw(android.graphics.Canvas);
+    field protected String! mText;
+  }
+
+  public class MotionButton extends androidx.appcompat.widget.AppCompatButton {
+    ctor public MotionButton(android.content.Context!);
+    ctor public MotionButton(android.content.Context!, android.util.AttributeSet!);
+    ctor public MotionButton(android.content.Context!, android.util.AttributeSet!, int);
+    method public float getRound();
+    method public float getRoundPercent();
+    method @RequiresApi(android.os.Build.VERSION_CODES.LOLLIPOP) public void setRound(float);
+    method @RequiresApi(android.os.Build.VERSION_CODES.LOLLIPOP) public void setRoundPercent(float);
+  }
+
+  public class MotionLabel extends android.view.View implements androidx.constraintlayout.motion.widget.FloatLayout {
+    ctor public MotionLabel(android.content.Context!);
+    ctor public MotionLabel(android.content.Context!, android.util.AttributeSet?);
+    ctor public MotionLabel(android.content.Context!, android.util.AttributeSet?, int);
+    method public float getRound();
+    method public float getRoundPercent();
+    method public float getScaleFromTextSize();
+    method public float getTextBackgroundPanX();
+    method public float getTextBackgroundPanY();
+    method public float getTextBackgroundRotate();
+    method public float getTextBackgroundZoom();
+    method public int getTextOutlineColor();
+    method public float getTextPanX();
+    method public float getTextPanY();
+    method public float getTextureHeight();
+    method public float getTextureWidth();
+    method public android.graphics.Typeface! getTypeface();
+    method public void layout(float, float, float, float);
+    method public void setGravity(int);
+    method @RequiresApi(android.os.Build.VERSION_CODES.LOLLIPOP) public void setRound(float);
+    method @RequiresApi(android.os.Build.VERSION_CODES.LOLLIPOP) public void setRoundPercent(float);
+    method public void setScaleFromTextSize(float);
+    method public void setText(CharSequence!);
+    method public void setTextBackgroundPanX(float);
+    method public void setTextBackgroundPanY(float);
+    method public void setTextBackgroundRotate(float);
+    method public void setTextBackgroundZoom(float);
+    method public void setTextFillColor(int);
+    method public void setTextOutlineColor(int);
+    method public void setTextOutlineThickness(float);
+    method public void setTextPanX(float);
+    method public void setTextPanY(float);
+    method public void setTextSize(float);
+    method public void setTextureHeight(float);
+    method public void setTextureWidth(float);
+    method public void setTypeface(android.graphics.Typeface!);
+  }
+
+  public class MotionTelltales extends androidx.constraintlayout.utils.widget.MockView {
+    ctor public MotionTelltales(android.content.Context!);
+    ctor public MotionTelltales(android.content.Context!, android.util.AttributeSet!);
+    ctor public MotionTelltales(android.content.Context!, android.util.AttributeSet!, int);
+    method public void setText(CharSequence!);
+  }
+
+}
+
+package androidx.constraintlayout.widget {
+
+  public class Barrier extends androidx.constraintlayout.widget.ConstraintHelper {
+    ctor public Barrier(android.content.Context!);
+    ctor public Barrier(android.content.Context!, android.util.AttributeSet!);
+    ctor public Barrier(android.content.Context!, android.util.AttributeSet!, int);
+    method @Deprecated public boolean allowsGoneWidget();
+    method public boolean getAllowsGoneWidget();
+    method public int getMargin();
+    method public int getType();
+    method public void setAllowsGoneWidget(boolean);
+    method public void setDpMargin(int);
+    method public void setMargin(int);
+    method public void setType(int);
+    field public static final int BOTTOM = 3; // 0x3
+    field public static final int END = 6; // 0x6
+    field public static final int LEFT = 0; // 0x0
+    field public static final int RIGHT = 1; // 0x1
+    field public static final int START = 5; // 0x5
+    field public static final int TOP = 2; // 0x2
+  }
+
+  public class ConstraintAttribute {
+    ctor public ConstraintAttribute(androidx.constraintlayout.widget.ConstraintAttribute!, Object!);
+    ctor public ConstraintAttribute(String!, androidx.constraintlayout.widget.ConstraintAttribute.AttributeType!);
+    ctor public ConstraintAttribute(String!, androidx.constraintlayout.widget.ConstraintAttribute.AttributeType!, Object!, boolean);
+    method public void applyCustom(android.view.View!);
+    method public boolean diff(androidx.constraintlayout.widget.ConstraintAttribute!);
+    method public static java.util.HashMap<java.lang.String!,androidx.constraintlayout.widget.ConstraintAttribute!>! extractAttributes(java.util.HashMap<java.lang.String!,androidx.constraintlayout.widget.ConstraintAttribute!>!, android.view.View!);
+    method public int getColorValue();
+    method public float getFloatValue();
+    method public int getIntegerValue();
+    method public String! getName();
+    method public String! getStringValue();
+    method public androidx.constraintlayout.widget.ConstraintAttribute.AttributeType! getType();
+    method public float getValueToInterpolate();
+    method public void getValuesToInterpolate(float[]!);
+    method public boolean isBooleanValue();
+    method public boolean isContinuous();
+    method public boolean isMethod();
+    method public int numberOfInterpolatedValues();
+    method public static void parse(android.content.Context!, org.xmlpull.v1.XmlPullParser!, java.util.HashMap<java.lang.String!,androidx.constraintlayout.widget.ConstraintAttribute!>!);
+    method public static void setAttributes(android.view.View!, java.util.HashMap<java.lang.String!,androidx.constraintlayout.widget.ConstraintAttribute!>!);
+    method public void setColorValue(int);
+    method public void setFloatValue(float);
+    method public void setIntValue(int);
+    method public void setStringValue(String!);
+    method public void setValue(float[]!);
+    method public void setValue(Object!);
+  }
+
+  public enum ConstraintAttribute.AttributeType {
+    enum_constant public static final androidx.constraintlayout.widget.ConstraintAttribute.AttributeType BOOLEAN_TYPE;
+    enum_constant public static final androidx.constraintlayout.widget.ConstraintAttribute.AttributeType COLOR_DRAWABLE_TYPE;
+    enum_constant public static final androidx.constraintlayout.widget.ConstraintAttribute.AttributeType COLOR_TYPE;
+    enum_constant public static final androidx.constraintlayout.widget.ConstraintAttribute.AttributeType DIMENSION_TYPE;
+    enum_constant public static final androidx.constraintlayout.widget.ConstraintAttribute.AttributeType FLOAT_TYPE;
+    enum_constant public static final androidx.constraintlayout.widget.ConstraintAttribute.AttributeType INT_TYPE;
+    enum_constant public static final androidx.constraintlayout.widget.ConstraintAttribute.AttributeType REFERENCE_TYPE;
+    enum_constant public static final androidx.constraintlayout.widget.ConstraintAttribute.AttributeType STRING_TYPE;
+  }
+
+  public abstract class ConstraintHelper extends android.view.View {
+    ctor public ConstraintHelper(android.content.Context!);
+    ctor public ConstraintHelper(android.content.Context!, android.util.AttributeSet!);
+    ctor public ConstraintHelper(android.content.Context!, android.util.AttributeSet!, int);
+    method public void addView(android.view.View!);
+    method public void applyHelperParams();
+    method protected void applyLayoutFeatures();
+    method protected void applyLayoutFeatures(androidx.constraintlayout.widget.ConstraintLayout!);
+    method protected void applyLayoutFeaturesInConstraintSet(androidx.constraintlayout.widget.ConstraintLayout!);
+    method public boolean containsId(int);
+    method public int[]! getReferencedIds();
+    method protected android.view.View![]! getViews(androidx.constraintlayout.widget.ConstraintLayout!);
+    method public int indexFromId(int);
+    method protected void init(android.util.AttributeSet!);
+    method public static boolean isChildOfHelper(android.view.View!);
+    method public void loadParameters(androidx.constraintlayout.widget.ConstraintSet.Constraint!, androidx.constraintlayout.core.widgets.HelperWidget!, androidx.constraintlayout.widget.ConstraintLayout.LayoutParams!, android.util.SparseArray<androidx.constraintlayout.core.widgets.ConstraintWidget!>!);
+    method public void onDraw(android.graphics.Canvas);
+    method public int removeView(android.view.View!);
+    method public void resolveRtl(androidx.constraintlayout.core.widgets.ConstraintWidget!, boolean);
+    method protected void setIds(String!);
+    method protected void setReferenceTags(String!);
+    method public void setReferencedIds(int[]!);
+    method public void updatePostConstraints(androidx.constraintlayout.widget.ConstraintLayout!);
+    method public void updatePostLayout(androidx.constraintlayout.widget.ConstraintLayout!);
+    method public void updatePostMeasure(androidx.constraintlayout.widget.ConstraintLayout!);
+    method public void updatePreDraw(androidx.constraintlayout.widget.ConstraintLayout!);
+    method public void updatePreLayout(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!, androidx.constraintlayout.core.widgets.Helper!, android.util.SparseArray<androidx.constraintlayout.core.widgets.ConstraintWidget!>!);
+    method public void updatePreLayout(androidx.constraintlayout.widget.ConstraintLayout!);
+    method public void validateParams();
+    field protected static final String CHILD_TAG = "CONSTRAINT_LAYOUT_HELPER_CHILD";
+    field protected int mCount;
+    field protected androidx.constraintlayout.core.widgets.Helper! mHelperWidget;
+    field protected int[]! mIds;
+    field protected java.util.HashMap<java.lang.Integer!,java.lang.String!>! mMap;
+    field protected String! mReferenceIds;
+    field protected String! mReferenceTags;
+    field protected boolean mUseViewMeasure;
+    field protected android.content.Context! myContext;
+  }
+
+  public class ConstraintLayout extends android.view.ViewGroup {
+    ctor public ConstraintLayout(android.content.Context);
+    ctor public ConstraintLayout(android.content.Context, android.util.AttributeSet?);
+    ctor public ConstraintLayout(android.content.Context, android.util.AttributeSet?, int);
+    ctor public ConstraintLayout(android.content.Context, android.util.AttributeSet?, int, int);
+    method public void addValueModifier(androidx.constraintlayout.widget.ConstraintLayout.ValueModifier!);
+    method protected void applyConstraintsFromLayoutParams(boolean, android.view.View!, androidx.constraintlayout.core.widgets.ConstraintWidget!, androidx.constraintlayout.widget.ConstraintLayout.LayoutParams!, android.util.SparseArray<androidx.constraintlayout.core.widgets.ConstraintWidget!>!);
+    method protected boolean dynamicUpdateConstraints(int, int);
+    method public void fillMetrics(androidx.constraintlayout.core.Metrics!);
+    method protected androidx.constraintlayout.widget.ConstraintLayout.LayoutParams! generateDefaultLayoutParams();
+    method public androidx.constraintlayout.widget.ConstraintLayout.LayoutParams! generateLayoutParams(android.util.AttributeSet!);
+    method public Object! getDesignInformation(int, Object!);
+    method public int getMaxHeight();
+    method public int getMaxWidth();
+    method public int getMinHeight();
+    method public int getMinWidth();
+    method public int getOptimizationLevel();
+    method public String! getSceneString();
+    method public static androidx.constraintlayout.widget.SharedValues! getSharedValues();
+    method public android.view.View! getViewById(int);
+    method public final androidx.constraintlayout.core.widgets.ConstraintWidget! getViewWidget(android.view.View!);
+    method protected boolean isRtl();
+    method public void loadLayoutDescription(int);
+    method protected void parseLayoutDescription(int);
+    method protected void resolveMeasuredDimension(int, int, int, int, boolean, boolean);
+    method protected void resolveSystem(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!, int, int, int);
+    method public void setConstraintSet(androidx.constraintlayout.widget.ConstraintSet!);
+    method public void setDesignInformation(int, Object!, Object!);
+    method public void setMaxHeight(int);
+    method public void setMaxWidth(int);
+    method public void setMinHeight(int);
+    method public void setMinWidth(int);
+    method public void setOnConstraintsChanged(androidx.constraintlayout.widget.ConstraintsChangedListener!);
+    method public void setOptimizationLevel(int);
+    method protected void setSelfDimensionBehaviour(androidx.constraintlayout.core.widgets.ConstraintWidgetContainer!, int, int, int, int);
+    method public void setState(int, int, int);
+    field public static final int DESIGN_INFO_ID = 0; // 0x0
+    field public static final String VERSION = "ConstraintLayout-2.2.0-alpha04";
+    field protected androidx.constraintlayout.widget.ConstraintLayoutStates! mConstraintLayoutSpec;
+    field protected boolean mDirtyHierarchy;
+    field protected androidx.constraintlayout.core.widgets.ConstraintWidgetContainer! mLayoutWidget;
+  }
+
+  public static class ConstraintLayout.LayoutParams extends android.view.ViewGroup.MarginLayoutParams {
+    ctor public ConstraintLayout.LayoutParams(android.content.Context!, android.util.AttributeSet!);
+    ctor public ConstraintLayout.LayoutParams(android.view.ViewGroup.LayoutParams!);
+    ctor public ConstraintLayout.LayoutParams(int, int);
+    method public String! getConstraintTag();
+    method public androidx.constraintlayout.core.widgets.ConstraintWidget! getConstraintWidget();
+    method public void reset();
+    method public void setWidgetDebugName(String!);
+    method public void validate();
+    field public static final int BASELINE = 5; // 0x5
+    field public static final int BOTTOM = 4; // 0x4
+    field public static final int CHAIN_PACKED = 2; // 0x2
+    field public static final int CHAIN_SPREAD = 0; // 0x0
+    field public static final int CHAIN_SPREAD_INSIDE = 1; // 0x1
+    field public static final int CIRCLE = 8; // 0x8
+    field public static final int END = 7; // 0x7
+    field public static final int GONE_UNSET = -2147483648; // 0x80000000
+    field public static final int HORIZONTAL = 0; // 0x0
+    field public static final int LEFT = 1; // 0x1
+    field public static final int MATCH_CONSTRAINT = 0; // 0x0
+    field public static final int MATCH_CONSTRAINT_PERCENT = 2; // 0x2
+    field public static final int MATCH_CONSTRAINT_SPREAD = 0; // 0x0
+    field public static final int MATCH_CONSTRAINT_WRAP = 1; // 0x1
+    field public static final int PARENT_ID = 0; // 0x0
+    field public static final int RIGHT = 2; // 0x2
+    field public static final int START = 6; // 0x6
+    field public static final int TOP = 3; // 0x3
+    field public static final int UNSET = -1; // 0xffffffff
+    field public static final int VERTICAL = 1; // 0x1
+    field public static final int WRAP_BEHAVIOR_HORIZONTAL_ONLY = 1; // 0x1
+    field public static final int WRAP_BEHAVIOR_INCLUDED = 0; // 0x0
+    field public static final int WRAP_BEHAVIOR_SKIPPED = 3; // 0x3
+    field public static final int WRAP_BEHAVIOR_VERTICAL_ONLY = 2; // 0x2
+    field public int baselineMargin;
+    field public int baselineToBaseline;
+    field public int baselineToBottom;
+    field public int baselineToTop;
+    field public int bottomToBottom;
+    field public int bottomToTop;
+    field public float circleAngle;
+    field public int circleConstraint;
+    field public int circleRadius;
+    field public boolean constrainedHeight;
+    field public boolean constrainedWidth;
+    field public String! constraintTag;
+    field public String! dimensionRatio;
+    field public int editorAbsoluteX;
+    field public int editorAbsoluteY;
+    field public int endToEnd;
+    field public int endToStart;
+    field public int goneBaselineMargin;
+    field public int goneBottomMargin;
+    field public int goneEndMargin;
+    field public int goneLeftMargin;
+    field public int goneRightMargin;
+    field public int goneStartMargin;
+    field public int goneTopMargin;
+    field public int guideBegin;
+    field public int guideEnd;
+    field public float guidePercent;
+    field public boolean guidelineUseRtl;
+    field public boolean helped;
+    field public float horizontalBias;
+    field public int horizontalChainStyle;
+    field public float horizontalWeight;
+    field public int leftToLeft;
+    field public int leftToRight;
+    field public int matchConstraintDefaultHeight;
+    field public int matchConstraintDefaultWidth;
+    field public int matchConstraintMaxHeight;
+    field public int matchConstraintMaxWidth;
+    field public int matchConstraintMinHeight;
+    field public int matchConstraintMinWidth;
+    field public float matchConstraintPercentHeight;
+    field public float matchConstraintPercentWidth;
+    field public int orientation;
+    field public int rightToLeft;
+    field public int rightToRight;
+    field public int startToEnd;
+    field public int startToStart;
+    field public int topToBottom;
+    field public int topToTop;
+    field public float verticalBias;
+    field public int verticalChainStyle;
+    field public float verticalWeight;
+    field public int wrapBehaviorInParent;
+  }
+
+  public static interface ConstraintLayout.ValueModifier {
+    method public boolean update(int, int, int, android.view.View!, androidx.constraintlayout.widget.ConstraintLayout.LayoutParams!);
+  }
+
+  public class ConstraintLayoutStates {
+    method public boolean needsToChange(int, float, float);
+    method public void setOnConstraintsChanged(androidx.constraintlayout.widget.ConstraintsChangedListener!);
+    method public void updateConstraints(int, float, float);
+    field public static final String TAG = "ConstraintLayoutStates";
+  }
+
+  public class ConstraintLayoutStatistics {
+    ctor public ConstraintLayoutStatistics(androidx.constraintlayout.widget.ConstraintLayout!);
+    ctor public ConstraintLayoutStatistics(androidx.constraintlayout.widget.ConstraintLayoutStatistics!);
+    method public void attach(androidx.constraintlayout.widget.ConstraintLayout!);
+    method public androidx.constraintlayout.widget.ConstraintLayoutStatistics! clone();
+    method public void detach();
+    method public long getValue(int);
+    method public void logSummary(String!);
+    method public void logSummary(String!, androidx.constraintlayout.widget.ConstraintLayoutStatistics!);
+    method public void reset();
+    field public static final int DURATION_OF_CHILD_MEASURES = 5; // 0x5
+    field public static final int DURATION_OF_LAYOUT = 7; // 0x7
+    field public static final int DURATION_OF_MEASURES = 6; // 0x6
+    field public static final int NUMBER_OF_CHILD_MEASURES = 4; // 0x4
+    field public static final int NUMBER_OF_CHILD_VIEWS = 3; // 0x3
+    field public static final int NUMBER_OF_EQUATIONS = 9; // 0x9
+    field public static final int NUMBER_OF_LAYOUTS = 1; // 0x1
+    field public static final int NUMBER_OF_ON_MEASURES = 2; // 0x2
+    field public static final int NUMBER_OF_SIMPLE_EQUATIONS = 10; // 0xa
+    field public static final int NUMBER_OF_VARIABLES = 8; // 0x8
+  }
+
+  public class ConstraintProperties {
+    ctor public ConstraintProperties(android.view.View!);
+    method public androidx.constraintlayout.widget.ConstraintProperties! addToHorizontalChain(int, int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! addToHorizontalChainRTL(int, int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! addToVerticalChain(int, int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! alpha(float);
+    method public void apply();
+    method public androidx.constraintlayout.widget.ConstraintProperties! center(int, int, int, int, int, int, float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! centerHorizontally(int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! centerHorizontally(int, int, int, int, int, int, float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! centerHorizontallyRtl(int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! centerHorizontallyRtl(int, int, int, int, int, int, float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! centerVertically(int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! centerVertically(int, int, int, int, int, int, float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! connect(int, int, int, int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! constrainDefaultHeight(int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! constrainDefaultWidth(int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! constrainHeight(int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! constrainMaxHeight(int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! constrainMaxWidth(int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! constrainMinHeight(int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! constrainMinWidth(int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! constrainWidth(int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! dimensionRatio(String!);
+    method public androidx.constraintlayout.widget.ConstraintProperties! elevation(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! goneMargin(int, int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! horizontalBias(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! horizontalChainStyle(int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! horizontalWeight(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! margin(int, int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! removeConstraints(int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! removeFromHorizontalChain();
+    method public androidx.constraintlayout.widget.ConstraintProperties! removeFromVerticalChain();
+    method public androidx.constraintlayout.widget.ConstraintProperties! rotation(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! rotationX(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! rotationY(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! scaleX(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! scaleY(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! transformPivot(float, float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! transformPivotX(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! transformPivotY(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! translation(float, float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! translationX(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! translationY(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! translationZ(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! verticalBias(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! verticalChainStyle(int);
+    method public androidx.constraintlayout.widget.ConstraintProperties! verticalWeight(float);
+    method public androidx.constraintlayout.widget.ConstraintProperties! visibility(int);
+    field public static final int BASELINE = 5; // 0x5
+    field public static final int BOTTOM = 4; // 0x4
+    field public static final int END = 7; // 0x7
+    field public static final int LEFT = 1; // 0x1
+    field public static final int MATCH_CONSTRAINT = 0; // 0x0
+    field public static final int MATCH_CONSTRAINT_SPREAD = 0; // 0x0
+    field public static final int MATCH_CONSTRAINT_WRAP = 1; // 0x1
+    field public static final int PARENT_ID = 0; // 0x0
+    field public static final int RIGHT = 2; // 0x2
+    field public static final int START = 6; // 0x6
+    field public static final int TOP = 3; // 0x3
+    field public static final int UNSET = -1; // 0xffffffff
+    field public static final int WRAP_CONTENT = -2; // 0xfffffffe
+  }
+
+  public class ConstraintSet {
+    ctor public ConstraintSet();
+    method public void addColorAttributes(java.lang.String!...!);
+    method public void addFloatAttributes(java.lang.String!...!);
+    method public void addIntAttributes(java.lang.String!...!);
+    method public void addStringAttributes(java.lang.String!...!);
+    method public void addToHorizontalChain(int, int, int);
+    method public void addToHorizontalChainRTL(int, int, int);
+    method public void addToVerticalChain(int, int, int);
+    method public void applyCustomAttributes(androidx.constraintlayout.widget.ConstraintLayout!);
+    method public void applyDeltaFrom(androidx.constraintlayout.widget.ConstraintSet!);
+    method public void applyTo(androidx.constraintlayout.widget.ConstraintLayout!);
+    method public void applyToHelper(androidx.constraintlayout.widget.ConstraintHelper!, androidx.constraintlayout.core.widgets.ConstraintWidget!, androidx.constraintlayout.widget.ConstraintLayout.LayoutParams!, android.util.SparseArray<androidx.constraintlayout.core.widgets.ConstraintWidget!>!);
+    method public void applyToLayoutParams(int, androidx.constraintlayout.widget.ConstraintLayout.LayoutParams!);
+    method public void applyToWithoutCustom(androidx.constraintlayout.widget.ConstraintLayout!);
+    method public static androidx.constraintlayout.widget.ConstraintSet.Constraint! buildDelta(android.content.Context!, org.xmlpull.v1.XmlPullParser!);
+    method public void center(int, int, int, int, int, int, int, float);
+    method public void centerHorizontally(int, int);
+    method public void centerHorizontally(int, int, int, int, int, int, int, float);
+    method public void centerHorizontallyRtl(int, int);
+    method public void centerHorizontallyRtl(int, int, int, int, int, int, int, float);
+    method public void centerVertically(int, int);
+    method public void centerVertically(int, int, int, int, int, int, int, float);
+    method public void clear(int);
+    method public void clear(int, int);
+    method public void clone(android.content.Context!, int);
+    method public void clone(androidx.constraintlayout.widget.ConstraintLayout!);
+    method public void clone(androidx.constraintlayout.widget.Constraints!);
+    method public void clone(androidx.constraintlayout.widget.ConstraintSet!);
+    method public void connect(int, int, int, int);
+    method public void connect(int, int, int, int, int);
+    method public void constrainCircle(int, int, int, float);
+    method public void constrainDefaultHeight(int, int);
+    method public void constrainDefaultWidth(int, int);
+    method public void constrainHeight(int, int);
+    method public void constrainMaxHeight(int, int);
+    method public void constrainMaxWidth(int, int);
+    method public void constrainMinHeight(int, int);
+    method public void constrainMinWidth(int, int);
+    method public void constrainPercentHeight(int, float);
+    method public void constrainPercentWidth(int, float);
+    method public void constrainWidth(int, int);
+    method public void constrainedHeight(int, boolean);
+    method public void constrainedWidth(int, boolean);
+    method public void create(int, int);
+    method public void createBarrier(int, int, int, int...!);
+    method public void createHorizontalChain(int, int, int, int, int[]!, float[]!, int);
+    method public void createHorizontalChainRtl(int, int, int, int, int[]!, float[]!, int);
+    method public void createVerticalChain(int, int, int, int, int[]!, float[]!, int);
+    method public void dump(androidx.constraintlayout.motion.widget.MotionScene!, int...!);
+    method public boolean getApplyElevation(int);
+    method public androidx.constraintlayout.widget.ConstraintSet.Constraint! getConstraint(int);
+    method public java.util.HashMap<java.lang.String!,androidx.constraintlayout.widget.ConstraintAttribute!>! getCustomAttributeSet();
+    method public int getHeight(int);
+    method public int[]! getKnownIds();
+    method public androidx.constraintlayout.widget.ConstraintSet.Constraint! getParameters(int);
+    method public int[]! getReferencedIds(int);
+    method public String![]! getStateLabels();
+    method public int getVisibility(int);
+    method public int getVisibilityMode(int);
+    method public int getWidth(int);
+    method public boolean isForceId();
+    method public boolean isValidateOnParse();
+    method public void load(android.content.Context!, int);
+    method public void load(android.content.Context!, org.xmlpull.v1.XmlPullParser!);
+    method public boolean matchesLabels(java.lang.String!...!);
+    method public void parseColorAttributes(androidx.constraintlayout.widget.ConstraintSet.Constraint!, String!);
+    method public void parseFloatAttributes(androidx.constraintlayout.widget.ConstraintSet.Constraint!, String!);
+    method public void parseIntAttributes(androidx.constraintlayout.widget.ConstraintSet.Constraint!, String!);
+    method public void parseStringAttributes(androidx.constraintlayout.widget.ConstraintSet.Constraint!, String!);
+    method public void readFallback(androidx.constraintlayout.widget.ConstraintLayout!);
+    method public void readFallback(androidx.constraintlayout.widget.ConstraintSet!);
+    method public void removeAttribute(String!);
+    method public void removeFromHorizontalChain(int);
+    method public void removeFromVerticalChain(int);
+    method public void setAlpha(int, float);
+    method public void setApplyElevation(int, boolean);
+    method public void setBarrierType(int, int);
+    method public void setColorValue(int, String!, int);
+    method public void setDimensionRatio(int, String!);
+    method public void setEditorAbsoluteX(int, int);
+    method public void setEditorAbsoluteY(int, int);
+    method public void setElevation(int, float);
+    method public void setFloatValue(int, String!, float);
+    method public void setForceId(boolean);
+    method public void setGoneMargin(int, int, int);
+    method public void setGuidelineBegin(int, int);
+    method public void setGuidelineEnd(int, int);
+    method public void setGuidelinePercent(int, float);
+    method public void setHorizontalBias(int, float);
+    method public void setHorizontalChainStyle(int, int);
+    method public void setHorizontalWeight(int, float);
+    method public void setIntValue(int, String!, int);
+    method public void setLayoutWrapBehavior(int, int);
+    method public void setMargin(int, int, int);
+    method public void setReferencedIds(int, int...!);
+    method public void setRotation(int, float);
+    method public void setRotationX(int, float);
+    method public void setRotationY(int, float);
+    method public void setScaleX(int, float);
+    method public void setScaleY(int, float);
+    method public void setStateLabels(String!);
+    method public void setStateLabelsList(java.lang.String!...!);
+    method public void setStringValue(int, String!, String!);
+    method public void setTransformPivot(int, float, float);
+    method public void setTransformPivotX(int, float);
+    method public void setTransformPivotY(int, float);
+    method public void setTranslation(int, float, float);
+    method public void setTranslationX(int, float);
+    method public void setTranslationY(int, float);
+    method public void setTranslationZ(int, float);
+    method public void setValidateOnParse(boolean);
+    method public void setVerticalBias(int, float);
+    method public void setVerticalChainStyle(int, int);
+    method public void setVerticalWeight(int, float);
+    method public void setVisibility(int, int);
+    method public void setVisibilityMode(int, int);
+    method public void writeState(java.io.Writer!, androidx.constraintlayout.widget.ConstraintLayout!, int) throws java.io.IOException;
+    field public static final int BASELINE = 5; // 0x5
+    field public static final int BOTTOM = 4; // 0x4
+    field public static final int CHAIN_PACKED = 2; // 0x2
+    field public static final int CHAIN_SPREAD = 0; // 0x0
+    field public static final int CHAIN_SPREAD_INSIDE = 1; // 0x1
+    field public static final int CIRCLE_REFERENCE = 8; // 0x8
+    field public static final int END = 7; // 0x7
+    field public static final int GONE = 8; // 0x8
+    field public static final int HORIZONTAL = 0; // 0x0
+    field public static final int HORIZONTAL_GUIDELINE = 0; // 0x0
+    field public static final int INVISIBLE = 4; // 0x4
+    field public static final int LEFT = 1; // 0x1
+    field public static final int MATCH_CONSTRAINT = 0; // 0x0
+    field public static final int MATCH_CONSTRAINT_PERCENT = 2; // 0x2
+    field public static final int MATCH_CONSTRAINT_SPREAD = 0; // 0x0
+    field public static final int MATCH_CONSTRAINT_WRAP = 1; // 0x1
+    field public static final int PARENT_ID = 0; // 0x0
+    field public static final int RIGHT = 2; // 0x2
+    field public static final int ROTATE_LEFT_OF_PORTRATE = 4; // 0x4
+    field public static final int ROTATE_NONE = 0; // 0x0
+    field public static final int ROTATE_PORTRATE_OF_LEFT = 2; // 0x2
+    field public static final int ROTATE_PORTRATE_OF_RIGHT = 1; // 0x1
+    field public static final int ROTATE_RIGHT_OF_PORTRATE = 3; // 0x3
+    field public static final int START = 6; // 0x6
+    field public static final int TOP = 3; // 0x3
+    field public static final int UNSET = -1; // 0xffffffff
+    field public static final int VERTICAL = 1; // 0x1
+    field public static final int VERTICAL_GUIDELINE = 1; // 0x1
+    field public static final int VISIBILITY_MODE_IGNORE = 1; // 0x1
+    field public static final int VISIBILITY_MODE_NORMAL = 0; // 0x0
+    field public static final int VISIBLE = 0; // 0x0
+    field public static final int WRAP_CONTENT = -2; // 0xfffffffe
+    field public String! derivedState;
+    field public String! mIdString;
+    field public int mRotate;
+  }
+
+  public static class ConstraintSet.Constraint {
+    ctor public ConstraintSet.Constraint();
+    method public void applyDelta(androidx.constraintlayout.widget.ConstraintSet.Constraint!);
+    method public void applyTo(androidx.constraintlayout.widget.ConstraintLayout.LayoutParams!);
+    method public androidx.constraintlayout.widget.ConstraintSet.Constraint! clone();
+    method public void printDelta(String!);
+    field public final androidx.constraintlayout.widget.ConstraintSet.Layout! layout;
+    field public java.util.HashMap<java.lang.String!,androidx.constraintlayout.widget.ConstraintAttribute!>! mCustomConstraints;
+    field public final androidx.constraintlayout.widget.ConstraintSet.Motion! motion;
+    field public final androidx.constraintlayout.widget.ConstraintSet.PropertySet! propertySet;
+    field public final androidx.constraintlayout.widget.ConstraintSet.Transform! transform;
+  }
+
+  public static class ConstraintSet.Layout {
+    ctor public ConstraintSet.Layout();
+    method public void copyFrom(androidx.constraintlayout.widget.ConstraintSet.Layout!);
+    method public void dump(androidx.constraintlayout.motion.widget.MotionScene!, StringBuilder!);
+    field public static final int UNSET = -1; // 0xffffffff
+    field public static final int UNSET_GONE_MARGIN = -2147483648; // 0x80000000
+    field public int baselineMargin;
+    field public int baselineToBaseline;
+    field public int baselineToBottom;
+    field public int baselineToTop;
+    field public int bottomMargin;
+    field public int bottomToBottom;
+    field public int bottomToTop;
+    field public float circleAngle;
+    field public int circleConstraint;
+    field public int circleRadius;
+    field public boolean constrainedHeight;
+    field public boolean constrainedWidth;
+    field public String! dimensionRatio;
+    field public int editorAbsoluteX;
+    field public int editorAbsoluteY;
+    field public int endMargin;
+    field public int endToEnd;
+    field public int endToStart;
+    field public int goneBaselineMargin;
+    field public int goneBottomMargin;
+    field public int goneEndMargin;
+    field public int goneLeftMargin;
+    field public int goneRightMargin;
+    field public int goneStartMargin;
+    field public int goneTopMargin;
+    field public int guideBegin;
+    field public int guideEnd;
+    field public float guidePercent;
+    field public boolean guidelineUseRtl;
+    field public int heightDefault;
+    field public int heightMax;
+    field public int heightMin;
+    field public float heightPercent;
+    field public float horizontalBias;
+    field public int horizontalChainStyle;
+    field public float horizontalWeight;
+    field public int leftMargin;
+    field public int leftToLeft;
+    field public int leftToRight;
+    field public boolean mApply;
+    field public boolean mBarrierAllowsGoneWidgets;
+    field public int mBarrierDirection;
+    field public int mBarrierMargin;
+    field public String! mConstraintTag;
+    field public int mHeight;
+    field public int mHelperType;
+    field public boolean mIsGuideline;
+    field public boolean mOverride;
+    field public String! mReferenceIdString;
+    field public int[]! mReferenceIds;
+    field public int mWidth;
+    field public int mWrapBehavior;
+    field public int orientation;
+    field public int rightMargin;
+    field public int rightToLeft;
+    field public int rightToRight;
+    field public int startMargin;
+    field public int startToEnd;
+    field public int startToStart;
+    field public int topMargin;
+    field public int topToBottom;
+    field public int topToTop;
+    field public float verticalBias;
+    field public int verticalChainStyle;
+    field public float verticalWeight;
+    field public int widthDefault;
+    field public int widthMax;
+    field public int widthMin;
+    field public float widthPercent;
+  }
+
+  public static class ConstraintSet.Motion {
+    ctor public ConstraintSet.Motion();
+    method public void copyFrom(androidx.constraintlayout.widget.ConstraintSet.Motion!);
+    field public int mAnimateCircleAngleTo;
+    field public int mAnimateRelativeTo;
+    field public boolean mApply;
+    field public int mDrawPath;
+    field public float mMotionStagger;
+    field public int mPathMotionArc;
+    field public float mPathRotate;
+    field public int mPolarRelativeTo;
+    field public int mQuantizeInterpolatorID;
+    field public String! mQuantizeInterpolatorString;
+    field public int mQuantizeInterpolatorType;
+    field public float mQuantizeMotionPhase;
+    field public int mQuantizeMotionSteps;
+    field public String! mTransitionEasing;
+  }
+
+  public static class ConstraintSet.PropertySet {
+    ctor public ConstraintSet.PropertySet();
+    method public void copyFrom(androidx.constraintlayout.widget.ConstraintSet.PropertySet!);
+    field public float alpha;
+    field public boolean mApply;
+    field public float mProgress;
+    field public int mVisibilityMode;
+    field public int visibility;
+  }
+
+  public static class ConstraintSet.Transform {
+    ctor public ConstraintSet.Transform();
+    method public void copyFrom(androidx.constraintlayout.widget.ConstraintSet.Transform!);
+    field public boolean applyElevation;
+    field public float elevation;
+    field public boolean mApply;
+    field public float rotation;
+    field public float rotationX;
+    field public float rotationY;
+    field public float scaleX;
+    field public float scaleY;
+    field public int transformPivotTarget;
+    field public float transformPivotX;
+    field public float transformPivotY;
+    field public float translationX;
+    field public float translationY;
+    field public float translationZ;
+  }
+
+  public class Constraints extends android.view.ViewGroup {
+    ctor public Constraints(android.content.Context!);
+    ctor public Constraints(android.content.Context!, android.util.AttributeSet!);
+    ctor public Constraints(android.content.Context!, android.util.AttributeSet!, int);
+    method protected androidx.constraintlayout.widget.Constraints.LayoutParams! generateDefaultLayoutParams();
+    method public androidx.constraintlayout.widget.Constraints.LayoutParams! generateLayoutParams(android.util.AttributeSet!);
+    method public androidx.constraintlayout.widget.ConstraintSet! getConstraintSet();
+    field public static final String TAG = "Constraints";
+  }
+
+  public static class Constraints.LayoutParams extends androidx.constraintlayout.widget.ConstraintLayout.LayoutParams {
+    ctor public Constraints.LayoutParams(android.content.Context!, android.util.AttributeSet!);
+    ctor public Constraints.LayoutParams(androidx.constraintlayout.widget.Constraints.LayoutParams!);
+    ctor public Constraints.LayoutParams(int, int);
+    field public float alpha;
+    field public boolean applyElevation;
+    field public float elevation;
+    field public float rotation;
+    field public float rotationX;
+    field public float rotationY;
+    field public float scaleX;
+    field public float scaleY;
+    field public float transformPivotX;
+    field public float transformPivotY;
+    field public float translationX;
+    field public float translationY;
+    field public float translationZ;
+  }
+
+  public abstract class ConstraintsChangedListener {
+    ctor public ConstraintsChangedListener();
+    method public void postLayoutChange(int, int);
+    method public void preLayoutChange(int, int);
+  }
+
+  public class Group extends androidx.constraintlayout.widget.ConstraintHelper {
+    ctor public Group(android.content.Context!);
+    ctor public Group(android.content.Context!, android.util.AttributeSet!);
+    ctor public Group(android.content.Context!, android.util.AttributeSet!, int);
+    method public void onAttachedToWindow();
+  }
+
+  public class Guideline extends android.view.View {
+    ctor public Guideline(android.content.Context!);
+    ctor public Guideline(android.content.Context!, android.util.AttributeSet!);
+    ctor public Guideline(android.content.Context!, android.util.AttributeSet!, int);
+    ctor public Guideline(android.content.Context!, android.util.AttributeSet!, int, int);
+    method public void setFilterRedundantCalls(boolean);
+    method public void setGuidelineBegin(int);
+    method public void setGuidelineEnd(int);
+    method public void setGuidelinePercent(float);
+  }
+
+  public class Placeholder extends android.view.View {
+    ctor public Placeholder(android.content.Context!);
+    ctor public Placeholder(android.content.Context!, android.util.AttributeSet!);
+    ctor public Placeholder(android.content.Context!, android.util.AttributeSet!, int);
+    ctor public Placeholder(android.content.Context!, android.util.AttributeSet!, int, int);
+    method public android.view.View! getContent();
+    method public int getEmptyVisibility();
+    method public void onDraw(android.graphics.Canvas);
+    method public void setContentId(int);
+    method public void setEmptyVisibility(int);
+    method public void updatePostMeasure(androidx.constraintlayout.widget.ConstraintLayout!);
+    method public void updatePreLayout(androidx.constraintlayout.widget.ConstraintLayout!);
+  }
+
+  public class ReactiveGuide extends android.view.View implements androidx.constraintlayout.widget.SharedValues.SharedValuesListener {
+    ctor public ReactiveGuide(android.content.Context!);
+    ctor public ReactiveGuide(android.content.Context!, android.util.AttributeSet!);
+    ctor public ReactiveGuide(android.content.Context!, android.util.AttributeSet!, int);
+    ctor public ReactiveGuide(android.content.Context!, android.util.AttributeSet!, int, int);
+    method public int getApplyToConstraintSetId();
+    method public int getAttributeId();
+    method public boolean isAnimatingChange();
+    method public void onNewValue(int, int, int);
+    method public void setAnimateChange(boolean);
+    method public void setApplyToConstraintSetId(int);
+    method public void setAttributeId(int);
+    method public void setGuidelineBegin(int);
+    method public void setGuidelineEnd(int);
+    method public void setGuidelinePercent(float);
+  }
+
+  public class SharedValues {
+    ctor public SharedValues();
+    method public void addListener(int, androidx.constraintlayout.widget.SharedValues.SharedValuesListener!);
+    method public void clearListeners();
+    method public void fireNewValue(int, int);
+    method public int getValue(int);
+    method public void removeListener(androidx.constraintlayout.widget.SharedValues.SharedValuesListener!);
+    method public void removeListener(int, androidx.constraintlayout.widget.SharedValues.SharedValuesListener!);
+    field public static final int UNSET = -1; // 0xffffffff
+  }
+
+  public static interface SharedValues.SharedValuesListener {
+    method public void onNewValue(int, int, int);
+  }
+
+  public class StateSet {
+    ctor public StateSet(android.content.Context!, org.xmlpull.v1.XmlPullParser!);
+    method public int convertToConstraintSet(int, int, float, float);
+    method public boolean needsToChange(int, float, float);
+    method public void setOnConstraintsChanged(androidx.constraintlayout.widget.ConstraintsChangedListener!);
+    method public int stateGetConstraintID(int, int, int);
+    method public int updateConstraints(int, int, float, float);
+    field public static final String TAG = "ConstraintLayoutStates";
+  }
+
+  public abstract class VirtualLayout extends androidx.constraintlayout.widget.ConstraintHelper {
+    ctor public VirtualLayout(android.content.Context!);
+    ctor public VirtualLayout(android.content.Context!, android.util.AttributeSet!);
+    ctor public VirtualLayout(android.content.Context!, android.util.AttributeSet!, int);
+    method public void onAttachedToWindow();
+    method public void onMeasure(androidx.constraintlayout.core.widgets.VirtualLayout!, int, int);
+  }
+
+}
+
diff --git a/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/E2EExtensionTests.kt b/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/E2EExtensionTests.kt
index ba2e475..08c30da 100644
--- a/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/E2EExtensionTests.kt
+++ b/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/E2EExtensionTests.kt
@@ -20,14 +20,16 @@
 import android.content.Intent
 import android.os.Build
 import android.os.Build.VERSION_CODES
-import androidx.annotation.RequiresApi
 import androidx.core.telecom.CallAttributesCompat
 import androidx.core.telecom.CallsManager
+import androidx.core.telecom.extensions.CallExtensionsScope
 import androidx.core.telecom.extensions.Capability
 import androidx.core.telecom.extensions.Participant
 import androidx.core.telecom.extensions.ParticipantClientActions
+import androidx.core.telecom.extensions.connectExtensions
 import androidx.core.telecom.extensions.getParticipantActions
 import androidx.core.telecom.internal.CallCompat
+import androidx.core.telecom.internal.CapabilityExchangeListenerRemote
 import androidx.core.telecom.internal.InCallServiceCompat
 import androidx.core.telecom.test.VoipAppWithExtensions.VoipAppWithExtensionsControl
 import androidx.core.telecom.test.VoipAppWithExtensions.VoipAppWithExtensionsControlLocal
@@ -43,6 +45,8 @@
 import androidx.test.rule.GrantPermissionRule
 import androidx.test.rule.ServiceTestRule
 import junit.framework.TestCase.assertEquals
+import junit.framework.TestCase.assertNull
+import kotlinx.coroutines.CompletableDeferred
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.withTimeoutOrNull
@@ -62,7 +66,6 @@
  * ConnSrv implementations of CallsManager.
  */
 @SdkSuppress(minSdkVersion = VERSION_CODES.O /* api=26 */)
-@RequiresApi(VERSION_CODES.O)
 @OptIn(ExperimentalAppActions::class)
 @RunWith(Parameterized::class)
 class E2EExtensionTests(private val parameters: TestParameters) : BaseTelecomTest() {
@@ -73,12 +76,12 @@
         private const val SERVICE_SOURCE_CONNSRV = 2
         // Set up a Capability with all actions supported.
         private val CAPABILITY_PARTICIPANT_WITH_ACTIONS =
-            Capability().apply {
-                featureId = CallsManager.PARTICIPANT
-                featureVersion = 1
-                supportedActions =
-                    intArrayOf(CallsManager.RAISE_HAND_ACTION, CallsManager.KICK_PARTICIPANT_ACTION)
-            }
+            createCapability(
+                id = CallsManager.PARTICIPANT,
+                version = 1,
+                actions =
+                    setOf(CallsManager.RAISE_HAND_ACTION, CallsManager.KICK_PARTICIPANT_ACTION)
+            )
 
         /** Provide all the combinations of parameters that should be tested for each run */
         @JvmStatic
@@ -94,6 +97,14 @@
                 )
                 .toList()
         }
+
+        fun createCapability(id: Int, version: Int, actions: Set<Int>): Capability {
+            return Capability().apply {
+                featureId = id
+                featureVersion = version
+                supportedActions = actions.toIntArray()
+            }
+        }
     }
 
     /**
@@ -144,7 +155,7 @@
         createAndVerifyVoipCall(
             voipAppControl,
             listOf(CAPABILITY_PARTICIPANT_WITH_ACTIONS),
-            CallAttributesCompat.DIRECTION_OUTGOING
+            parameters.direction
         )
         TestUtils.waitOnInCallServiceToReachXCalls(1)
         try {
@@ -156,6 +167,74 @@
     }
 
     /**
+     * Refactor Part 1: Move ICS logic from InCallServiceCompat -> CallExtensions
+     *
+     * <p>
+     * Create a new VOIP call and use [connectExtensions] in the ICS to connect to the VOIP call.
+     * Once complete, use the [CallExtensionsScope.registerExtension] method to register an
+     * extension and ensure that for valid capabilities (PARTICIPANT), we get the remote interface
+     * used to setup/maintain the connection. For capabilities that do not exist on the remote,
+     * ensure we get the correct null indication.
+     */
+    @LargeTest
+    @Test(timeout = 10000)
+    fun testIcsExtensionsCreation() = runBlocking {
+        setupParameterizedTest()
+        val voipAppControl = bindToVoipAppWithExtensions()
+        createAndVerifyVoipCall(
+            voipAppControl,
+            listOf(CAPABILITY_PARTICIPANT_WITH_ACTIONS),
+            parameters.direction
+        )
+
+        val call = TestUtils.waitOnInCallServiceToReachXCalls(1)!!
+        var hasConnected = false
+        val icsCapability =
+            createCapability(
+                id = CallsManager.PARTICIPANT,
+                version = 2,
+                actions = setOf(CallsManager.RAISE_HAND_ACTION)
+            )
+        // Manually connect extensions here to exercise the CallExtensionsScope class
+        connectExtensions(mContext, call) {
+            val remote =
+                registerExtension(
+                    this,
+                    icsCapability,
+                    negotiatedCapability =
+                        createCapability(
+                            id = CallsManager.PARTICIPANT,
+                            version = 1,
+                            actions = setOf(CallsManager.RAISE_HAND_ACTION)
+                        )
+                )
+            // Create an extension that the VOIP app does not know about and ensure that
+            // we receive a null response during negotiation so we can notify the ICS of the state
+            // of that extension
+            val nonexistentRemote =
+                registerExtension(
+                    this,
+                    icsCapability =
+                        createCapability(id = 8675309, version = 42, actions = emptySet()),
+                    negotiatedCapability = null
+                )
+            onConnected {
+                hasConnected = true
+                assertNotNull(
+                    "Connection to remote should not be null for VOIP supported features",
+                    remote.await()
+                )
+                assertNull(
+                    "Connection to remote should be null for features with no VOIP support",
+                    nonexistentRemote.await()
+                )
+                call.disconnect()
+            }
+        }
+        assertTrue("onConnected never received", hasConnected)
+    }
+
+    /**
      * Validate that for a bound VOIP app, when a new call is added, the InCallService receives the
      * new call and can use all Participant extension interfaces.
      */
@@ -178,7 +257,7 @@
             createAndVerifyVoipCall(
                 voipAppControl,
                 listOf(CAPABILITY_PARTICIPANT_WITH_ACTIONS),
-                CallAttributesCompat.DIRECTION_OUTGOING
+                parameters.direction
             )
         val icsCall = getLastIcsCall()
 
@@ -227,6 +306,33 @@
      * Helpers
      * =========================================================================================
      */
+    private fun registerExtension(
+        scope: CallExtensionsScope,
+        icsCapability: Capability,
+        negotiatedCapability: Capability?
+    ): CompletableDeferred<CapabilityExchangeListenerRemote?> {
+        val deferredVal = CompletableDeferred<CapabilityExchangeListenerRemote?>()
+        // Register a test extension that will receive the PARTICIPANT capability
+        scope.registerExtension(icsCapability) { capability, remote ->
+            assertEquals(
+                "Expected PARTICIPANT capability",
+                negotiatedCapability?.featureId,
+                capability?.featureId
+            )
+            assertEquals(
+                "Expected version to equal the lowest common version",
+                negotiatedCapability?.featureVersion,
+                capability?.featureVersion
+            )
+            assertEquals(
+                "The negotiated actions should be the actions supported by both",
+                negotiatedCapability?.supportedActions?.toSet(),
+                capability?.supportedActions?.toSet()
+            )
+            deferredVal.complete(remote)
+        }
+        return deferredVal
+    }
 
     /** Verify that the ICS state for raised hands matches the VOIP app's updates to the state */
     private suspend fun verifyIcsRaisedHandsMatch(
diff --git a/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/VoipAppWithExtensions/VoipCall.kt b/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/VoipAppWithExtensions/VoipCall.kt
index 7230508..5e61165 100644
--- a/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/VoipAppWithExtensions/VoipCall.kt
+++ b/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/VoipAppWithExtensions/VoipCall.kt
@@ -51,7 +51,7 @@
         onDisconnect: suspend (disconnectCause: DisconnectCause) -> Unit,
         onSetActive: suspend () -> Unit,
         onSetInactive: suspend () -> Unit,
-        init: suspend CallControlScope.() -> Unit
+        init: CallControlScope.() -> Unit
     ) {
         callsManager.addCallWithExtensions(
             callAttributes,
diff --git a/core/core-telecom/src/main/java/androidx/core/telecom/extensions/CallExtensions.kt b/core/core-telecom/src/main/java/androidx/core/telecom/extensions/CallExtensions.kt
new file mode 100644
index 0000000..d0f69a4
--- /dev/null
+++ b/core/core-telecom/src/main/java/androidx/core/telecom/extensions/CallExtensions.kt
@@ -0,0 +1,436 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:JvmName("CallExtensions")
+
+package androidx.core.telecom.extensions
+
+import android.Manifest
+import android.content.Context
+import android.content.pm.PackageManager
+import android.os.Build
+import android.os.Bundle
+import android.os.Handler
+import android.os.IBinder
+import android.os.Looper
+import android.telecom.Call
+import android.telecom.Call.Callback
+import android.telecom.InCallService
+import android.telecom.PhoneAccount
+import android.telecom.TelecomManager
+import android.util.Log
+import androidx.annotation.DoNotInline
+import androidx.annotation.IntDef
+import androidx.annotation.RequiresApi
+import androidx.core.content.ContextCompat
+import androidx.core.telecom.CallsManager
+import androidx.core.telecom.internal.CapabilityExchangeListenerRemote
+import androidx.core.telecom.internal.utils.Utils
+import androidx.core.telecom.util.ExperimentalAppActions
+import java.util.Collections
+import kotlin.coroutines.resume
+import kotlin.coroutines.suspendCoroutine
+import kotlin.math.min
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.channels.trySendBlocking
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.callbackFlow
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.suspendCancellableCoroutine
+import kotlinx.coroutines.withTimeoutOrNull
+
+/**
+ * Connects extensions to the provided [Call], allowing the call to support additional optional
+ * behaviors beyond the traditional call state management.
+ *
+ * For example, an extension may allow the participants of a meeting to be surfaced to this
+ * application so that the user can view and manage the participants in the meeting on different
+ * surfaces:
+ * ```
+ * class InCallServiceImpl : InCallServiceCompat() {
+ * ...
+ *   override fun onCallAdded(call: Call) {
+ *     lifecycleScope.launch {
+ *       connectExtensions(context, call) {
+ *         // Initialize extensions
+ *         onConnected { call ->
+ *           // change call states & listen/update extensions
+ *         }
+ *       }
+ *       // Once the call is destroyed, control flow will resume again
+ *     }
+ *   }
+ *  ...
+ * }
+ * ```
+ */
+@ExperimentalAppActions
+@RequiresApi(Build.VERSION_CODES.O)
+internal suspend fun connectExtensions(
+    applicationContext: Context,
+    call: Call,
+    init: CallExtensionsScope.() -> Unit
+) {
+    val scope = CallExtensionsScope(applicationContext, call)
+    scope.init()
+    when (val type = scope.resolveCallExtensionsType()) {
+        CallExtensionsScope.CAPABILITY_EXCHANGE -> scope.performCapabilityExchange()
+        else -> Log.w(CallExtensionsScope.TAG, "connectExtensions: unexpected type: $type")
+    }
+    scope.invokeDelegate()
+    scope.waitForDestroy()
+}
+
+/**
+ * Extensions registering to handle Extension must implement this receiver in order to create and
+ * maintain the connection to the extension that they support.
+ *
+ * @see [CallExtensionsScope.registerExtension]
+ */
+@OptIn(ExperimentalAppActions::class)
+internal typealias ExtensionReceiver = (Capability?, CapabilityExchangeListenerRemote?) -> Unit
+
+/**
+ * Represents the result of performing capability exchange with the underlying VOIP application.
+ * Contains the capabilities that the VOIP app supports and the remote binder implementation used to
+ * communicate with the remote process.
+ */
+@ExperimentalAppActions
+internal data class CapabilityExchangeResult(
+    val voipCapabilities: Set<Capability>,
+    val extensionInitializationBinder: CapabilityExchangeListenerRemote
+)
+
+/**
+ * The scope enclosing an ongoing call that allows the user to set up optional extensions to the
+ * call.
+ *
+ * Once the call is connected to the remote, [onConnected] will be called and the [Call] is ready to
+ * be used with extensions:
+ * ```
+ * connectExtensions(context, call) {
+ *   // initialize extensions
+ *   onConnected { call ->
+ *     // call extensions are ready to be used along with the traditional call APIs
+ *   }
+ * }
+ * ```
+ */
+@RequiresApi(Build.VERSION_CODES.O)
+@ExperimentalAppActions
+internal class CallExtensionsScope(
+    private val applicationContext: Context,
+    private val call: Call
+) {
+
+    companion object {
+        internal const val TAG = "CallExtensions"
+        internal const val CAPABILITY_EXCHANGE_VERSION = 1
+        internal const val RESOLVE_EXTENSIONS_TYPE_TIMEOUT_MS = 1000L
+        internal const val CAPABILITY_EXCHANGE_TIMEOUT_MS = 1000L
+
+        /** Constants used to denote the extension level supported by the VOIP app. */
+        @Retention(AnnotationRetention.SOURCE)
+        @IntDef(NONE, EXTRAS, CAPABILITY_EXCHANGE, UNKNOWN)
+        internal annotation class CapabilityExchangeType
+
+        internal const val NONE = 0
+        internal const val EXTRAS = 1
+        internal const val CAPABILITY_EXCHANGE = 2
+        internal const val UNKNOWN = 3
+    }
+
+    private var delegate: (suspend (Call) -> Unit)? = null
+    // Maps a Capability that has been registered to the Receiver that will be used to create and
+    // maintain the extension connection with the remote VOIP application.
+    private val callExtensions = HashMap<Capability, ExtensionReceiver>()
+
+    /**
+     * Called when the [Call] extensions have been successfully set up and are ready to be used.
+     *
+     * @param block Called when extensions are ready to be used
+     */
+    fun onConnected(block: suspend (Call) -> Unit) {
+        delegate = block
+    }
+
+    /**
+     * Register an extension with this call, whose [capability] will be negotiated with the VOIP
+     * application.
+     *
+     * Once capability exchange completes, the shared [Capability.featureId] will be used to map the
+     * negotiated capability with this extension and [receiver] will be called with a valid
+     * negotiated [Capability] and interface to use to create/manage this extension with the remote.
+     *
+     * @param capability The [Capability] that will be registered to this extension and used during
+     *   feature negotiation.
+     * @param receiver The receiver that will be called once capability exchange completes and we
+     *   either have a valid negotiated capability or a `null` Capability if the remote side does
+     *   not support this capability.
+     */
+    internal fun registerExtension(capability: Capability, receiver: ExtensionReceiver) {
+        callExtensions[capability] = receiver
+    }
+
+    /**
+     * Invoke the stored [onConnected] block once capability exchange has completed and the
+     * associated extensions have been set up.
+     */
+    internal suspend fun invokeDelegate() {
+        Log.i(TAG, "invokeDelegate")
+        delegate?.invoke(call)
+    }
+
+    /**
+     * Internal helper used to help resolve the call extension type. This is invoked before
+     * capability exchange between the [InCallService] and VOIP app starts to ensure the necessary
+     * features are enabled to support it.
+     *
+     * If the call is placed using the V1.5 ConnectionService + Extensions Library (Auto Case), the
+     * call will have the [CallsManager.EXTRA_VOIP_API_VERSION] defined in the extras. The call
+     * extension would be resolved as [EXTRAS].
+     *
+     * If the call is using the v2 APIs and the phone account associated with the call supports
+     * transactional ops (U+) or the call has the [CallsManager.PROPERTY_IS_TRANSACTIONAL] property
+     * defined (on V devices), then the extension type is [CAPABILITY_EXCHANGE].
+     *
+     * If the call is added via [CallsManager.addCall] on pre-U devices and the
+     * [CallsManager.EXTRA_VOIP_BACKWARDS_COMPATIBILITY_SUPPORTED] is present in the call extras,
+     * the extension type also resolves to [CAPABILITY_EXCHANGE].
+     *
+     * In the case that none of the cases above apply and the phone account is found not to support
+     * transactional ops (assumes that caller has [android.Manifest.permission.READ_PHONE_NUMBERS]
+     * permission), then the extension type is [NONE].
+     *
+     * If the caller does not have the required permission to retrieve the phone account, then the
+     * extension type will be [UNKNOWN], until it can be resolved.
+     *
+     * @return the extension type [CapabilityExchangeType] resolved for the call.
+     */
+    internal suspend fun resolveCallExtensionsType(): Int {
+        var details = call.details
+        var type = NONE
+        // Android CallsManager V+ check
+        if (details.hasProperty(CallsManager.PROPERTY_IS_TRANSACTIONAL)) {
+            return CAPABILITY_EXCHANGE
+        }
+        if (Utils.hasPlatformV2Apis()) {
+            // Android CallsManager U check
+            // Verify read phone numbers permission to see if phone account supports transactional
+            // ops.
+            if (
+                ContextCompat.checkSelfPermission(
+                    applicationContext,
+                    Manifest.permission.READ_PHONE_NUMBERS
+                ) == PackageManager.PERMISSION_GRANTED
+            ) {
+                val telecomManager =
+                    applicationContext.getSystemService(Context.TELECOM_SERVICE) as TelecomManager
+                val phoneAccount = telecomManager.getPhoneAccount(details.accountHandle)
+                if (
+                    phoneAccount?.hasCapabilities(
+                        PhoneAccount.CAPABILITY_SUPPORTS_TRANSACTIONAL_OPERATIONS
+                    ) == true
+                ) {
+                    return CAPABILITY_EXCHANGE
+                } else {
+                    Log.i(
+                        TAG,
+                        "Unable to resolve call extension type due to lack of" + "permission."
+                    )
+                    type = UNKNOWN
+                }
+            }
+        }
+        // The extras may come in after the call is first signalled to InCallService - wait for the
+        // details to be populated with extras.
+        if (details.extras == null || details.extras.isEmpty()) {
+            details =
+                withTimeoutOrNull(RESOLVE_EXTENSIONS_TYPE_TIMEOUT_MS) {
+                    detailsFlow().first { details ->
+                        details.extras != null && !details.extras.isEmpty()
+                    }
+                    // return initial details if no updates come in before the timeout
+                } ?: call.details
+        }
+        val callExtras = details.extras ?: Bundle()
+        // Extras based impl check
+        if (callExtras.containsKey(CallsManager.EXTRA_VOIP_API_VERSION)) {
+            return EXTRAS
+        }
+        // CS based impl check
+        if (callExtras.containsKey(CallsManager.EXTRA_VOIP_BACKWARDS_COMPATIBILITY_SUPPORTED)) {
+            return CAPABILITY_EXCHANGE
+        }
+        Log.i(TAG, "Unable to resolve call extension type. Returning $type.")
+        return type
+    }
+
+    /**
+     * Perform the capability exchange procedure with the calling application and negotiate
+     * capabilities. When complete, call all extension that were registered with [registerExtension]
+     * and provide the negotiated capability or null.
+     *
+     * If negotiation takes longer than [CAPABILITY_EXCHANGE_TIMEOUT_MS], we will assume the remote
+     * does not support extensions at all.
+     */
+    internal suspend fun performCapabilityExchange() {
+        Log.i(TAG, "performCapabilityExchange: Starting capability negotiation with VOIP app...")
+        val extensions =
+            withTimeoutOrNull(CAPABILITY_EXCHANGE_TIMEOUT_MS) { registerWithRemoteService() }
+        if (extensions == null) {
+            Log.w(TAG, "performCapabilityExchange: never received response")
+            for (initializer in callExtensions.entries) {
+                initializer.value.invoke(null, null)
+            }
+            return
+        }
+
+        for (initializer in callExtensions.entries) {
+            val remoteCap =
+                extensions.voipCapabilities.firstOrNull {
+                    it.featureId == initializer.key.featureId
+                }
+            if (remoteCap == null) {
+                initializer.value.invoke(null, null)
+                continue
+            }
+            initializer.value.invoke(
+                calculateNegotiatedCapability(initializer.key, remoteCap),
+                extensions.extensionInitializationBinder
+            )
+        }
+    }
+
+    /**
+     * Initiate capability exchange via a call event and wait for the response from the calling
+     * application using the Binder passed to the remote service.
+     *
+     * @return the remote capabilities and Binder interface used to communicate with the remote
+     */
+    private suspend fun registerWithRemoteService(): CapabilityExchangeResult? =
+        suspendCoroutine { continuation ->
+            val binder =
+                object : ICapabilityExchange.Stub() {
+                    override fun beginExchange(
+                        capabilities: MutableList<Capability>?,
+                        l: ICapabilityExchangeListener?
+                    ) {
+                        continuation.resume(
+                            l?.let {
+                                CapabilityExchangeResult(
+                                    capabilities?.toSet() ?: Collections.emptySet(),
+                                    CapabilityExchangeListenerRemote(l)
+                                )
+                            }
+                        )
+                    }
+                }
+            val extras = setExtras(binder)
+            call.sendCallEvent(CallsManager.EVENT_JETPACK_CAPABILITY_EXCHANGE, extras)
+        }
+
+    /**
+     * @return the negotiated capability by finding the highest version and actions supported by
+     *   both the local and remote interfaces.
+     */
+    @ExperimentalAppActions
+    private fun calculateNegotiatedCapability(
+        localCapability: Capability,
+        remoteCapability: Capability
+    ): Capability {
+        return Capability().apply {
+            featureId = localCapability.featureId
+            featureVersion = min(localCapability.featureVersion, remoteCapability.featureVersion)
+            supportedActions =
+                localCapability.supportedActions
+                    .intersect(remoteCapability.supportedActions.toSet())
+                    .toIntArray()
+        }
+    }
+
+    /**
+     * @return a [Bundle] that contains the binder and version used by the remote to respond to a
+     *   capability exchange request.
+     */
+    @RequiresApi(Build.VERSION_CODES.O)
+    private fun setExtras(binder: IBinder): Bundle {
+        return Bundle().apply {
+            putBinder(CallsManagerExtensions.EXTRA_CAPABILITY_EXCHANGE_BINDER, binder)
+            putInt(
+                CallsManagerExtensions.EXTRA_CAPABILITY_EXCHANGE_VERSION,
+                CAPABILITY_EXCHANGE_VERSION
+            )
+        }
+    }
+
+    /** Create a flow that reports changes to [Call.Details] provided by the [Call.Callback]. */
+    private fun detailsFlow(): Flow<Call.Details> = callbackFlow {
+        val callback =
+            object : Callback() {
+                override fun onDetailsChanged(call: Call?, details: Call.Details?) {
+                    details?.also { trySendBlocking(it) }
+                }
+            }
+        // send the current state first since registering for the callback doesn't deliver the
+        // current value.
+        trySendBlocking(call.details)
+        call.registerCallback(callback, Handler(Looper.getMainLooper()))
+        awaitClose { call.unregisterCallback(callback) }
+    }
+
+    /** Wait for the call to be destroyed. */
+    internal suspend fun waitForDestroy() = suspendCancellableCoroutine { continuation ->
+        val callback =
+            object : Callback() {
+                override fun onCallDestroyed(targetCall: Call?) {
+                    if (targetCall == null || call != targetCall || continuation.isCompleted) return
+                    continuation.resume(Unit)
+                }
+            }
+        if (Api26Impl.getCallState(call) != Call.STATE_DISCONNECTED) {
+            call.registerCallback(callback, Handler(Looper.getMainLooper()))
+            continuation.invokeOnCancellation { call.unregisterCallback(callback) }
+        } else {
+            continuation.resume(Unit)
+        }
+    }
+}
+
+/** Ensure compatibility for [Call] APIs back to API level 26 */
+@RequiresApi(Build.VERSION_CODES.O)
+private object Api26Impl {
+    @Suppress("DEPRECATION")
+    @JvmStatic
+    @DoNotInline
+    fun getCallState(call: Call): Int {
+        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+            Api31Impl.getCallState(call)
+        } else {
+            call.state
+        }
+    }
+}
+
+/** Ensure compatibility for [Call] APIs for API level 31+ */
+@RequiresApi(Build.VERSION_CODES.S)
+private object Api31Impl {
+    @JvmStatic
+    @DoNotInline
+    fun getCallState(call: Call): Int {
+        return call.details.state
+    }
+}
diff --git a/core/core-telecom/src/main/java/androidx/core/telecom/extensions/ParticipantExtension.kt b/core/core-telecom/src/main/java/androidx/core/telecom/extensions/ParticipantExtension.kt
index 77571da..4b75ee0 100644
--- a/core/core-telecom/src/main/java/androidx/core/telecom/extensions/ParticipantExtension.kt
+++ b/core/core-telecom/src/main/java/androidx/core/telecom/extensions/ParticipantExtension.kt
@@ -165,10 +165,11 @@
     /**
      * The active participant associated with this call, if it exists
      *
-     * @param p the participant that is marked as active or `null` if there is no active participant
+     * @param participant the participant that is marked as active or `null` if there is no active
+     *   participant
      */
-    suspend fun updateActiveParticipant(p: Participant?) {
-        activeParticipant.emit(p)
+    suspend fun updateActiveParticipant(participant: Participant?) {
+        activeParticipant.emit(participant)
     }
 
     /**
diff --git a/core/core-telecom/src/main/java/androidx/core/telecom/internal/AidlExtensions.kt b/core/core-telecom/src/main/java/androidx/core/telecom/internal/AidlExtensions.kt
index 1f49e18..9e90998 100644
--- a/core/core-telecom/src/main/java/androidx/core/telecom/internal/AidlExtensions.kt
+++ b/core/core-telecom/src/main/java/androidx/core/telecom/internal/AidlExtensions.kt
@@ -71,6 +71,10 @@
 internal class CapabilityExchangeRemote(binder: ICapabilityExchange) :
     ICapabilityExchange by binder
 
+@ExperimentalAppActions
+internal class CapabilityExchangeListenerRemote(binder: ICapabilityExchangeListener) :
+    ICapabilityExchangeListener by binder
+
 /**
  * The implementation of the capability exchange listener, which is used by the InCallService to
  * create and remove extensions.
diff --git a/core/core/api/current.txt b/core/core/api/current.txt
index 9529deb..3d8ff29 100644
--- a/core/core/api/current.txt
+++ b/core/core/api/current.txt
@@ -2489,7 +2489,9 @@
   public final class DisplayCutoutCompat {
     ctor public DisplayCutoutCompat(android.graphics.Rect?, java.util.List<android.graphics.Rect!>?);
     ctor public DisplayCutoutCompat(androidx.core.graphics.Insets, android.graphics.Rect?, android.graphics.Rect?, android.graphics.Rect?, android.graphics.Rect?, androidx.core.graphics.Insets);
+    ctor public DisplayCutoutCompat(androidx.core.graphics.Insets, android.graphics.Rect?, android.graphics.Rect?, android.graphics.Rect?, android.graphics.Rect?, androidx.core.graphics.Insets, android.graphics.Path?);
     method public java.util.List<android.graphics.Rect!> getBoundingRects();
+    method public android.graphics.Path? getCutoutPath();
     method public int getSafeInsetBottom();
     method public int getSafeInsetLeft();
     method public int getSafeInsetRight();
diff --git a/core/core/api/restricted_current.txt b/core/core/api/restricted_current.txt
index c280485..fd3badb 100644
--- a/core/core/api/restricted_current.txt
+++ b/core/core/api/restricted_current.txt
@@ -2965,7 +2965,9 @@
   public final class DisplayCutoutCompat {
     ctor public DisplayCutoutCompat(android.graphics.Rect?, java.util.List<android.graphics.Rect!>?);
     ctor public DisplayCutoutCompat(androidx.core.graphics.Insets, android.graphics.Rect?, android.graphics.Rect?, android.graphics.Rect?, android.graphics.Rect?, androidx.core.graphics.Insets);
+    ctor public DisplayCutoutCompat(androidx.core.graphics.Insets, android.graphics.Rect?, android.graphics.Rect?, android.graphics.Rect?, android.graphics.Rect?, androidx.core.graphics.Insets, android.graphics.Path?);
     method public java.util.List<android.graphics.Rect!> getBoundingRects();
+    method public android.graphics.Path? getCutoutPath();
     method public int getSafeInsetBottom();
     method public int getSafeInsetLeft();
     method public int getSafeInsetRight();
diff --git a/core/core/src/androidTest/java/androidx/core/view/DisplayCutoutCompatTest.java b/core/core/src/androidTest/java/androidx/core/view/DisplayCutoutCompatTest.java
index 4d92901..caf6393 100644
--- a/core/core/src/androidTest/java/androidx/core/view/DisplayCutoutCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/view/DisplayCutoutCompatTest.java
@@ -23,7 +23,9 @@
 import static org.hamcrest.Matchers.hasItem;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
 
+import android.graphics.Path;
 import android.graphics.Rect;
 import android.os.Build;
 
@@ -98,6 +100,26 @@
     }
 
     @Test
+    public void testCutoutPath() {
+        Path cutoutPath = new Path();
+        cutoutPath.addCircle(55, 10, 5, Path.Direction.CW);
+
+        DisplayCutoutCompat cutoutWithPath =
+                new DisplayCutoutCompat(Insets.of(0, 20, 0, 20),
+                        ZERO_RECT, new Rect(50, 0, 60, 20),
+                        ZERO_RECT, ZERO_RECT,
+                        Insets.of(0, 20, 0, 20),
+                        cutoutPath);
+
+
+        if (Build.VERSION.SDK_INT >= 33) {
+            assertEquals(cutoutPath, cutoutWithPath.getCutoutPath());
+        } else {
+            assertNull(cutoutWithPath.getCutoutPath());
+        }
+    }
+
+    @Test
     public void testEquals() {
         assertEquals(mCutoutTopBottomClone, mCutoutTopBottom);
         if (SDK_INT >= 28) {
diff --git a/core/core/src/androidTest/java/androidx/core/view/WindowInsetsControllerCompatActivityTest.kt b/core/core/src/androidTest/java/androidx/core/view/WindowInsetsControllerCompatActivityTest.kt
index 32679bb..2f07d423 100644
--- a/core/core/src/androidTest/java/androidx/core/view/WindowInsetsControllerCompatActivityTest.kt
+++ b/core/core/src/androidTest/java/androidx/core/view/WindowInsetsControllerCompatActivityTest.kt
@@ -20,7 +20,6 @@
 import android.os.Build
 import android.view.View
 import android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
-import android.widget.EditText
 import android.widget.TextView
 import androidx.annotation.RequiresApi
 import androidx.core.graphics.Insets
@@ -101,23 +100,6 @@
 
     /** IME visibility is only reliable on API 23+, where we have access to the root WindowInsets */
     @SdkSuppress(minSdkVersion = 23)
-    @Test
-    public fun do_not_show_IME_if_TextView_not_focused() {
-        val editText = scenario.withActivity { findViewById<EditText>(R.id.edittext) }
-
-        // We hide the edit text to ensure it won't be automatically focused
-        scenario.onActivity {
-            editText.visibility = View.GONE
-            assertThat(editText.isFocused, `is`(false))
-        }
-
-        val type = WindowInsetsCompat.Type.ime()
-        scenario.onActivity { windowInsetsController.show(type) }
-        container.assertInsetsVisibility(type, false)
-    }
-
-    /** IME visibility is only reliable on API 23+, where we have access to the root WindowInsets */
-    @SdkSuppress(minSdkVersion = 23)
     @Ignore("b/294556594")
     @Test
     fun show_IME_fromEditText() {
diff --git a/core/core/src/main/java/androidx/core/app/NotificationCompat.java b/core/core/src/main/java/androidx/core/app/NotificationCompat.java
index d5fd41ad..2b6ee42 100644
--- a/core/core/src/main/java/androidx/core/app/NotificationCompat.java
+++ b/core/core/src/main/java/androidx/core/app/NotificationCompat.java
@@ -5514,7 +5514,12 @@
          *                the notification.
          * @param notification The notification from which to get texts from its content view.
          * @return A list of text from the notification custom content view made by the above
-         * method. Otherwise, returns the empty list.
+         * method. Note that the method only returns a list of text from one of the custom view
+         * as the above when it set, meaning when multiple custom content views has set in a
+         * notification, the returned list will base on the detail of custom content and usage as
+         * the priority: First is {@link Notification#bigContentView}, then is
+         * {@link Notification#contentView} when no big content view has set, or
+         * {@link Notification#headsUpContentView} when set. Otherwise, returns the empty list.
          */
         @NonNull
         @SuppressWarnings("MixedMutabilityReturnType")
diff --git a/core/core/src/main/java/androidx/core/view/DisplayCutoutCompat.java b/core/core/src/main/java/androidx/core/view/DisplayCutoutCompat.java
index fd432c6..ce16f73 100644
--- a/core/core/src/main/java/androidx/core/view/DisplayCutoutCompat.java
+++ b/core/core/src/main/java/androidx/core/view/DisplayCutoutCompat.java
@@ -18,6 +18,7 @@
 
 import static android.os.Build.VERSION.SDK_INT;
 
+import android.graphics.Path;
 import android.graphics.Rect;
 import android.os.Build;
 import android.view.DisplayCutout;
@@ -74,13 +75,43 @@
             @Nullable Rect boundTop, @Nullable Rect boundRight, @Nullable Rect boundBottom,
             @NonNull Insets waterfallInsets) {
         this(constructDisplayCutout(safeInsets, boundLeft, boundTop, boundRight, boundBottom,
-                waterfallInsets));
+                waterfallInsets, null));
+    }
+
+    /**
+     * Creates a DisplayCutout instance.
+     *
+     * @param safeInsets the insets from each edge which avoid the display cutout as returned by
+     *                   {@link #getSafeInsetTop()} etc.
+     * @param boundLeft the left bounding rect of the display cutout in pixels. If null is passed,
+     *                  it's treated as an empty rectangle (0,0)-(0,0).
+     * @param boundTop the top bounding rect of the display cutout in pixels. If null is passed,
+     *                  it's treated as an empty rectangle (0,0)-(0,0).
+     * @param boundRight the right bounding rect of the display cutout in pixels. If null is
+     *                  passed, it's treated as an empty rectangle (0,0)-(0,0).
+     * @param boundBottom the bottom bounding rect of the display cutout in pixels. If null is
+     *                   passed, it's treated as an empty rectangle (0,0)-(0,0).
+     * @param waterfallInsets the insets for the curved areas in waterfall display.
+     * @param cutoutPath the path of the display cutout. Specifying a path with this
+     *                   constructor is only supported on API 33 and above, even though a real
+     *                   DisplayCutout can have a cutout path on API 31 and above. On API 32 and
+     *                   below, this path is ignored.
+     */
+    public DisplayCutoutCompat(@NonNull Insets safeInsets, @Nullable Rect boundLeft,
+            @Nullable Rect boundTop, @Nullable Rect boundRight, @Nullable Rect boundBottom,
+            @NonNull Insets waterfallInsets, @Nullable Path cutoutPath) {
+        this(constructDisplayCutout(safeInsets, boundLeft, boundTop, boundRight, boundBottom,
+                waterfallInsets, cutoutPath));
     }
 
     private static DisplayCutout constructDisplayCutout(@NonNull Insets safeInsets,
             @Nullable Rect boundLeft, @Nullable Rect boundTop, @Nullable Rect boundRight,
-            @Nullable Rect boundBottom, @NonNull Insets waterfallInsets) {
-        if (SDK_INT >= 30) {
+            @Nullable Rect boundBottom, @NonNull Insets waterfallInsets,
+            @Nullable Path cutoutPath) {
+        if (SDK_INT >= 33) {
+            return Api33Impl.createDisplayCutout(safeInsets.toPlatformInsets(), boundLeft, boundTop,
+                    boundRight, boundBottom, waterfallInsets.toPlatformInsets(), cutoutPath);
+        } else if (SDK_INT >= 30) {
             return Api30Impl.createDisplayCutout(safeInsets.toPlatformInsets(), boundLeft, boundTop,
                     boundRight, boundBottom, waterfallInsets.toPlatformInsets());
         } else if (SDK_INT >= Build.VERSION_CODES.Q) {
@@ -185,6 +216,23 @@
         }
     }
 
+    /**
+     * Returns a Path that contains the cutout paths of all sides on the display.
+     * To get a cutout path for one specific side, apps can intersect the Path with the Rect
+     * obtained from getBoundingRectLeft(), getBoundingRectTop(), getBoundingRectRight() or
+     * getBoundingRectBottom().
+     *
+     * @return the path corresponding to the cutout, or null if there is no cutout on the display.
+     */
+    @Nullable
+    public Path getCutoutPath() {
+        if (SDK_INT >= 31) {
+            return Api31Impl.getCutoutPath(mDisplayCutout);
+        } else {
+            return null;
+        }
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) {
@@ -254,6 +302,19 @@
         }
     }
 
+    @RequiresApi(29)
+    static class Api29Impl {
+        private Api29Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static DisplayCutout createDisplayCutout(android.graphics.Insets safeInsets, Rect boundLeft,
+                Rect boundTop, Rect boundRight, Rect boundBottom) {
+            return new DisplayCutout(safeInsets, boundLeft, boundTop, boundRight, boundBottom);
+        }
+    }
+
     @RequiresApi(30)
     static class Api30Impl {
         private Api30Impl() {
@@ -274,16 +335,38 @@
         }
     }
 
-    @RequiresApi(29)
-    static class Api29Impl {
-        private Api29Impl() {
+    @RequiresApi(31)
+    static class Api31Impl {
+        private Api31Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        @Nullable
+        static Path getCutoutPath(DisplayCutout displayCutout) {
+            return displayCutout.getCutoutPath();
+        }
+    }
+
+    @RequiresApi(33)
+    static class Api33Impl {
+        private Api33Impl() {
             // This class is not instantiable.
         }
 
         @DoNotInline
         static DisplayCutout createDisplayCutout(android.graphics.Insets safeInsets, Rect boundLeft,
-                Rect boundTop, Rect boundRight, Rect boundBottom) {
-            return new DisplayCutout(safeInsets, boundLeft, boundTop, boundRight, boundBottom);
+                Rect boundTop, Rect boundRight, Rect boundBottom,
+                android.graphics.Insets waterfallInsets, Path cutoutPath) {
+            return new DisplayCutout.Builder()
+                    .setSafeInsets(safeInsets)
+                    .setBoundingRectLeft(boundLeft)
+                    .setBoundingRectTop(boundTop)
+                    .setBoundingRectRight(boundRight)
+                    .setBoundingRectBottom(boundBottom)
+                    .setWaterfallInsets(waterfallInsets)
+                    .setCutoutPath(cutoutPath)
+                    .build();
         }
     }
 }
diff --git a/core/uwb/uwb/src/main/java/androidx/core/uwb/impl/UwbControllerSessionScopeImpl.kt b/core/uwb/uwb/src/main/java/androidx/core/uwb/impl/UwbControllerSessionScopeImpl.kt
index 7410702..d4d1c35 100644
--- a/core/uwb/uwb/src/main/java/androidx/core/uwb/impl/UwbControllerSessionScopeImpl.kt
+++ b/core/uwb/uwb/src/main/java/androidx/core/uwb/impl/UwbControllerSessionScopeImpl.kt
@@ -80,8 +80,14 @@
 
     override suspend fun addControlee(address: UwbAddress, parameters: RangingControleeParameters) {
         val uwbAddress = com.google.android.gms.nearby.uwb.UwbAddress(address.address)
+        val uwbControleeParams =
+            com.google.android.gms.nearby.uwb.RangingControleeParameters(
+                uwbAddress,
+                parameters.subSessionId,
+                parameters.subSessionKey
+            )
         try {
-            uwbClient.addControlee(uwbAddress).await()
+            uwbClient.addControleeWithSessionParams(uwbControleeParams).await()
         } catch (e: ApiException) {
             if (e.statusCode == UwbStatusCodes.INVALID_API_CALL) {
                 throw IllegalStateException(
diff --git a/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/beginsignin/CredentialProviderBeginSignInControllerJavaTest.java b/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/beginsignin/CredentialProviderBeginSignInControllerJavaTest.java
index bffaa43..2d72cf9 100644
--- a/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/beginsignin/CredentialProviderBeginSignInControllerJavaTest.java
+++ b/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/beginsignin/CredentialProviderBeginSignInControllerJavaTest.java
@@ -16,9 +16,14 @@
 
 package androidx.credentials.playservices.beginsignin;
 
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.junit.Assert.assertThrows;
+import static org.junit.Assume.assumeFalse;
+
+import android.content.Context;
 
 import androidx.credentials.GetCredentialRequest;
 import androidx.credentials.GetPasswordOption;
@@ -27,6 +32,8 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 
+import com.google.android.gms.common.ConnectionResult;
+import com.google.android.gms.common.GoogleApiAvailability;
 import com.google.android.libraries.identity.googleid.GetGoogleIdOption;
 
 import org.junit.Test;
@@ -45,6 +52,7 @@
                 ActivityScenario.launch(TestCredentialsActivity.class);
         activityScenario.onActivity(
                 activity -> {
+                    assumeFalse(deviceHasGMS(getApplicationContext()));
                     com.google.android.gms.auth.api.identity.BeginSignInRequest actualResponse =
                             androidx.credentials.playservices.controllers.BeginSignIn.CredentialProviderBeginSignInController.getInstance(activity)
                                     .convertRequestToPlayServices(
@@ -62,6 +70,7 @@
                 ActivityScenario.launch(TestCredentialsActivity.class);
         activityScenario.onActivity(
                 activity -> {
+                    assumeFalse(deviceHasGMS(getApplicationContext()));
                     com.google.android.gms.auth.api.identity.BeginSignInRequest actualResponse =
                             androidx.credentials.playservices.controllers.BeginSignIn.CredentialProviderBeginSignInController.getInstance(activity)
                                     .convertRequestToPlayServices(
@@ -81,6 +90,7 @@
                 ActivityScenario.launch(TestCredentialsActivity.class);
         activityScenario.onActivity(
                 activity -> {
+                    assumeFalse(deviceHasGMS(getApplicationContext()));
                     assertThrows(
                             "null get credential request must throw exception",
                             NullPointerException.class,
@@ -96,6 +106,7 @@
                 ActivityScenario.launch(TestCredentialsActivity.class);
         activityScenario.onActivity(
                 activity -> {
+                    assumeFalse(deviceHasGMS(getApplicationContext()));
                     assertThrows(
                             "null sign in credential response must throw exception",
                             NullPointerException.class,
@@ -122,6 +133,7 @@
 
         activityScenario.onActivity(
                 activity -> {
+                    assumeFalse(deviceHasGMS(getApplicationContext()));
                     com.google.android.gms.auth.api.identity.BeginSignInRequest actualRequest =
                             androidx.credentials.playservices.controllers.BeginSignIn.CredentialProviderBeginSignInController.getInstance(activity)
                                     .convertRequestToPlayServices(
@@ -153,6 +165,7 @@
                 ActivityScenario.launch(TestCredentialsActivity.class);
         activityScenario.onActivity(
                 activity -> {
+                assumeFalse(deviceHasGMS(getApplicationContext()));
                     androidx.credentials.playservices.controllers.BeginSignIn.CredentialProviderBeginSignInController firstInstance =
                             androidx.credentials.playservices.controllers.BeginSignIn.CredentialProviderBeginSignInController.getInstance(activity);
                     androidx.credentials.playservices.controllers.BeginSignIn.CredentialProviderBeginSignInController secondInstance =
@@ -160,4 +173,9 @@
                     assertThat(firstInstance).isNotEqualTo(secondInstance);
                 });
     }
+
+    private boolean deviceHasGMS(Context context) {
+        return GoogleApiAvailability.getInstance()
+                .isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS;
+    }
 }
diff --git a/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/beginsignin/CredentialProviderBeginSignInControllerTest.kt b/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/beginsignin/CredentialProviderBeginSignInControllerTest.kt
index 510f166..4bc0d41 100644
--- a/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/beginsignin/CredentialProviderBeginSignInControllerTest.kt
+++ b/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/beginsignin/CredentialProviderBeginSignInControllerTest.kt
@@ -16,6 +16,7 @@
 
 package androidx.credentials.playservices.beginsignin
 
+import android.content.Context
 import android.os.Build
 import androidx.annotation.RequiresApi
 import androidx.credentials.GetCredentialRequest
@@ -23,10 +24,14 @@
 import androidx.credentials.playservices.TestCredentialsActivity
 import androidx.credentials.playservices.controllers.BeginSignIn.CredentialProviderBeginSignInController.Companion.getInstance
 import androidx.test.core.app.ActivityScenario
+import androidx.test.core.app.ApplicationProvider.getApplicationContext
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
+import com.google.android.gms.common.ConnectionResult
+import com.google.android.gms.common.GoogleApiAvailability
 import com.google.android.libraries.identity.googleid.GetGoogleIdOption
 import com.google.common.truth.Truth.assertThat
+import org.junit.Assume.assumeFalse
 import org.junit.Test
 import org.junit.runner.RunWith
 
@@ -39,6 +44,7 @@
     fun convertRequestToPlayServices_setPasswordOptionRequestAndFalseAutoSelect_success() {
         val activityScenario = ActivityScenario.launch(TestCredentialsActivity::class.java)
         activityScenario.onActivity { activity: TestCredentialsActivity? ->
+            assumeFalse(deviceHasGMS(getApplicationContext()))
             val actualResponse =
                 getInstance(activity!!)
                     .convertRequestToPlayServices(GetCredentialRequest(listOf(GetPasswordOption())))
@@ -51,6 +57,7 @@
     fun convertRequestToPlayServices_setPasswordOptionRequestAndTrueAutoSelect_success() {
         val activityScenario = ActivityScenario.launch(TestCredentialsActivity::class.java)
         activityScenario.onActivity { activity: TestCredentialsActivity? ->
+            assumeFalse(deviceHasGMS(getApplicationContext()))
             val actualResponse =
                 getInstance(activity!!)
                     .convertRequestToPlayServices(
@@ -76,6 +83,7 @@
                 .build()
 
         activityScenario.onActivity { activity: TestCredentialsActivity? ->
+            assumeFalse(deviceHasGMS(getApplicationContext()))
             val actualRequest =
                 getInstance(activity!!)
                     .convertRequestToPlayServices(GetCredentialRequest(listOf(option)))
@@ -98,9 +106,14 @@
     fun duplicateGetInstance_shouldBeUnequal() {
         val activityScenario = ActivityScenario.launch(TestCredentialsActivity::class.java)
         activityScenario.onActivity { activity: TestCredentialsActivity? ->
+            assumeFalse(deviceHasGMS(getApplicationContext()))
             val firstInstance = getInstance(activity!!)
             val secondInstance = getInstance(activity)
             assertThat(firstInstance).isNotEqualTo(secondInstance)
         }
     }
+
+    private fun deviceHasGMS(context: Context): Boolean =
+        GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context) ==
+            ConnectionResult.SUCCESS
 }
diff --git a/development/buildHealthAdviceToCsv.main.kts b/development/buildHealthAdviceToCsv.main.kts
new file mode 100755
index 0000000..40dc9c4
--- /dev/null
+++ b/development/buildHealthAdviceToCsv.main.kts
@@ -0,0 +1,222 @@
+#!/usr/bin/env kotlin
+
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * To run .kts files, follow these steps:
+ *
+ * 1. Download and install the Kotlin compiler (kotlinc). There are several ways to do this; see
+ *    https://kotlinlang.org/docs/command-line.html
+ * 2. Run the script from the command line:
+ *    <path_to>/kotlinc -script <script_file>.kts <arguments>
+ */
+
+@file:Repository("https://repo1.maven.org/maven2")
+@file:DependsOn("com.google.code.gson:gson:2.11.0")
+
+import java.io.File
+import java.util.Locale
+import kotlin.system.exitProcess
+import com.google.gson.Gson
+
+if (args.isEmpty() || !args.contains("-input")) {
+    println("Expected path to buildHealth Advice json file using -input.")
+    println("Provide output file path using -output. By default, output.csv will be generated " +
+        "in the current directory")
+    println("Usage ex: kotlinc -script buildHealthAdviceToCsv.main.kts -- -input " +
+        "path/to/build-health-report.json -output /path/to/output.csv")
+    exitProcess(1)
+}
+
+val input = args[1]
+if (!File(input).exists()) {
+    println("Could not find input files: $input")
+    exitProcess(1)
+}
+val inputJsonFile = File(input)
+println("Parsing ${inputJsonFile.path}...")
+
+val outputFile = if(args.contains("-output")) {
+    args[3]
+} else {
+    "output.csv"
+}
+
+val csvOutputFile = File(outputFile)
+if(csvOutputFile.exists()) {
+    csvOutputFile.delete()
+}
+
+val csvData = StringBuilder()
+val columnHeaders = listOf(
+    "ID", // leave blank
+    "Priority",
+    "Summary",
+    "HotlistIds",
+    "Assignee", // leave blank
+    "Status",
+    "ComponentPath",
+    "Reporter",
+    "FirstNote"
+)
+csvData.append(columnHeaders.joinToString(","))
+csvData.append("\n")
+
+val gson = Gson()
+val advice: Advice = gson.fromJson(inputJsonFile.readLines().first(), Advice::class.java)
+
+//list of projects we want to file issues for
+//val androidxProjects = listOf("lint", "lint-checks", "buildSrc-tests", "androidx-demos", "stableaidl", "test")
+//val flanProjects = listOf("activity", "fragment", "lifecycle", "navigation")
+
+var numProjects = 0
+advice.projectAdvice.forEach projectAdvice@{ projectAdvice ->
+    val projectPath = projectAdvice.projectPath
+    val title = "Please fix misconfigured dependencies for $projectPath"
+
+    val project = projectPath.split(":")[1]
+
+//    Uncomment the following section if you want to create bugs for specific projects
+//    if(project !in flanProjects) {
+//        return@projectAdvice
+//    }
+
+    val description = StringBuilder()
+    description.appendLine(
+        "The dependency analysis gradle plugin found some dependencies that may have been " +
+            "misconfigured. Please fix the following dependencies: \n"
+    )
+
+    val unused = mutableSetOf<String>()
+    val transitive = mutableSetOf<String>()
+    val modified = mutableSetOf<String>()
+    projectAdvice.dependencyAdvice.forEach { dependencyAdvice ->
+        val fromConfiguration = dependencyAdvice.fromConfiguration
+        val toConfiguration = dependencyAdvice.toConfiguration
+        val coordinates = dependencyAdvice.coordinates
+        val resolvedVersion = coordinates.resolvedVersion
+
+        val isCompileOnly = toConfiguration?.endsWith("compileOnly", ignoreCase = true) == true
+        val isModifyDependencyAdvice = fromConfiguration != null && toConfiguration != null
+        val isTransitiveDependencyAdvice = fromConfiguration == null && toConfiguration != null && !isCompileOnly
+        val isUnusedDependencyAdvice = fromConfiguration != null && toConfiguration == null
+
+        var identifier = if(resolvedVersion == null) {
+            "'${coordinates.identifier}'"
+        } else {
+            "'${coordinates.identifier}:${coordinates.resolvedVersion}'"
+        }
+        if (coordinates.type == "project") {
+            identifier = "project($identifier)"
+        }
+        if (isModifyDependencyAdvice) {
+            modified.add("$toConfiguration($identifier) (was $fromConfiguration)")
+        }
+        if(isTransitiveDependencyAdvice) {
+            transitive.add("$toConfiguration($identifier)")
+        }
+        if(isUnusedDependencyAdvice) {
+            unused.add("$fromConfiguration($identifier)")
+        }
+    }
+
+    if(unused.isNotEmpty()) {
+        description.appendLine("Unused dependencies which should be removed:")
+        description.appendLine("```")
+        description.appendLine(unused.sorted().joinToString(separator = "\n"))
+        description.appendLine("```")
+
+    }
+    if (transitive.isNotEmpty()) {
+        description.appendLine("These transitive dependencies can be declared directly:")
+        description.appendLine("```")
+        description.appendLine(transitive.sorted().joinToString(separator = "\n"))
+        description.appendLine("```")
+    }
+    if (modified.isNotEmpty()) {
+        description.appendLine(
+            "These dependencies can be modified to be as indicated. Please be careful " +
+                "while changing the type of dependencies since it can affect the consumers of " +
+                "this library. To learn more about the various dependency configurations, " +
+                "please visit: [dac]" +
+                "(https://developer.android.com/build/dependencies#dependency_configurations). " +
+                "Also check [Gradle's guide for dependency management]" +
+                "(https://docs.gradle.org/current/userguide/dependency_management.html).\n"
+        )
+        description.appendLine("```")
+        description.appendLine(modified.sorted().joinToString(separator = "\n"))
+        description.appendLine("```")
+    }
+
+    description.appendLine("To get more up-to-date project advice, please run:")
+    description.appendLine("```")
+    description.appendLine("./gradlew $projectPath:projectHealth")
+    description.appendLine("```")
+    val newColumns = listOf(
+        "NEW00000", // ID
+        "P2", // priority
+        title,
+        "=HYPERLINK(\"https://issuetracker.google.com/issues?q=status%3Aopen%20hotlistid%3A(5997499)\", \"Androidx misconfigured dependencies\")",
+        "", // Assignee: leave blank
+        "Assigned", // status
+        "Android > Android OS & Apps > Jetpack (androidx) > ${project.replaceFirstChar {
+            if (it.isLowerCase()) it.titlecase(
+                Locale.getDefault()
+            ) else it.toString()
+        }}",
+        "", // reporter: add your ldap here
+        description.toString()
+    )
+
+    if (projectAdvice.dependencyAdvice.isNotEmpty()) {
+        numProjects++
+        csvData.append(newColumns.joinToString(",") { data ->
+            "\"${data.replace("\"", "\"\"")}\""
+        })
+        csvData.append("\n")
+    }
+}
+
+csvOutputFile.appendText(csvData.toString())
+println("Wrote CSV output to ${csvOutputFile.path} for $numProjects projects")
+
+data class Advice(
+    val projectAdvice: List<ProjectAdvice>,
+)
+
+data class ProjectAdvice(
+    val projectPath: String,
+    val dependencyAdvice: List<DependencyAdvice>,
+    val pluginAdvice: List<PluginAdvice>,
+)
+
+data class DependencyAdvice(
+    val coordinates: Coordinates,
+    val fromConfiguration: String?,
+    val toConfiguration: String?
+)
+
+data class Coordinates(
+    val type: String,
+    val identifier: String,
+    val resolvedVersion: String?
+)
+
+data class PluginAdvice(
+    val redundantPlugin: String,
+    val reason: String
+)
diff --git a/development/build_log_simplifier/messages.ignore b/development/build_log_simplifier/messages.ignore
index d1d312b..0a37038 100644
--- a/development/build_log_simplifier/messages.ignore
+++ b/development/build_log_simplifier/messages.ignore
@@ -274,7 +274,7 @@
 # Linux builds cannot build mac, hence we get this warning.
 # see: https://github.com/JetBrains/kotlin/blob/master/native/commonizer/README.md
 # This warning is printed from: https://github.com/JetBrains/kotlin/blob/bc853e45e8982eff74e3263b0197c1af6086615d/native/commonizer/src/org/jetbrains/kotlin/commonizer/konan/LibraryCommonizer.kt#L41
-Warning\: No libraries found for target (macos|ios|ios_simulator)_(arm|x)[0-9]+\. This target will be excluded from commonization\.
+Warning\: No libraries found for target (macos|ios|ios_simulator|tvos|tvos_simulator|watchos|watchos_simulator)_(arm|x)[0-9]+\. This target will be excluded from commonization\.
 # > Task :compose:ui:ui:testDebugUnitTest
 (OpenJDK 64\-Bit Server VM warning:.*|.*Sharing is only supported for boot loader classes because bootstrap classpath has been appended)
 # KMP messages on successful XCFramework builds.
@@ -300,9 +300,11 @@
 i: \[ksp\] loaded provider\(s\): \[androidx\.room\.RoomKspProcessor\$Provider\]
 # buildPrivacySandboxSdkApksForDebug (b/329101823)
 Extracted sandbox SDK APK for.*
-# > Task :appcompat:appcompat:findDeclaredProcsDebug
-Could not reflectively access processor class 'androidx\.resourceinspection\.processor\.ResourceInspectionProcessor'
-# > Task :buildHealth
-There were dependency violations\. See report at file://\$OUT_DIR/androidx/build/reports/dependency\-analysis/build\-health\-report\.txt
 # Building XCFrameworks (b/260140834) and iOS benchmark invocation
-.*xcodebuild.*
\ No newline at end of file
+.*xcodebuild.*
+# > Task :benchmark:benchmark-darwin-samples:assembleAndroidXDarwinBenchmarksReleaseXCFramework
+objc\[[0-9]+\]: Class AMSupportURLConnectionDelegate is implemented in both /usr/lib/libauthinstall\.dylib \([0-9]+x[0-9]+f[0-9]+cf[0-9]+e[0-9]+\) and /System/Library/PrivateFrameworks/MobileDevice\.framework/Versions/A/MobileDevice \([0-9]+x[0-9]+e[0-9]+bc[0-9]+c[0-9]+\)\. One of the two will be used\. Which one is undefined\.
+objc\[[0-9]+\]: Class AMSupportURLSession is implemented in both /usr/lib/libauthinstall\.dylib \([0-9]+x[0-9]+f[0-9]+cf[0-9]+\) and /System/Library/PrivateFrameworks/MobileDevice\.framework/Versions/A/MobileDevice \([0-9]+x[0-9]+e[0-9]+bc[0-9]+\)\. One of the two will be used\. Which one is undefined\.
+# > Task :collection:collection-benchmark:assembleAndroidXDarwinBenchmarksReleaseXCFramework
+objc\[[0-9]+\]: Class AMSupportURLConnectionDelegate is implemented in both /usr/lib/libauthinstall\.dylib \([0-9]+x[0-9]+f[0-9]+cf[0-9]+e[0-9]+\) and /System/Library/PrivateFrameworks/MobileDevice\.framework/Versions/A/MobileDevice \([0-9]+x[0-9]+c[0-9]+c[0-9]+\)\. One of the two will be used\. Which one is undefined\.
+objc\[[0-9]+\]: Class AMSupportURLSession is implemented in both /usr/lib/libauthinstall\.dylib \([0-9]+x[0-9]+f[0-9]+cf[0-9]+\) and /System/Library/PrivateFrameworks/MobileDevice\.framework/Versions/A/MobileDevice \([0-9]+x[0-9]+c[0-9]+\)\. One of the two will be used\. Which one is undefined\.
\ No newline at end of file
diff --git a/development/importMaven/build.gradle.kts b/development/importMaven/build.gradle.kts
index 86205a6..7f33326 100644
--- a/development/importMaven/build.gradle.kts
+++ b/development/importMaven/build.gradle.kts
@@ -42,12 +42,15 @@
 }
 
 java {
+    sourceCompatibility = JavaVersion.VERSION_17
+    targetCompatibility = JavaVersion.VERSION_17
     sourceSets {
         main {
             resources.srcDir(createPropertiesResourceDirectoryTask.map { it.destinationDir })
         }
     }
 }
+tasks.withType(KotlinCompile::class.java).configureEach { kotlinOptions { jvmTarget = "17" } }
 
 dependencies {
     implementation(libs.kotlinGradlePluginz)
@@ -64,6 +67,7 @@
     testImplementation(importMavenLibs.okioFakeFilesystem)
 }
 
+
 // b/250726951 Gradle ProjectBuilder needs reflection access to java.lang.
 val jvmAddOpensArgs = listOf("--add-opens=java.base/java.lang=ALL-UNNAMED")
 tasks.withType<Test>() {
diff --git a/development/importMaven/gradlew b/development/importMaven/gradlew
deleted file mode 120000
index d9f055c..0000000
--- a/development/importMaven/gradlew
+++ /dev/null
@@ -1 +0,0 @@
-../../playground-common/gradlew
\ No newline at end of file
diff --git a/development/importMaven/gradlew b/development/importMaven/gradlew
new file mode 100755
index 0000000..23c0ca8
--- /dev/null
+++ b/development/importMaven/gradlew
@@ -0,0 +1,256 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# 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
+#
+#      https://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.
+#
+
+##############################################################################
+#
+#   Gradle start up script for POSIX generated by Gradle.
+#
+#   Important for running:
+#
+#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+#       noncompliant, but you have some other compliant shell such as ksh or
+#       bash, then to run this script, type that shell name before the whole
+#       command line, like:
+#
+#           ksh Gradle
+#
+#       Busybox and similar reduced shells will NOT work, because this script
+#       requires all of these POSIX shell features:
+#         * functions;
+#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+#         * compound commands having a testable exit status, especially «case»;
+#         * various built-in commands including «command», «set», and «ulimit».
+#
+#   Important for patching:
+#
+#   (2) This script targets any POSIX shell, so it avoids extensions provided
+#       by Bash, Ksh, etc; in particular arrays are avoided.
+#
+#       The "traditional" practice of packing multiple parameters into a
+#       space-separated string is a well documented source of bugs and security
+#       problems, so this is (mostly) avoided, by progressively accumulating
+#       options in "$@", and eventually passing that to Java.
+#
+#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+#       see the in-line comments for details.
+#
+#       There are tweaks for specific operating systems such as AIX, CygWin,
+#       Darwin, MinGW, and NonStop.
+#
+#   (3) This script is generated from the Groovy template
+#       https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+#       within the Gradle project.
+#
+#       You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+    APP_HOME=${app_path%"${app_path##*/}"}  # leaves a trailing /; empty if no leading path
+    [ -h "$app_path" ]
+do
+    ls=$( ls -ld "$app_path" )
+    link=${ls#*' -> '}
+    case $link in             #(
+      /*)   app_path=$link ;; #(
+      *)    app_path=$APP_HOME$link ;;
+    esac
+done
+
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+
+APP_NAME="Gradle"
+APP_BASE_NAME=${0##*/}
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+    echo "$*"
+} >&2
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in                #(
+  CYGWIN* )         cygwin=true  ;; #(
+  Darwin* )         darwin=true  ;; #(
+  MSYS* | MINGW* )  msys=true    ;; #(
+  NONSTOP* )        nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# override JAVA_HOME, because CI machines have it and it points to very old JDK
+platform_suffix="x86"
+case "$(arch)" in
+  arm64* )
+    platform_suffix="arm64"
+esac
+
+# Pick the correct fullsdk for this OS.
+if [ $darwin == "true" ]; then
+    plat="darwin"
+else
+    plat="linux"
+fi
+
+export ANDROIDX_JDK21="$APP_HOME/../../../../prebuilts/jdk/jdk21/$plat-$platform_suffix"
+export JAVA_HOME=$ANDROIDX_JDK21
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD=$JAVA_HOME/jre/sh/java
+    else
+        JAVACMD=$JAVA_HOME/bin/java
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD=java
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+    case $MAX_FD in #(
+      max*)
+        MAX_FD=$( ulimit -H -n ) ||
+            warn "Could not query maximum file descriptor limit"
+    esac
+    case $MAX_FD in  #(
+      '' | soft) :;; #(
+      *)
+        ulimit -n "$MAX_FD" ||
+            warn "Could not set maximum file descriptor limit to $MAX_FD"
+    esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+#   * args from the command line
+#   * the main class name
+#   * -classpath
+#   * -D...appname settings
+#   * --module-path (only if needed)
+#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+    APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+    CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+    JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    for arg do
+        if
+            case $arg in                                #(
+              -*)   false ;;                            # don't mess with options #(
+              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath
+                    [ -e "$t" ] ;;                      #(
+              *)    false ;;
+            esac
+        then
+            arg=$( cygpath --path --ignore --mixed "$arg" )
+        fi
+        # Roll the args list around exactly as many times as the number of
+        # args, so each arg winds up back in the position where it started, but
+        # possibly modified.
+        #
+        # NB: a `for` loop captures its iteration list before it begins, so
+        # changing the positional parameters here affects neither the number of
+        # iterations, nor the values presented in `arg`.
+        shift                   # remove old arg
+        set -- "$@" "$arg"      # push replacement arg
+    done
+fi
+
+# Collect all arguments for the java command;
+#   * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+#     shell script including quotes and variable substitutions, so put them in
+#     double quotes to make sure that they get re-expanded; and
+#   * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+        "-Dorg.gradle.appname=$APP_BASE_NAME" \
+        -classpath "$CLASSPATH" \
+        org.gradle.wrapper.GradleWrapperMain \
+        "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+    die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+#   readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+#   set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+        printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+        xargs -n1 |
+        sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+        tr '\n' ' '
+    )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/development/importMaven/src/main/kotlin/androidx/build/importMaven/KmpConfig.kt b/development/importMaven/src/main/kotlin/androidx/build/importMaven/KmpConfig.kt
index 12aea87..33ba831 100644
--- a/development/importMaven/src/main/kotlin/androidx/build/importMaven/KmpConfig.kt
+++ b/development/importMaven/src/main/kotlin/androidx/build/importMaven/KmpConfig.kt
@@ -2,35 +2,38 @@
 
 import org.jetbrains.kotlin.konan.target.KonanTarget
 
-/**
- * Common configuration for KMP builds.
- */
+/** Common configuration for KMP builds. */
 internal object KmpConfig {
-    /**
-     * host machines where we support compiling KMP
-     */
-    val SUPPORTED_HOSTS = listOf(
-        KonanTarget.LINUX_X64,
-        KonanTarget.MACOS_ARM64,
-        KonanTarget.MACOS_X64,
-    )
+    /** host machines where we support compiling KMP */
+    val SUPPORTED_HOSTS =
+        listOf(
+            KonanTarget.LINUX_X64,
+            KonanTarget.MACOS_ARM64,
+            KonanTarget.MACOS_X64,
+        )
 
-    /**
-     * Supported konan targets
-     */
-    val SUPPORTED_KONAN_TARGETS = listOf(
-        KonanTarget.MACOS_ARM64,
-        KonanTarget.MACOS_X64,
-        KonanTarget.LINUX_ARM64,
-        KonanTarget.LINUX_X64,
-        KonanTarget.MINGW_X64,
-        KonanTarget.MINGW_X86,
-        KonanTarget.IOS_ARM64,
-        KonanTarget.IOS_SIMULATOR_ARM64,
-        KonanTarget.IOS_X64,
-        KonanTarget.ANDROID_X86,
-        KonanTarget.ANDROID_X64,
-        KonanTarget.ANDROID_ARM32,
-        KonanTarget.ANDROID_ARM64,
-    )
-}
\ No newline at end of file
+    /** Supported konan targets */
+    val SUPPORTED_KONAN_TARGETS =
+        listOf(
+            KonanTarget.MACOS_ARM64,
+            KonanTarget.MACOS_X64,
+            KonanTarget.LINUX_ARM64,
+            KonanTarget.LINUX_X64,
+            KonanTarget.MINGW_X64,
+            KonanTarget.MINGW_X86,
+            KonanTarget.IOS_ARM64,
+            KonanTarget.IOS_SIMULATOR_ARM64,
+            KonanTarget.IOS_X64,
+            KonanTarget.WATCHOS_ARM32,
+            KonanTarget.WATCHOS_ARM64,
+            KonanTarget.WATCHOS_SIMULATOR_ARM64,
+            KonanTarget.WATCHOS_X64,
+            KonanTarget.TVOS_ARM64,
+            KonanTarget.TVOS_SIMULATOR_ARM64,
+            KonanTarget.TVOS_X64,
+            KonanTarget.ANDROID_X86,
+            KonanTarget.ANDROID_X64,
+            KonanTarget.ANDROID_ARM32,
+            KonanTarget.ANDROID_ARM64,
+        )
+}
diff --git a/development/update_studio.sh b/development/update_studio.sh
index 3ead3d7..b1c814e 100755
--- a/development/update_studio.sh
+++ b/development/update_studio.sh
@@ -7,8 +7,8 @@
 
 # Versions that the user should update when running this script
 echo Getting Studio version and link
-AGP_VERSION=${1:-8.6.0-alpha05}
-STUDIO_VERSION_STRING=${2:-"Android Studio Koala Feature Drop | 2024.1.2 Canary 5"}
+AGP_VERSION=${1:-8.6.0-alpha07}
+STUDIO_VERSION_STRING=${2:-"Android Studio Koala Feature Drop | 2024.1.2 Canary 7"}
 
 # Get studio version number from version name
 STUDIO_IFRAME_LINK=`curl "https://developer.android.com/studio/archive.html" | grep "<iframe " | sed "s/.* src=\"\([^\"]*\)\".*/\1/g"`
diff --git a/docs-public/build.gradle b/docs-public/build.gradle
index 71157c1..66a9dd9 100644
--- a/docs-public/build.gradle
+++ b/docs-public/build.gradle
@@ -15,14 +15,14 @@
 }
 
 dependencies {
-    docs("androidx.activity:activity:1.9.0")
-    docs("androidx.activity:activity-compose:1.9.0")
-    docs("androidx.activity:activity-ktx:1.9.0")
+    docs("androidx.activity:activity:1.10.0-alpha01")
+    docs("androidx.activity:activity-compose:1.10.0-alpha01")
+    docs("androidx.activity:activity-ktx:1.10.0-alpha01")
     // ads-identifier is deprecated
     docsWithoutApiSince("androidx.ads:ads-identifier:1.0.0-alpha05")
     docsWithoutApiSince("androidx.ads:ads-identifier-common:1.0.0-alpha05")
     docsWithoutApiSince("androidx.ads:ads-identifier-provider:1.0.0-alpha05")
-    kmpDocs("androidx.annotation:annotation:1.8.0-rc01")
+    kmpDocs("androidx.annotation:annotation:1.9.0-alpha01")
     docs("androidx.annotation:annotation-experimental:1.4.1")
     docs("androidx.appcompat:appcompat:1.7.0")
     docs("androidx.appcompat:appcompat-resources:1.7.0")
@@ -59,49 +59,48 @@
     docs("androidx.camera:camera-viewfinder:1.4.0-alpha07")
     docs("androidx.camera:camera-viewfinder-compose:1.4.0-alpha03")
     docs("androidx.camera:camera-viewfinder-core:1.4.0-alpha07")
-    docs("androidx.car.app:app:1.7.0-alpha02")
-    docs("androidx.car.app:app-automotive:1.7.0-alpha02")
-    docs("androidx.car.app:app-projected:1.7.0-alpha02")
-    docs("androidx.car.app:app-testing:1.7.0-alpha02")
+    docs("androidx.car.app:app:1.7.0-beta01")
+    docs("androidx.car.app:app-automotive:1.7.0-beta01")
+    docs("androidx.car.app:app-projected:1.7.0-beta01")
+    docs("androidx.car.app:app-testing:1.7.0-beta01")
     docs("androidx.cardview:cardview:1.0.0")
     kmpDocs("androidx.collection:collection:1.4.0")
     docs("androidx.collection:collection-ktx:1.4.0-rc01")
-    kmpDocs("androidx.compose.animation:animation:1.7.0-beta03")
-    kmpDocs("androidx.compose.animation:animation-core:1.7.0-beta03")
-    kmpDocs("androidx.compose.animation:animation-graphics:1.7.0-beta03")
-    kmpDocs("androidx.compose.foundation:foundation:1.7.0-beta03")
-    kmpDocs("androidx.compose.foundation:foundation-layout:1.7.0-beta03")
-    kmpDocs("androidx.compose.material3.adaptive:adaptive:1.0.0-beta03")
-    kmpDocs("androidx.compose.material3.adaptive:adaptive-layout:1.0.0-beta03")
-    kmpDocs("androidx.compose.material3.adaptive:adaptive-navigation:1.0.0-beta03")
-    kmpDocs("androidx.compose.material3:material3:1.3.0-beta03")
-    kmpDocs("androidx.compose.material3:material3-adaptive-navigation-suite:1.3.0-beta03")
+    kmpDocs("androidx.compose.animation:animation:1.7.0-beta04")
+    kmpDocs("androidx.compose.animation:animation-core:1.7.0-beta04")
+    kmpDocs("androidx.compose.animation:animation-graphics:1.7.0-beta04")
+    kmpDocs("androidx.compose.foundation:foundation:1.7.0-beta04")
+    kmpDocs("androidx.compose.foundation:foundation-layout:1.7.0-beta04")
+    kmpDocs("androidx.compose.material3.adaptive:adaptive:1.0.0-beta04")
+    kmpDocs("androidx.compose.material3.adaptive:adaptive-layout:1.0.0-beta04")
+    kmpDocs("androidx.compose.material3.adaptive:adaptive-navigation:1.0.0-beta04")
+    kmpDocs("androidx.compose.material3:material3:1.3.0-beta04")
+    kmpDocs("androidx.compose.material3:material3-adaptive-navigation-suite:1.3.0-beta04")
     kmpDocs("androidx.compose.material3:material3-common:1.0.0-alpha01")
-    kmpDocs("androidx.compose.material3:material3-window-size-class:1.3.0-beta03")
-    kmpDocs("androidx.compose.material:material:1.7.0-beta03")
-    kmpDocs("androidx.compose.material:material-icons-core:1.7.0-beta03")
+    kmpDocs("androidx.compose.material3:material3-window-size-class:1.3.0-beta04")
+    kmpDocs("androidx.compose.material:material:1.7.0-beta04")
+    kmpDocs("androidx.compose.material:material-icons-core:1.7.0-beta04")
     docs("androidx.compose.material:material-navigation:1.7.0-beta03")
-    kmpDocs("androidx.compose.material:material-ripple:1.7.0-beta03")
-    kmpDocs("androidx.compose.runtime:runtime:1.7.0-beta03")
-    docs("androidx.compose.runtime:runtime-livedata:1.7.0-beta03")
-    docs("androidx.compose.runtime:runtime-rxjava2:1.7.0-beta03")
-    docs("androidx.compose.runtime:runtime-rxjava3:1.7.0-beta03")
-    kmpDocs("androidx.compose.runtime:runtime-saveable:1.7.0-beta03")
+    kmpDocs("androidx.compose.material:material-ripple:1.7.0-beta04")
+    kmpDocs("androidx.compose.runtime:runtime:1.7.0-beta04")
+    docs("androidx.compose.runtime:runtime-livedata:1.7.0-beta04")
+    docs("androidx.compose.runtime:runtime-rxjava2:1.7.0-beta04")
+    docs("androidx.compose.runtime:runtime-rxjava3:1.7.0-beta04")
+    kmpDocs("androidx.compose.runtime:runtime-saveable:1.7.0-beta04")
     docs("androidx.compose.runtime:runtime-tracing:1.0.0-beta01")
-    kmpDocs("androidx.compose.ui:ui:1.7.0-beta03")
-    docs("androidx.compose.ui:ui-android-stubs:1.7.0-beta03")
-    kmpDocs("androidx.compose.ui:ui-geometry:1.7.0-beta03")
-    kmpDocs("androidx.compose.ui:ui-graphics:1.7.0-beta03")
-    kmpDocs("androidx.compose.ui:ui-test:1.7.0-beta03")
-    kmpDocs("androidx.compose.ui:ui-test-junit4:1.7.0-beta03")
-    kmpDocs("androidx.compose.ui:ui-text:1.7.0-beta03")
-    docs("androidx.compose.ui:ui-text-google-fonts:1.7.0-beta03")
-    kmpDocs("androidx.compose.ui:ui-tooling:1.7.0-beta03")
-    kmpDocs("androidx.compose.ui:ui-tooling-data:1.7.0-beta03")
-    kmpDocs("androidx.compose.ui:ui-tooling-preview:1.7.0-beta03")
-    kmpDocs("androidx.compose.ui:ui-unit:1.7.0-beta03")
-    kmpDocs("androidx.compose.ui:ui-util:1.7.0-beta01")
-    docs("androidx.compose.ui:ui-viewbinding:1.7.0-beta03")
+    kmpDocs("androidx.compose.ui:ui:1.7.0-beta04")
+    kmpDocs("androidx.compose.ui:ui-geometry:1.7.0-beta04")
+    kmpDocs("androidx.compose.ui:ui-graphics:1.7.0-beta04")
+    kmpDocs("androidx.compose.ui:ui-test:1.7.0-beta04")
+    kmpDocs("androidx.compose.ui:ui-test-junit4:1.7.0-beta04")
+    kmpDocs("androidx.compose.ui:ui-text:1.7.0-beta04")
+    docs("androidx.compose.ui:ui-text-google-fonts:1.7.0-beta04")
+    kmpDocs("androidx.compose.ui:ui-tooling:1.7.0-beta04")
+    kmpDocs("androidx.compose.ui:ui-tooling-data:1.7.0-beta04")
+    kmpDocs("androidx.compose.ui:ui-tooling-preview:1.7.0-beta04")
+    kmpDocs("androidx.compose.ui:ui-unit:1.7.0-beta04")
+    kmpDocs("androidx.compose.ui:ui-util:1.7.0-beta04")
+    docs("androidx.compose.ui:ui-viewbinding:1.7.0-beta04")
     docs("androidx.concurrent:concurrent-futures:1.2.0")
     docs("androidx.concurrent:concurrent-futures-ktx:1.2.0")
     docs("androidx.constraintlayout:constraintlayout:2.2.0-alpha13")
@@ -161,10 +160,10 @@
     docs("androidx.enterprise:enterprise-feedback:1.1.0")
     docs("androidx.enterprise:enterprise-feedback-testing:1.1.0")
     docs("androidx.exifinterface:exifinterface:1.3.6")
-    docs("androidx.fragment:fragment:1.8.0")
-    docs("androidx.fragment:fragment-compose:1.8.0")
-    docs("androidx.fragment:fragment-ktx:1.8.0")
-    docs("androidx.fragment:fragment-testing:1.8.0")
+    docs("androidx.fragment:fragment:1.8.1")
+    docs("androidx.fragment:fragment-compose:1.8.1")
+    docs("androidx.fragment:fragment-ktx:1.8.1")
+    docs("androidx.fragment:fragment-testing:1.8.1")
     docs("androidx.glance:glance:1.1.0")
     docs("androidx.glance:glance-appwidget:1.1.0")
     docs("androidx.glance:glance-appwidget-preview:1.1.0")
@@ -224,47 +223,47 @@
     docs("androidx.media2:media2-widget:1.3.0")
     docs("androidx.media:media:1.7.0")
     // androidx.media3 is not hosted in androidx
-    docsWithoutApiSince("androidx.media3:media3-cast:1.4.0-alpha02")
-    docsWithoutApiSince("androidx.media3:media3-common:1.4.0-alpha02")
-    docsWithoutApiSince("androidx.media3:media3-container:1.4.0-alpha02")
-    docsWithoutApiSince("androidx.media3:media3-database:1.4.0-alpha02")
-    docsWithoutApiSince("androidx.media3:media3-datasource:1.4.0-alpha02")
-    docsWithoutApiSince("androidx.media3:media3-datasource-cronet:1.4.0-alpha02")
-    docsWithoutApiSince("androidx.media3:media3-datasource-okhttp:1.4.0-alpha02")
-    docsWithoutApiSince("androidx.media3:media3-datasource-rtmp:1.4.0-alpha02")
-    docsWithoutApiSince("androidx.media3:media3-decoder:1.4.0-alpha02")
-    docsWithoutApiSince("androidx.media3:media3-effect:1.4.0-alpha02")
-    docsWithoutApiSince("androidx.media3:media3-exoplayer:1.4.0-alpha02")
-    docsWithoutApiSince("androidx.media3:media3-exoplayer-dash:1.4.0-alpha02")
-    docsWithoutApiSince("androidx.media3:media3-exoplayer-hls:1.4.0-alpha02")
-    docsWithoutApiSince("androidx.media3:media3-exoplayer-ima:1.4.0-alpha02")
-    docsWithoutApiSince("androidx.media3:media3-exoplayer-rtsp:1.4.0-alpha02")
-    docsWithoutApiSince("androidx.media3:media3-exoplayer-smoothstreaming:1.4.0-alpha02")
-    docsWithoutApiSince("androidx.media3:media3-exoplayer-workmanager:1.4.0-alpha02")
-    docsWithoutApiSince("androidx.media3:media3-extractor:1.4.0-alpha02")
-    docsWithoutApiSince("androidx.media3:media3-muxer:1.4.0-alpha02")
-    docsWithoutApiSince("androidx.media3:media3-session:1.4.0-alpha02")
-    docsWithoutApiSince("androidx.media3:media3-test-utils:1.4.0-alpha02")
-    docsWithoutApiSince("androidx.media3:media3-test-utils-robolectric:1.4.0-alpha02")
-    docsWithoutApiSince("androidx.media3:media3-transformer:1.4.0-alpha02")
-    docsWithoutApiSince("androidx.media3:media3-ui:1.4.0-alpha02")
-    docsWithoutApiSince("androidx.media3:media3-ui-leanback:1.4.0-alpha02")
+    docsWithoutApiSince("androidx.media3:media3-cast:1.4.0-rc01")
+    docsWithoutApiSince("androidx.media3:media3-common:1.4.0-rc01")
+    docsWithoutApiSince("androidx.media3:media3-container:1.4.0-rc01")
+    docsWithoutApiSince("androidx.media3:media3-database:1.4.0-rc01")
+    docsWithoutApiSince("androidx.media3:media3-datasource:1.4.0-rc01")
+    docsWithoutApiSince("androidx.media3:media3-datasource-cronet:1.4.0-rc01")
+    docsWithoutApiSince("androidx.media3:media3-datasource-okhttp:1.4.0-rc01")
+    docsWithoutApiSince("androidx.media3:media3-datasource-rtmp:1.4.0-rc01")
+    docsWithoutApiSince("androidx.media3:media3-decoder:1.4.0-rc01")
+    docsWithoutApiSince("androidx.media3:media3-effect:1.4.0-rc01")
+    docsWithoutApiSince("androidx.media3:media3-exoplayer:1.4.0-rc01")
+    docsWithoutApiSince("androidx.media3:media3-exoplayer-dash:1.4.0-rc01")
+    docsWithoutApiSince("androidx.media3:media3-exoplayer-hls:1.4.0-rc01")
+    docsWithoutApiSince("androidx.media3:media3-exoplayer-ima:1.4.0-rc01")
+    docsWithoutApiSince("androidx.media3:media3-exoplayer-rtsp:1.4.0-rc01")
+    docsWithoutApiSince("androidx.media3:media3-exoplayer-smoothstreaming:1.4.0-rc01")
+    docsWithoutApiSince("androidx.media3:media3-exoplayer-workmanager:1.4.0-rc01")
+    docsWithoutApiSince("androidx.media3:media3-extractor:1.4.0-rc01")
+    docsWithoutApiSince("androidx.media3:media3-muxer:1.4.0-rc01")
+    docsWithoutApiSince("androidx.media3:media3-session:1.4.0-rc01")
+    docsWithoutApiSince("androidx.media3:media3-test-utils:1.4.0-rc01")
+    docsWithoutApiSince("androidx.media3:media3-test-utils-robolectric:1.4.0-rc01")
+    docsWithoutApiSince("androidx.media3:media3-transformer:1.4.0-rc01")
+    docsWithoutApiSince("androidx.media3:media3-ui:1.4.0-rc01")
+    docsWithoutApiSince("androidx.media3:media3-ui-leanback:1.4.0-rc01")
     docs("androidx.mediarouter:mediarouter:1.7.0")
     docs("androidx.mediarouter:mediarouter-testing:1.7.0")
     docs("androidx.metrics:metrics-performance:1.0.0-beta01")
-    docs("androidx.navigation:navigation-common:2.8.0-beta03")
-    docs("androidx.navigation:navigation-common-ktx:2.8.0-beta03")
-    docs("androidx.navigation:navigation-compose:2.8.0-beta03")
-    docs("androidx.navigation:navigation-dynamic-features-fragment:2.8.0-beta03")
-    docs("androidx.navigation:navigation-dynamic-features-runtime:2.8.0-beta03")
-    docs("androidx.navigation:navigation-fragment:2.8.0-beta03")
-    docs("androidx.navigation:navigation-fragment-compose:2.8.0-beta03")
-    docs("androidx.navigation:navigation-fragment-ktx:2.8.0-beta03")
-    docs("androidx.navigation:navigation-runtime:2.8.0-beta03")
-    docs("androidx.navigation:navigation-runtime-ktx:2.8.0-beta03")
-    docs("androidx.navigation:navigation-testing:2.8.0-beta03")
-    docs("androidx.navigation:navigation-ui:2.8.0-beta03")
-    docs("androidx.navigation:navigation-ui-ktx:2.8.0-beta03")
+    docs("androidx.navigation:navigation-common:2.8.0-beta04")
+    docs("androidx.navigation:navigation-common-ktx:2.8.0-beta04")
+    docs("androidx.navigation:navigation-compose:2.8.0-beta04")
+    docs("androidx.navigation:navigation-dynamic-features-fragment:2.8.0-beta04")
+    docs("androidx.navigation:navigation-dynamic-features-runtime:2.8.0-beta04")
+    docs("androidx.navigation:navigation-fragment:2.8.0-beta04")
+    docs("androidx.navigation:navigation-fragment-compose:2.8.0-beta04")
+    docs("androidx.navigation:navigation-fragment-ktx:2.8.0-beta04")
+    docs("androidx.navigation:navigation-runtime:2.8.0-beta04")
+    docs("androidx.navigation:navigation-runtime-ktx:2.8.0-beta04")
+    docs("androidx.navigation:navigation-testing:2.8.0-beta04")
+    docs("androidx.navigation:navigation-ui:2.8.0-beta04")
+    docs("androidx.navigation:navigation-ui-ktx:2.8.0-beta04")
     kmpDocs("androidx.paging:paging-common:3.3.0")
     docs("androidx.paging:paging-common-ktx:3.3.0")
     kmpDocs("androidx.paging:paging-compose:3.3.0")
@@ -284,15 +283,15 @@
     docs("androidx.privacysandbox.activity:activity-client:1.0.0-alpha01")
     docs("androidx.privacysandbox.activity:activity-core:1.0.0-alpha01")
     docs("androidx.privacysandbox.activity:activity-provider:1.0.0-alpha01")
-    docs("androidx.privacysandbox.ads:ads-adservices:1.1.0-beta07")
-    docs("androidx.privacysandbox.ads:ads-adservices-java:1.1.0-beta07")
+    docs("androidx.privacysandbox.ads:ads-adservices:1.1.0-beta08")
+    docs("androidx.privacysandbox.ads:ads-adservices-java:1.1.0-beta08")
     docs("androidx.privacysandbox.sdkruntime:sdkruntime-client:1.0.0-alpha13")
     docs("androidx.privacysandbox.sdkruntime:sdkruntime-core:1.0.0-alpha13")
     docs("androidx.privacysandbox.sdkruntime:sdkruntime-provider:1.0.0-alpha13")
-    docs("androidx.privacysandbox.tools:tools:1.0.0-alpha08")
-    docs("androidx.privacysandbox.ui:ui-client:1.0.0-alpha08")
-    docs("androidx.privacysandbox.ui:ui-core:1.0.0-alpha08")
-    docs("androidx.privacysandbox.ui:ui-provider:1.0.0-alpha08")
+    docs("androidx.privacysandbox.tools:tools:1.0.0-alpha09")
+    docs("androidx.privacysandbox.ui:ui-client:1.0.0-alpha09")
+    docs("androidx.privacysandbox.ui:ui-core:1.0.0-alpha09")
+    docs("androidx.privacysandbox.ui:ui-provider:1.0.0-alpha09")
     docs("androidx.profileinstaller:profileinstaller:1.4.0-alpha01")
     docs("androidx.recommendation:recommendation:1.0.0")
     docs("androidx.recyclerview:recyclerview:1.4.0-alpha01")
@@ -318,7 +317,7 @@
     docs("androidx.security:security-crypto:1.1.0-alpha06")
     docs("androidx.security:security-crypto-ktx:1.1.0-alpha06")
     docs("androidx.security:security-identity-credential:1.0.0-alpha03")
-    docs("androidx.security:security-state:1.0.0-alpha01")
+    docs("androidx.security:security-state:1.0.0-alpha02")
     docs("androidx.sharetarget:sharetarget:1.2.0")
     docs("androidx.slice:slice-builders:1.1.0-alpha02")
     docs("androidx.slice:slice-builders-ktx:1.0.0-alpha08")
@@ -332,28 +331,26 @@
     docs("androidx.startup:startup-runtime:1.2.0-alpha02")
     docs("androidx.swiperefreshlayout:swiperefreshlayout:1.2.0-alpha01")
     // androidx.test is not hosted in androidx
-    docsWithoutApiSince("androidx.test:core:1.6.0-rc01")
-    docsWithoutApiSince("androidx.test:core-ktx:1.6.0-rc01")
-    docsWithoutApiSince("androidx.test:monitor:1.7.0-rc01")
-    docsWithoutApiSince("androidx.test:rules:1.6.0-rc01")
-    docsWithoutApiSince("androidx.test:runner:1.6.0-rc01")
-    docsWithoutApiSince("androidx.test.espresso:espresso-accessibility:3.6.0-rc01")
-    docsWithoutApiSince("androidx.test.espresso:espresso-contrib:3.6.0-rc01")
-    docsWithoutApiSince("androidx.test.espresso:espresso-core:3.6.0-rc01")
-    docsWithoutApiSince("androidx.test.espresso:espresso-device:1.0.0-rc01")
-    docsWithoutApiSince("androidx.test.espresso:espresso-idling-resource:3.6.0-rc01")
-    docsWithoutApiSince("androidx.test.espresso:espresso-intents:3.6.0-rc01")
-    docsWithoutApiSince("androidx.test.espresso:espresso-remote:3.6.0-rc01")
-    docsWithoutApiSince("androidx.test.espresso:espresso-web:3.6.0-rc01")
-    docsWithoutApiSince("androidx.test.espresso.idling:idling-concurrent:3.6.0-rc01")
-    docsWithoutApiSince("androidx.test.espresso.idling:idling-net:3.6.0-rc01")
-    docsWithoutApiSince("androidx.test.ext:junit:1.2.0-rc01")
-    docsWithoutApiSince("androidx.test.ext:junit-ktx:1.2.0-rc01")
-    docsWithoutApiSince("androidx.test.ext:truth:1.6.0-rc01")
-    docsWithoutApiSince("androidx.test.services:storage:1.5.0-rc01")
-    docsWithoutApiSince("androidx.test.uiautomator:uiautomator:2.3.0")
-    // androidx.textclassifier is not hosted in androidx
-    docsWithoutApiSince("androidx.textclassifier:textclassifier:1.0.0-alpha04")
+    docsWithoutApiSince("androidx.test:core:1.6.1")
+    docsWithoutApiSince("androidx.test:core-ktx:1.6.1")
+    docsWithoutApiSince("androidx.test:monitor:1.7.1")
+    docsWithoutApiSince("androidx.test:rules:1.6.1")
+    docsWithoutApiSince("androidx.test:runner:1.6.1")
+    docsWithoutApiSince("androidx.test.espresso:espresso-accessibility:3.6.1")
+    docsWithoutApiSince("androidx.test.espresso:espresso-contrib:3.6.1")
+    docsWithoutApiSince("androidx.test.espresso:espresso-core:3.6.1")
+    docsWithoutApiSince("androidx.test.espresso:espresso-device:1.0.1")
+    docsWithoutApiSince("androidx.test.espresso:espresso-idling-resource:3.6.1")
+    docsWithoutApiSince("androidx.test.espresso:espresso-intents:3.6.1")
+    docsWithoutApiSince("androidx.test.espresso:espresso-remote:3.6.1")
+    docsWithoutApiSince("androidx.test.espresso:espresso-web:3.6.1")
+    docsWithoutApiSince("androidx.test.espresso.idling:idling-concurrent:3.6.1")
+    docsWithoutApiSince("androidx.test.espresso.idling:idling-net:3.6.1")
+    docsWithoutApiSince("androidx.test.ext:junit:1.2.1")
+    docsWithoutApiSince("androidx.test.ext:junit-ktx:1.2.1")
+    docsWithoutApiSince("androidx.test.ext:truth:1.6.0")
+    docsWithoutApiSince("androidx.test.services:storage:1.5.0")
+    docs("androidx.test.uiautomator:uiautomator:2.4.0-alpha01")
     docs("androidx.tracing:tracing:1.3.0-alpha02")
     docs("androidx.tracing:tracing-ktx:1.3.0-alpha02")
     docs("androidx.tracing:tracing-perfetto:1.0.0")
@@ -377,18 +374,18 @@
     docs("androidx.wear.compose:compose-material3:1.0.0-alpha23")
     docs("androidx.wear.compose:compose-navigation:1.4.0-beta03")
     docs("androidx.wear.compose:compose-ui-tooling:1.4.0-beta03")
-    docs("androidx.wear.protolayout:protolayout:1.2.0-alpha04")
-    docs("androidx.wear.protolayout:protolayout-expression:1.2.0-alpha04")
-    docs("androidx.wear.protolayout:protolayout-expression-pipeline:1.2.0-alpha04")
-    docs("androidx.wear.protolayout:protolayout-material:1.2.0-alpha04")
-    docs("androidx.wear.protolayout:protolayout-material-core:1.2.0-alpha04")
-    docs("androidx.wear.protolayout:protolayout-renderer:1.2.0-alpha04")
-    docs("androidx.wear.tiles:tiles:1.4.0-alpha04")
-    docs("androidx.wear.tiles:tiles-material:1.4.0-alpha04")
-    docs("androidx.wear.tiles:tiles-renderer:1.4.0-alpha04")
-    docs("androidx.wear.tiles:tiles-testing:1.4.0-alpha04")
-    docs("androidx.wear.tiles:tiles-tooling:1.4.0-alpha04")
-    docs("androidx.wear.tiles:tiles-tooling-preview:1.4.0-alpha04")
+    docs("androidx.wear.protolayout:protolayout:1.2.0-alpha05")
+    docs("androidx.wear.protolayout:protolayout-expression:1.2.0-alpha05")
+    docs("androidx.wear.protolayout:protolayout-expression-pipeline:1.2.0-alpha05")
+    docs("androidx.wear.protolayout:protolayout-material:1.2.0-alpha05")
+    docs("androidx.wear.protolayout:protolayout-material-core:1.2.0-alpha05")
+    docs("androidx.wear.protolayout:protolayout-renderer:1.2.0-alpha05")
+    docs("androidx.wear.tiles:tiles:1.4.0-alpha05")
+    docs("androidx.wear.tiles:tiles-material:1.4.0-alpha05")
+    docs("androidx.wear.tiles:tiles-renderer:1.4.0-alpha05")
+    docs("androidx.wear.tiles:tiles-testing:1.4.0-alpha05")
+    docs("androidx.wear.tiles:tiles-tooling:1.4.0-alpha05")
+    docs("androidx.wear.tiles:tiles-tooling-preview:1.4.0-alpha05")
     docs("androidx.wear.watchface:watchface:1.3.0-alpha03")
     docs("androidx.wear.watchface:watchface-client:1.3.0-alpha03")
     docs("androidx.wear.watchface:watchface-client-guava:1.3.0-alpha03")
diff --git a/docs-tip-of-tree/build.gradle b/docs-tip-of-tree/build.gradle
index acd2153..38c3dfb 100644
--- a/docs-tip-of-tree/build.gradle
+++ b/docs-tip-of-tree/build.gradle
@@ -98,7 +98,6 @@
     kmpDocs(project(":compose:runtime:runtime-saveable"))
     docs(project(":compose:runtime:runtime-tracing"))
     kmpDocs(project(":compose:ui:ui"))
-    docs(project(":compose:ui:ui-android-stubs"))
     kmpDocs(project(":compose:ui:ui-geometry"))
     kmpDocs(project(":compose:ui:ui-graphics"))
     kmpDocs(project(":compose:ui:ui-test"))
@@ -197,7 +196,7 @@
     docs(project(":hilt:hilt-navigation-compose"))
     docs(project(":hilt:hilt-navigation-fragment"))
     docs(project(":hilt:hilt-work"))
-    docs(project(":ink:ink-brush"))
+    kmpDocs(project(":ink:ink-brush"))
     docs(project(":input:input-motionprediction"))
     docs(project(":interpolator:interpolator"))
     docs(project(":javascriptengine:javascriptengine"))
@@ -285,7 +284,7 @@
     docs(project(":room:room-guava"))
     docs(project(":room:room-ktx"))
     kmpDocs(project(":room:room-migration"))
-    docs(project(":room:room-paging"))
+    kmpDocs(project(":room:room-paging"))
     docs(project(":room:room-paging-guava"))
     docs(project(":room:room-paging-rxjava2"))
     docs(project(":room:room-paging-rxjava3"))
diff --git a/docs/kmp_images/kmp_jetpad.png b/docs/kmp_images/kmp_jetpad.png
new file mode 100644
index 0000000..a96212a
--- /dev/null
+++ b/docs/kmp_images/kmp_jetpad.png
Binary files differ
diff --git a/docs/onboarding.md b/docs/onboarding.md
index 4ce677b..6355b24 100644
--- a/docs/onboarding.md
+++ b/docs/onboarding.md
@@ -1054,18 +1054,4 @@
 
 ### How do I enable MultiDex for my library?
 
-Go to your project/app level build.gradle file, and add
-
-```
-android {
-    defaultConfig {
-        multiDexEnabled = true
-    }
-}
-```
-
-as well as `androidTestImplementation(libs.multidex)` to the dependenices block.
-
-If you want it enabled for the application and not test APK, add
-`implementation(libs.multidex)` to the dependencies block instead. Any prior
-failures may not re-occur now that the software is multi-dexed. Rerun the build.
+It is enabled automatically as androidx minSdkVersion is API >=21.
diff --git a/emoji2/emoji2-bundled/api/1.5.0-beta01.txt b/emoji2/emoji2-bundled/api/1.5.0-beta01.txt
new file mode 100644
index 0000000..fab7dab
--- /dev/null
+++ b/emoji2/emoji2-bundled/api/1.5.0-beta01.txt
@@ -0,0 +1,10 @@
+// Signature format: 4.0
+package androidx.emoji2.bundled {
+
+  public class BundledEmojiCompatConfig extends androidx.emoji2.text.EmojiCompat.Config {
+    ctor @Deprecated public BundledEmojiCompatConfig(android.content.Context);
+    ctor public BundledEmojiCompatConfig(android.content.Context, java.util.concurrent.Executor);
+  }
+
+}
+
diff --git a/emoji2/emoji2-bundled/api/res-1.5.0-beta01.txt b/emoji2/emoji2-bundled/api/res-1.5.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/emoji2/emoji2-bundled/api/res-1.5.0-beta01.txt
diff --git a/emoji2/emoji2-bundled/api/restricted_1.5.0-beta01.txt b/emoji2/emoji2-bundled/api/restricted_1.5.0-beta01.txt
new file mode 100644
index 0000000..fab7dab
--- /dev/null
+++ b/emoji2/emoji2-bundled/api/restricted_1.5.0-beta01.txt
@@ -0,0 +1,10 @@
+// Signature format: 4.0
+package androidx.emoji2.bundled {
+
+  public class BundledEmojiCompatConfig extends androidx.emoji2.text.EmojiCompat.Config {
+    ctor @Deprecated public BundledEmojiCompatConfig(android.content.Context);
+    ctor public BundledEmojiCompatConfig(android.content.Context, java.util.concurrent.Executor);
+  }
+
+}
+
diff --git a/emoji2/emoji2-emojipicker/api/1.5.0-beta01.txt b/emoji2/emoji2-emojipicker/api/1.5.0-beta01.txt
new file mode 100644
index 0000000..8f56c18b
--- /dev/null
+++ b/emoji2/emoji2-emojipicker/api/1.5.0-beta01.txt
@@ -0,0 +1,43 @@
+// Signature format: 4.0
+package androidx.emoji2.emojipicker {
+
+  public final class EmojiPickerView extends android.widget.FrameLayout {
+    ctor public EmojiPickerView(android.content.Context context);
+    ctor public EmojiPickerView(android.content.Context context, optional android.util.AttributeSet? attrs);
+    ctor public EmojiPickerView(android.content.Context context, optional android.util.AttributeSet? attrs, optional int defStyleAttr);
+    method public int getEmojiGridColumns();
+    method public float getEmojiGridRows();
+    method public void setEmojiGridColumns(int);
+    method public void setEmojiGridRows(float);
+    method public void setOnEmojiPickedListener(androidx.core.util.Consumer<androidx.emoji2.emojipicker.EmojiViewItem>? onEmojiPickedListener);
+    method public void setRecentEmojiProvider(androidx.emoji2.emojipicker.RecentEmojiProvider recentEmojiProvider);
+    property public final int emojiGridColumns;
+    property public final float emojiGridRows;
+  }
+
+  public final class EmojiViewItem {
+    ctor public EmojiViewItem(String emoji, java.util.List<java.lang.String> variants);
+    method public String getEmoji();
+    method public java.util.List<java.lang.String> getVariants();
+    property public final String emoji;
+    property public final java.util.List<java.lang.String> variants;
+  }
+
+  public interface RecentEmojiAsyncProvider {
+    method public com.google.common.util.concurrent.ListenableFuture<java.util.List<java.lang.String>> getRecentEmojiListAsync();
+    method public void recordSelection(String emoji);
+  }
+
+  public interface RecentEmojiProvider {
+    method public suspend Object? getRecentEmojiList(kotlin.coroutines.Continuation<? super java.util.List<java.lang.String>>);
+    method public void recordSelection(String emoji);
+  }
+
+  public final class RecentEmojiProviderAdapter implements androidx.emoji2.emojipicker.RecentEmojiProvider {
+    ctor public RecentEmojiProviderAdapter(androidx.emoji2.emojipicker.RecentEmojiAsyncProvider recentEmojiAsyncProvider);
+    method public suspend Object? getRecentEmojiList(kotlin.coroutines.Continuation<? super java.util.List<java.lang.String>>);
+    method public void recordSelection(String emoji);
+  }
+
+}
+
diff --git a/emoji2/emoji2-emojipicker/api/res-1.5.0-beta01.txt b/emoji2/emoji2-emojipicker/api/res-1.5.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/emoji2/emoji2-emojipicker/api/res-1.5.0-beta01.txt
diff --git a/emoji2/emoji2-emojipicker/api/restricted_1.5.0-beta01.txt b/emoji2/emoji2-emojipicker/api/restricted_1.5.0-beta01.txt
new file mode 100644
index 0000000..8f56c18b
--- /dev/null
+++ b/emoji2/emoji2-emojipicker/api/restricted_1.5.0-beta01.txt
@@ -0,0 +1,43 @@
+// Signature format: 4.0
+package androidx.emoji2.emojipicker {
+
+  public final class EmojiPickerView extends android.widget.FrameLayout {
+    ctor public EmojiPickerView(android.content.Context context);
+    ctor public EmojiPickerView(android.content.Context context, optional android.util.AttributeSet? attrs);
+    ctor public EmojiPickerView(android.content.Context context, optional android.util.AttributeSet? attrs, optional int defStyleAttr);
+    method public int getEmojiGridColumns();
+    method public float getEmojiGridRows();
+    method public void setEmojiGridColumns(int);
+    method public void setEmojiGridRows(float);
+    method public void setOnEmojiPickedListener(androidx.core.util.Consumer<androidx.emoji2.emojipicker.EmojiViewItem>? onEmojiPickedListener);
+    method public void setRecentEmojiProvider(androidx.emoji2.emojipicker.RecentEmojiProvider recentEmojiProvider);
+    property public final int emojiGridColumns;
+    property public final float emojiGridRows;
+  }
+
+  public final class EmojiViewItem {
+    ctor public EmojiViewItem(String emoji, java.util.List<java.lang.String> variants);
+    method public String getEmoji();
+    method public java.util.List<java.lang.String> getVariants();
+    property public final String emoji;
+    property public final java.util.List<java.lang.String> variants;
+  }
+
+  public interface RecentEmojiAsyncProvider {
+    method public com.google.common.util.concurrent.ListenableFuture<java.util.List<java.lang.String>> getRecentEmojiListAsync();
+    method public void recordSelection(String emoji);
+  }
+
+  public interface RecentEmojiProvider {
+    method public suspend Object? getRecentEmojiList(kotlin.coroutines.Continuation<? super java.util.List<java.lang.String>>);
+    method public void recordSelection(String emoji);
+  }
+
+  public final class RecentEmojiProviderAdapter implements androidx.emoji2.emojipicker.RecentEmojiProvider {
+    ctor public RecentEmojiProviderAdapter(androidx.emoji2.emojipicker.RecentEmojiAsyncProvider recentEmojiAsyncProvider);
+    method public suspend Object? getRecentEmojiList(kotlin.coroutines.Continuation<? super java.util.List<java.lang.String>>);
+    method public void recordSelection(String emoji);
+  }
+
+}
+
diff --git a/emoji2/emoji2-views-helper/api/1.5.0-beta01.txt b/emoji2/emoji2-views-helper/api/1.5.0-beta01.txt
new file mode 100644
index 0000000..30a6feb
--- /dev/null
+++ b/emoji2/emoji2-views-helper/api/1.5.0-beta01.txt
@@ -0,0 +1,27 @@
+// Signature format: 4.0
+package androidx.emoji2.viewsintegration {
+
+  public final class EmojiEditTextHelper {
+    ctor public EmojiEditTextHelper(android.widget.EditText);
+    ctor public EmojiEditTextHelper(android.widget.EditText, boolean);
+    method public android.text.method.KeyListener? getKeyListener(android.text.method.KeyListener?);
+    method public int getMaxEmojiCount();
+    method public boolean isEnabled();
+    method public android.view.inputmethod.InputConnection? onCreateInputConnection(android.view.inputmethod.InputConnection?, android.view.inputmethod.EditorInfo);
+    method public void setEnabled(boolean);
+    method public void setMaxEmojiCount(@IntRange(from=0) int);
+  }
+
+  public final class EmojiTextViewHelper {
+    ctor public EmojiTextViewHelper(android.widget.TextView);
+    ctor public EmojiTextViewHelper(android.widget.TextView, boolean);
+    method public android.text.InputFilter![] getFilters(android.text.InputFilter![]);
+    method public boolean isEnabled();
+    method public void setAllCaps(boolean);
+    method public void setEnabled(boolean);
+    method public void updateTransformationMethod();
+    method public android.text.method.TransformationMethod? wrapTransformationMethod(android.text.method.TransformationMethod?);
+  }
+
+}
+
diff --git a/emoji2/emoji2-views-helper/api/res-1.5.0-beta01.txt b/emoji2/emoji2-views-helper/api/res-1.5.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/emoji2/emoji2-views-helper/api/res-1.5.0-beta01.txt
diff --git a/emoji2/emoji2-views-helper/api/restricted_1.5.0-beta01.txt b/emoji2/emoji2-views-helper/api/restricted_1.5.0-beta01.txt
new file mode 100644
index 0000000..30a6feb
--- /dev/null
+++ b/emoji2/emoji2-views-helper/api/restricted_1.5.0-beta01.txt
@@ -0,0 +1,27 @@
+// Signature format: 4.0
+package androidx.emoji2.viewsintegration {
+
+  public final class EmojiEditTextHelper {
+    ctor public EmojiEditTextHelper(android.widget.EditText);
+    ctor public EmojiEditTextHelper(android.widget.EditText, boolean);
+    method public android.text.method.KeyListener? getKeyListener(android.text.method.KeyListener?);
+    method public int getMaxEmojiCount();
+    method public boolean isEnabled();
+    method public android.view.inputmethod.InputConnection? onCreateInputConnection(android.view.inputmethod.InputConnection?, android.view.inputmethod.EditorInfo);
+    method public void setEnabled(boolean);
+    method public void setMaxEmojiCount(@IntRange(from=0) int);
+  }
+
+  public final class EmojiTextViewHelper {
+    ctor public EmojiTextViewHelper(android.widget.TextView);
+    ctor public EmojiTextViewHelper(android.widget.TextView, boolean);
+    method public android.text.InputFilter![] getFilters(android.text.InputFilter![]);
+    method public boolean isEnabled();
+    method public void setAllCaps(boolean);
+    method public void setEnabled(boolean);
+    method public void updateTransformationMethod();
+    method public android.text.method.TransformationMethod? wrapTransformationMethod(android.text.method.TransformationMethod?);
+  }
+
+}
+
diff --git a/emoji2/emoji2-views/api/1.5.0-beta01.txt b/emoji2/emoji2-views/api/1.5.0-beta01.txt
new file mode 100644
index 0000000..879b30e
--- /dev/null
+++ b/emoji2/emoji2-views/api/1.5.0-beta01.txt
@@ -0,0 +1,34 @@
+// Signature format: 4.0
+package androidx.emoji2.widget {
+
+  public class EmojiButton extends android.widget.Button {
+    ctor public EmojiButton(android.content.Context);
+    ctor public EmojiButton(android.content.Context, android.util.AttributeSet?);
+    ctor public EmojiButton(android.content.Context, android.util.AttributeSet?, int);
+  }
+
+  public class EmojiEditText extends android.widget.EditText {
+    ctor public EmojiEditText(android.content.Context);
+    ctor public EmojiEditText(android.content.Context, android.util.AttributeSet?);
+    ctor public EmojiEditText(android.content.Context, android.util.AttributeSet?, int);
+    method public int getMaxEmojiCount();
+    method public void setMaxEmojiCount(@IntRange(from=0) int);
+  }
+
+  public class EmojiExtractTextLayout extends android.widget.LinearLayout {
+    ctor public EmojiExtractTextLayout(android.content.Context);
+    ctor public EmojiExtractTextLayout(android.content.Context, android.util.AttributeSet?);
+    ctor public EmojiExtractTextLayout(android.content.Context, android.util.AttributeSet?, int);
+    method public int getEmojiReplaceStrategy();
+    method public void onUpdateExtractingViews(android.inputmethodservice.InputMethodService, android.view.inputmethod.EditorInfo);
+    method public void setEmojiReplaceStrategy(int);
+  }
+
+  public class EmojiTextView extends android.widget.TextView {
+    ctor public EmojiTextView(android.content.Context);
+    ctor public EmojiTextView(android.content.Context, android.util.AttributeSet?);
+    ctor public EmojiTextView(android.content.Context, android.util.AttributeSet?, int);
+  }
+
+}
+
diff --git a/emoji2/emoji2-views/api/res-1.5.0-beta01.txt b/emoji2/emoji2-views/api/res-1.5.0-beta01.txt
new file mode 100644
index 0000000..8bc8423
--- /dev/null
+++ b/emoji2/emoji2-views/api/res-1.5.0-beta01.txt
@@ -0,0 +1,2 @@
+attr emojiReplaceStrategy
+attr maxEmojiCount
diff --git a/emoji2/emoji2-views/api/restricted_1.5.0-beta01.txt b/emoji2/emoji2-views/api/restricted_1.5.0-beta01.txt
new file mode 100644
index 0000000..879b30e
--- /dev/null
+++ b/emoji2/emoji2-views/api/restricted_1.5.0-beta01.txt
@@ -0,0 +1,34 @@
+// Signature format: 4.0
+package androidx.emoji2.widget {
+
+  public class EmojiButton extends android.widget.Button {
+    ctor public EmojiButton(android.content.Context);
+    ctor public EmojiButton(android.content.Context, android.util.AttributeSet?);
+    ctor public EmojiButton(android.content.Context, android.util.AttributeSet?, int);
+  }
+
+  public class EmojiEditText extends android.widget.EditText {
+    ctor public EmojiEditText(android.content.Context);
+    ctor public EmojiEditText(android.content.Context, android.util.AttributeSet?);
+    ctor public EmojiEditText(android.content.Context, android.util.AttributeSet?, int);
+    method public int getMaxEmojiCount();
+    method public void setMaxEmojiCount(@IntRange(from=0) int);
+  }
+
+  public class EmojiExtractTextLayout extends android.widget.LinearLayout {
+    ctor public EmojiExtractTextLayout(android.content.Context);
+    ctor public EmojiExtractTextLayout(android.content.Context, android.util.AttributeSet?);
+    ctor public EmojiExtractTextLayout(android.content.Context, android.util.AttributeSet?, int);
+    method public int getEmojiReplaceStrategy();
+    method public void onUpdateExtractingViews(android.inputmethodservice.InputMethodService, android.view.inputmethod.EditorInfo);
+    method public void setEmojiReplaceStrategy(int);
+  }
+
+  public class EmojiTextView extends android.widget.TextView {
+    ctor public EmojiTextView(android.content.Context);
+    ctor public EmojiTextView(android.content.Context, android.util.AttributeSet?);
+    ctor public EmojiTextView(android.content.Context, android.util.AttributeSet?, int);
+  }
+
+}
+
diff --git a/emoji2/emoji2/api/1.5.0-beta01.txt b/emoji2/emoji2/api/1.5.0-beta01.txt
new file mode 100644
index 0000000..35a7659
--- /dev/null
+++ b/emoji2/emoji2/api/1.5.0-beta01.txt
@@ -0,0 +1,133 @@
+// Signature format: 4.0
+package androidx.emoji2.text {
+
+  public final class DefaultEmojiCompatConfig {
+    method public static androidx.emoji2.text.FontRequestEmojiCompatConfig? create(android.content.Context);
+  }
+
+  @AnyThread public class EmojiCompat {
+    method public static androidx.emoji2.text.EmojiCompat get();
+    method public String getAssetSignature();
+    method public int getEmojiEnd(CharSequence, @IntRange(from=0) int);
+    method public int getEmojiMatch(CharSequence, @IntRange(from=0) int);
+    method public int getEmojiStart(CharSequence, @IntRange(from=0) int);
+    method public int getLoadState();
+    method public static boolean handleDeleteSurroundingText(android.view.inputmethod.InputConnection, android.text.Editable, @IntRange(from=0) int, @IntRange(from=0) int, boolean);
+    method public static boolean handleOnKeyDown(android.text.Editable, int, android.view.KeyEvent);
+    method @Deprecated public boolean hasEmojiGlyph(CharSequence);
+    method @Deprecated public boolean hasEmojiGlyph(CharSequence, @IntRange(from=0) int);
+    method public static androidx.emoji2.text.EmojiCompat? init(android.content.Context);
+    method public static androidx.emoji2.text.EmojiCompat init(androidx.emoji2.text.EmojiCompat.Config);
+    method public static boolean isConfigured();
+    method public void load();
+    method @CheckResult public CharSequence? process(CharSequence?);
+    method @CheckResult public CharSequence? process(CharSequence?, @IntRange(from=0) int, @IntRange(from=0) int);
+    method @CheckResult public CharSequence? process(CharSequence?, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int);
+    method @CheckResult public CharSequence? process(CharSequence?, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int, int);
+    method public void registerInitCallback(androidx.emoji2.text.EmojiCompat.InitCallback);
+    method public void registerInitCallback(java.util.concurrent.Executor, androidx.emoji2.text.EmojiCompat.InitCallback);
+    method public void unregisterInitCallback(androidx.emoji2.text.EmojiCompat.InitCallback);
+    method public void updateEditorInfo(android.view.inputmethod.EditorInfo);
+    field public static final String EDITOR_INFO_METAVERSION_KEY = "android.support.text.emoji.emojiCompat_metadataVersion";
+    field public static final String EDITOR_INFO_REPLACE_ALL_KEY = "android.support.text.emoji.emojiCompat_replaceAll";
+    field public static final int EMOJI_FALLBACK = 2; // 0x2
+    field public static final int EMOJI_SUPPORTED = 1; // 0x1
+    field public static final int EMOJI_UNSUPPORTED = 0; // 0x0
+    field public static final int LOAD_STATE_DEFAULT = 3; // 0x3
+    field public static final int LOAD_STATE_FAILED = 2; // 0x2
+    field public static final int LOAD_STATE_LOADING = 0; // 0x0
+    field public static final int LOAD_STATE_SUCCEEDED = 1; // 0x1
+    field public static final int LOAD_STRATEGY_DEFAULT = 0; // 0x0
+    field public static final int LOAD_STRATEGY_MANUAL = 1; // 0x1
+    field public static final int REPLACE_STRATEGY_ALL = 1; // 0x1
+    field public static final int REPLACE_STRATEGY_DEFAULT = 0; // 0x0
+    field public static final int REPLACE_STRATEGY_NON_EXISTENT = 2; // 0x2
+  }
+
+  public abstract static class EmojiCompat.Config {
+    ctor protected EmojiCompat.Config(androidx.emoji2.text.EmojiCompat.MetadataRepoLoader);
+    method protected final androidx.emoji2.text.EmojiCompat.MetadataRepoLoader getMetadataRepoLoader();
+    method public androidx.emoji2.text.EmojiCompat.Config registerInitCallback(androidx.emoji2.text.EmojiCompat.InitCallback);
+    method public androidx.emoji2.text.EmojiCompat.Config registerInitCallback(java.util.concurrent.Executor, androidx.emoji2.text.EmojiCompat.InitCallback);
+    method public androidx.emoji2.text.EmojiCompat.Config setEmojiSpanIndicatorColor(@ColorInt int);
+    method public androidx.emoji2.text.EmojiCompat.Config setEmojiSpanIndicatorEnabled(boolean);
+    method public androidx.emoji2.text.EmojiCompat.Config setGlyphChecker(androidx.emoji2.text.EmojiCompat.GlyphChecker);
+    method public androidx.emoji2.text.EmojiCompat.Config setMetadataLoadStrategy(int);
+    method public androidx.emoji2.text.EmojiCompat.Config setReplaceAll(boolean);
+    method public androidx.emoji2.text.EmojiCompat.Config setSpanFactory(androidx.emoji2.text.EmojiCompat.SpanFactory);
+    method public androidx.emoji2.text.EmojiCompat.Config setUseEmojiAsDefaultStyle(boolean);
+    method public androidx.emoji2.text.EmojiCompat.Config setUseEmojiAsDefaultStyle(boolean, java.util.List<java.lang.Integer!>?);
+    method public androidx.emoji2.text.EmojiCompat.Config unregisterInitCallback(androidx.emoji2.text.EmojiCompat.InitCallback);
+  }
+
+  public static interface EmojiCompat.GlyphChecker {
+    method public boolean hasGlyph(CharSequence, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int);
+  }
+
+  public abstract static class EmojiCompat.InitCallback {
+    ctor public EmojiCompat.InitCallback();
+    method public void onFailed(Throwable?);
+    method public void onInitialized();
+  }
+
+  public static interface EmojiCompat.MetadataRepoLoader {
+    method public void load(androidx.emoji2.text.EmojiCompat.MetadataRepoLoaderCallback);
+  }
+
+  public abstract static class EmojiCompat.MetadataRepoLoaderCallback {
+    ctor public EmojiCompat.MetadataRepoLoaderCallback();
+    method public abstract void onFailed(Throwable?);
+    method public abstract void onLoaded(androidx.emoji2.text.MetadataRepo);
+  }
+
+  public static interface EmojiCompat.SpanFactory {
+    method public androidx.emoji2.text.EmojiSpan createSpan(androidx.emoji2.text.TypefaceEmojiRasterizer);
+  }
+
+  public class EmojiCompatInitializer implements androidx.startup.Initializer<java.lang.Boolean!> {
+    ctor public EmojiCompatInitializer();
+    method public Boolean create(android.content.Context);
+    method public java.util.List<java.lang.Class<? extends androidx.startup.Initializer<? extends java.lang.Object!>!>!> dependencies();
+  }
+
+  public abstract class EmojiSpan extends android.text.style.ReplacementSpan {
+    method public int getSize(android.graphics.Paint, CharSequence!, int, int, android.graphics.Paint.FontMetricsInt?);
+    method public final androidx.emoji2.text.TypefaceEmojiRasterizer getTypefaceRasterizer();
+  }
+
+  public class FontRequestEmojiCompatConfig extends androidx.emoji2.text.EmojiCompat.Config {
+    ctor public FontRequestEmojiCompatConfig(android.content.Context, androidx.core.provider.FontRequest);
+    method @Deprecated public androidx.emoji2.text.FontRequestEmojiCompatConfig setHandler(android.os.Handler?);
+    method public androidx.emoji2.text.FontRequestEmojiCompatConfig setLoadingExecutor(java.util.concurrent.Executor);
+    method public androidx.emoji2.text.FontRequestEmojiCompatConfig setRetryPolicy(androidx.emoji2.text.FontRequestEmojiCompatConfig.RetryPolicy?);
+  }
+
+  public static class FontRequestEmojiCompatConfig.ExponentialBackoffRetryPolicy extends androidx.emoji2.text.FontRequestEmojiCompatConfig.RetryPolicy {
+    ctor public FontRequestEmojiCompatConfig.ExponentialBackoffRetryPolicy(long);
+    method public long getRetryDelay();
+  }
+
+  public abstract static class FontRequestEmojiCompatConfig.RetryPolicy {
+    ctor public FontRequestEmojiCompatConfig.RetryPolicy();
+    method public abstract long getRetryDelay();
+  }
+
+  @AnyThread public final class MetadataRepo {
+    method public static androidx.emoji2.text.MetadataRepo create(android.content.res.AssetManager, String) throws java.io.IOException;
+    method public static androidx.emoji2.text.MetadataRepo create(android.graphics.Typeface, java.io.InputStream) throws java.io.IOException;
+    method public static androidx.emoji2.text.MetadataRepo create(android.graphics.Typeface, java.nio.ByteBuffer) throws java.io.IOException;
+  }
+
+  @AnyThread public class TypefaceEmojiRasterizer {
+    method public void draw(android.graphics.Canvas, float, float, android.graphics.Paint);
+    method public int getCodepointAt(int);
+    method public int getCodepointsLength();
+    method public int getHeight();
+    method public android.graphics.Typeface getTypeface();
+    method public int getWidth();
+    method public boolean isDefaultEmoji();
+    method public boolean isPreferredSystemRender();
+  }
+
+}
+
diff --git a/emoji2/emoji2/api/res-1.5.0-beta01.txt b/emoji2/emoji2/api/res-1.5.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/emoji2/emoji2/api/res-1.5.0-beta01.txt
diff --git a/emoji2/emoji2/api/restricted_1.5.0-beta01.txt b/emoji2/emoji2/api/restricted_1.5.0-beta01.txt
new file mode 100644
index 0000000..35a7659
--- /dev/null
+++ b/emoji2/emoji2/api/restricted_1.5.0-beta01.txt
@@ -0,0 +1,133 @@
+// Signature format: 4.0
+package androidx.emoji2.text {
+
+  public final class DefaultEmojiCompatConfig {
+    method public static androidx.emoji2.text.FontRequestEmojiCompatConfig? create(android.content.Context);
+  }
+
+  @AnyThread public class EmojiCompat {
+    method public static androidx.emoji2.text.EmojiCompat get();
+    method public String getAssetSignature();
+    method public int getEmojiEnd(CharSequence, @IntRange(from=0) int);
+    method public int getEmojiMatch(CharSequence, @IntRange(from=0) int);
+    method public int getEmojiStart(CharSequence, @IntRange(from=0) int);
+    method public int getLoadState();
+    method public static boolean handleDeleteSurroundingText(android.view.inputmethod.InputConnection, android.text.Editable, @IntRange(from=0) int, @IntRange(from=0) int, boolean);
+    method public static boolean handleOnKeyDown(android.text.Editable, int, android.view.KeyEvent);
+    method @Deprecated public boolean hasEmojiGlyph(CharSequence);
+    method @Deprecated public boolean hasEmojiGlyph(CharSequence, @IntRange(from=0) int);
+    method public static androidx.emoji2.text.EmojiCompat? init(android.content.Context);
+    method public static androidx.emoji2.text.EmojiCompat init(androidx.emoji2.text.EmojiCompat.Config);
+    method public static boolean isConfigured();
+    method public void load();
+    method @CheckResult public CharSequence? process(CharSequence?);
+    method @CheckResult public CharSequence? process(CharSequence?, @IntRange(from=0) int, @IntRange(from=0) int);
+    method @CheckResult public CharSequence? process(CharSequence?, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int);
+    method @CheckResult public CharSequence? process(CharSequence?, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int, int);
+    method public void registerInitCallback(androidx.emoji2.text.EmojiCompat.InitCallback);
+    method public void registerInitCallback(java.util.concurrent.Executor, androidx.emoji2.text.EmojiCompat.InitCallback);
+    method public void unregisterInitCallback(androidx.emoji2.text.EmojiCompat.InitCallback);
+    method public void updateEditorInfo(android.view.inputmethod.EditorInfo);
+    field public static final String EDITOR_INFO_METAVERSION_KEY = "android.support.text.emoji.emojiCompat_metadataVersion";
+    field public static final String EDITOR_INFO_REPLACE_ALL_KEY = "android.support.text.emoji.emojiCompat_replaceAll";
+    field public static final int EMOJI_FALLBACK = 2; // 0x2
+    field public static final int EMOJI_SUPPORTED = 1; // 0x1
+    field public static final int EMOJI_UNSUPPORTED = 0; // 0x0
+    field public static final int LOAD_STATE_DEFAULT = 3; // 0x3
+    field public static final int LOAD_STATE_FAILED = 2; // 0x2
+    field public static final int LOAD_STATE_LOADING = 0; // 0x0
+    field public static final int LOAD_STATE_SUCCEEDED = 1; // 0x1
+    field public static final int LOAD_STRATEGY_DEFAULT = 0; // 0x0
+    field public static final int LOAD_STRATEGY_MANUAL = 1; // 0x1
+    field public static final int REPLACE_STRATEGY_ALL = 1; // 0x1
+    field public static final int REPLACE_STRATEGY_DEFAULT = 0; // 0x0
+    field public static final int REPLACE_STRATEGY_NON_EXISTENT = 2; // 0x2
+  }
+
+  public abstract static class EmojiCompat.Config {
+    ctor protected EmojiCompat.Config(androidx.emoji2.text.EmojiCompat.MetadataRepoLoader);
+    method protected final androidx.emoji2.text.EmojiCompat.MetadataRepoLoader getMetadataRepoLoader();
+    method public androidx.emoji2.text.EmojiCompat.Config registerInitCallback(androidx.emoji2.text.EmojiCompat.InitCallback);
+    method public androidx.emoji2.text.EmojiCompat.Config registerInitCallback(java.util.concurrent.Executor, androidx.emoji2.text.EmojiCompat.InitCallback);
+    method public androidx.emoji2.text.EmojiCompat.Config setEmojiSpanIndicatorColor(@ColorInt int);
+    method public androidx.emoji2.text.EmojiCompat.Config setEmojiSpanIndicatorEnabled(boolean);
+    method public androidx.emoji2.text.EmojiCompat.Config setGlyphChecker(androidx.emoji2.text.EmojiCompat.GlyphChecker);
+    method public androidx.emoji2.text.EmojiCompat.Config setMetadataLoadStrategy(int);
+    method public androidx.emoji2.text.EmojiCompat.Config setReplaceAll(boolean);
+    method public androidx.emoji2.text.EmojiCompat.Config setSpanFactory(androidx.emoji2.text.EmojiCompat.SpanFactory);
+    method public androidx.emoji2.text.EmojiCompat.Config setUseEmojiAsDefaultStyle(boolean);
+    method public androidx.emoji2.text.EmojiCompat.Config setUseEmojiAsDefaultStyle(boolean, java.util.List<java.lang.Integer!>?);
+    method public androidx.emoji2.text.EmojiCompat.Config unregisterInitCallback(androidx.emoji2.text.EmojiCompat.InitCallback);
+  }
+
+  public static interface EmojiCompat.GlyphChecker {
+    method public boolean hasGlyph(CharSequence, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int);
+  }
+
+  public abstract static class EmojiCompat.InitCallback {
+    ctor public EmojiCompat.InitCallback();
+    method public void onFailed(Throwable?);
+    method public void onInitialized();
+  }
+
+  public static interface EmojiCompat.MetadataRepoLoader {
+    method public void load(androidx.emoji2.text.EmojiCompat.MetadataRepoLoaderCallback);
+  }
+
+  public abstract static class EmojiCompat.MetadataRepoLoaderCallback {
+    ctor public EmojiCompat.MetadataRepoLoaderCallback();
+    method public abstract void onFailed(Throwable?);
+    method public abstract void onLoaded(androidx.emoji2.text.MetadataRepo);
+  }
+
+  public static interface EmojiCompat.SpanFactory {
+    method public androidx.emoji2.text.EmojiSpan createSpan(androidx.emoji2.text.TypefaceEmojiRasterizer);
+  }
+
+  public class EmojiCompatInitializer implements androidx.startup.Initializer<java.lang.Boolean!> {
+    ctor public EmojiCompatInitializer();
+    method public Boolean create(android.content.Context);
+    method public java.util.List<java.lang.Class<? extends androidx.startup.Initializer<? extends java.lang.Object!>!>!> dependencies();
+  }
+
+  public abstract class EmojiSpan extends android.text.style.ReplacementSpan {
+    method public int getSize(android.graphics.Paint, CharSequence!, int, int, android.graphics.Paint.FontMetricsInt?);
+    method public final androidx.emoji2.text.TypefaceEmojiRasterizer getTypefaceRasterizer();
+  }
+
+  public class FontRequestEmojiCompatConfig extends androidx.emoji2.text.EmojiCompat.Config {
+    ctor public FontRequestEmojiCompatConfig(android.content.Context, androidx.core.provider.FontRequest);
+    method @Deprecated public androidx.emoji2.text.FontRequestEmojiCompatConfig setHandler(android.os.Handler?);
+    method public androidx.emoji2.text.FontRequestEmojiCompatConfig setLoadingExecutor(java.util.concurrent.Executor);
+    method public androidx.emoji2.text.FontRequestEmojiCompatConfig setRetryPolicy(androidx.emoji2.text.FontRequestEmojiCompatConfig.RetryPolicy?);
+  }
+
+  public static class FontRequestEmojiCompatConfig.ExponentialBackoffRetryPolicy extends androidx.emoji2.text.FontRequestEmojiCompatConfig.RetryPolicy {
+    ctor public FontRequestEmojiCompatConfig.ExponentialBackoffRetryPolicy(long);
+    method public long getRetryDelay();
+  }
+
+  public abstract static class FontRequestEmojiCompatConfig.RetryPolicy {
+    ctor public FontRequestEmojiCompatConfig.RetryPolicy();
+    method public abstract long getRetryDelay();
+  }
+
+  @AnyThread public final class MetadataRepo {
+    method public static androidx.emoji2.text.MetadataRepo create(android.content.res.AssetManager, String) throws java.io.IOException;
+    method public static androidx.emoji2.text.MetadataRepo create(android.graphics.Typeface, java.io.InputStream) throws java.io.IOException;
+    method public static androidx.emoji2.text.MetadataRepo create(android.graphics.Typeface, java.nio.ByteBuffer) throws java.io.IOException;
+  }
+
+  @AnyThread public class TypefaceEmojiRasterizer {
+    method public void draw(android.graphics.Canvas, float, float, android.graphics.Paint);
+    method public int getCodepointAt(int);
+    method public int getCodepointsLength();
+    method public int getHeight();
+    method public android.graphics.Typeface getTypeface();
+    method public int getWidth();
+    method public boolean isDefaultEmoji();
+    method public boolean isPreferredSystemRender();
+  }
+
+}
+
diff --git a/glance/glance-appwidget/api/current.txt b/glance/glance-appwidget/api/current.txt
index 1f04a7b..a1dcbd0 100644
--- a/glance/glance-appwidget/api/current.txt
+++ b/glance/glance-appwidget/api/current.txt
@@ -77,6 +77,7 @@
     method public androidx.glance.GlanceId? getGlanceIdBy(android.content.Intent configurationIntent);
     method public androidx.glance.GlanceId getGlanceIdBy(int appWidgetId);
     method public suspend <T extends androidx.glance.appwidget.GlanceAppWidget> Object? getGlanceIds(Class<T> provider, kotlin.coroutines.Continuation<? super java.util.List<? extends androidx.glance.GlanceId>>);
+    method public suspend <T extends androidx.glance.appwidget.GlanceAppWidgetReceiver> Object? requestPinGlanceAppWidget(Class<T> receiver, optional androidx.glance.appwidget.GlanceAppWidget? preview, optional androidx.compose.ui.unit.DpSize? previewSize, optional Object? previewState, optional android.app.PendingIntent? successCallback, kotlin.coroutines.Continuation<? super java.lang.Boolean>);
     method public suspend <T extends androidx.glance.appwidget.GlanceAppWidgetReceiver> Object? requestPinGlanceAppWidget(Class<T> receiver, optional androidx.glance.appwidget.GlanceAppWidget? preview, optional Object? previewState, optional android.app.PendingIntent? successCallback, kotlin.coroutines.Continuation<? super java.lang.Boolean>);
   }
 
diff --git a/glance/glance-appwidget/api/restricted_current.txt b/glance/glance-appwidget/api/restricted_current.txt
index 1f04a7b..a1dcbd0 100644
--- a/glance/glance-appwidget/api/restricted_current.txt
+++ b/glance/glance-appwidget/api/restricted_current.txt
@@ -77,6 +77,7 @@
     method public androidx.glance.GlanceId? getGlanceIdBy(android.content.Intent configurationIntent);
     method public androidx.glance.GlanceId getGlanceIdBy(int appWidgetId);
     method public suspend <T extends androidx.glance.appwidget.GlanceAppWidget> Object? getGlanceIds(Class<T> provider, kotlin.coroutines.Continuation<? super java.util.List<? extends androidx.glance.GlanceId>>);
+    method public suspend <T extends androidx.glance.appwidget.GlanceAppWidgetReceiver> Object? requestPinGlanceAppWidget(Class<T> receiver, optional androidx.glance.appwidget.GlanceAppWidget? preview, optional androidx.compose.ui.unit.DpSize? previewSize, optional Object? previewState, optional android.app.PendingIntent? successCallback, kotlin.coroutines.Continuation<? super java.lang.Boolean>);
     method public suspend <T extends androidx.glance.appwidget.GlanceAppWidgetReceiver> Object? requestPinGlanceAppWidget(Class<T> receiver, optional androidx.glance.appwidget.GlanceAppWidget? preview, optional Object? previewState, optional android.app.PendingIntent? successCallback, kotlin.coroutines.Continuation<? super java.lang.Boolean>);
   }
 
diff --git a/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/AppWidgetComposer.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/AppWidgetComposer.kt
index 2cc1731..1f8a5e0 100644
--- a/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/AppWidgetComposer.kt
+++ b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/AppWidgetComposer.kt
@@ -42,6 +42,12 @@
  *
  * If a valid [id] is provided, this function will use the sizing values from the bound widget if
  * using [SizeMode.Exact] or [SizeMode.Single].
+ *
+ * Only one instance of compose for a particular [id] may run at the same time. Calling compose
+ * concurrently with the same ID will succeed, but the first call will resume with an exception.
+ *
+ * If you need to call compose concurrently, you can omit [id] so that a random fake ID will be
+ * used. Otherwise, call compose sequentially when using the same [id].
  */
 suspend fun GlanceAppWidget.compose(
     @Suppress("ContextFirst") context: Context,
@@ -70,6 +76,13 @@
  * Lambda actions and list views in the emitted [RemoteViews] will continue to work while this is
  * flow is running. This currently does not support resizing (you have to run the flow again with
  * new [sizes]) or reloading the [androidx.glance.state.GlanceStateDefinition] state value.
+ *
+ * Note: In order to handle lambda actions correctly, only one instance of runComposition for a
+ * particular [id] may run at the same time. Calling runComposition concurrently with the same ID
+ * will succeed, but the first call will resume with an exception.
+ *
+ * If you need to call runComposition concurrently, you can omit [id] so that a random fake ID will
+ * be used. Otherwise, call runComposition sequentially when using the same [id].
  */
 @SuppressLint("PrimitiveInCollection")
 @ExperimentalGlanceApi
@@ -102,10 +115,8 @@
                     sizeMode
                 } else {
                     // When no sizes are provided, the widget is not SizeMode.Responsive, and we are
-                    // not
-                    // composing for a bound widget, use SizeMode.Exact (which means
-                    // AppWidgetSession will
-                    // use DpSize.Zero).
+                    // not composing for a bound widget, use SizeMode.Exact (which means
+                    // AppWidgetSession will use DpSize.Zero).
                     SizeMode.Exact
                 },
             shouldPublish = false,
diff --git a/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/AppWidgetUtils.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/AppWidgetUtils.kt
index 1339438..3b35e96 100644
--- a/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/AppWidgetUtils.kt
+++ b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/AppWidgetUtils.kt
@@ -63,25 +63,7 @@
     appWidgetId: Int
 ): DpSize {
     val info = appWidgetManager.getAppWidgetInfo(appWidgetId) ?: return DpSize.Zero
-    val minWidth =
-        min(
-            info.minWidth,
-            if (info.resizeMode and AppWidgetProviderInfo.RESIZE_HORIZONTAL != 0) {
-                info.minResizeWidth
-            } else {
-                Int.MAX_VALUE
-            }
-        )
-    val minHeight =
-        min(
-            info.minHeight,
-            if (info.resizeMode and AppWidgetProviderInfo.RESIZE_VERTICAL != 0) {
-                info.minResizeHeight
-            } else {
-                Int.MAX_VALUE
-            }
-        )
-    return DpSize(minWidth.pixelsToDp(displayMetrics), minHeight.pixelsToDp(displayMetrics))
+    return info.getMinSize(displayMetrics)
 }
 
 // Extract the sizes from the bundle
diff --git a/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/GlanceAppWidgetManager.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/GlanceAppWidgetManager.kt
index 57d2076..3bbd8a6f2 100644
--- a/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/GlanceAppWidgetManager.kt
+++ b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/GlanceAppWidgetManager.kt
@@ -203,6 +203,42 @@
         previewState: Any? = null,
         successCallback: PendingIntent? = null,
     ): Boolean {
+        return requestPinGlanceAppWidget(
+            receiver = receiver,
+            preview = preview,
+            previewSize = null,
+            previewState = previewState,
+            successCallback = successCallback,
+        )
+    }
+
+    /**
+     * Request to pin the [GlanceAppWidget] of the given receiver on the current launcher (if
+     * supported).
+     *
+     * Note: the request is only supported for SDK 26 and beyond, for lower versions this method
+     * will be no-op and return false.
+     *
+     * @param receiver the target [GlanceAppWidgetReceiver] class
+     * @param preview the instance of the GlanceAppWidget to compose the preview that will be shown
+     *   in the request dialog. When not provided the app widget previewImage (as defined in the
+     *   meta-data) will be used instead, or the app's icon if not available either.
+     * @param previewState the state (as defined by the [GlanceAppWidget.stateDefinition] to use for
+     *   the preview
+     * @param previewSize the size to be used for the preview. If none is provided, the widget's
+     *   minimum size (as determined by its' AppWidgetProviderInfo) will be used.
+     * @param successCallback a [PendingIntent] to be invoked if the app widget pinning is accepted
+     *   by the user
+     * @return true if the request was successfully sent to the system, false otherwise
+     * @see AppWidgetManager.requestPinAppWidget for more information and limitations
+     */
+    suspend fun <T : GlanceAppWidgetReceiver> requestPinGlanceAppWidget(
+        receiver: Class<T>,
+        preview: GlanceAppWidget? = null,
+        previewSize: DpSize? = null,
+        previewState: Any? = null,
+        successCallback: PendingIntent? = null,
+    ): Boolean {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
             return false
         }
@@ -219,7 +255,9 @@
                                 id = AppWidgetId(AppWidgetManager.INVALID_APPWIDGET_ID),
                                 state = previewState,
                                 options = Bundle.EMPTY,
-                                size = info.getMinSize(context.resources.displayMetrics),
+                                size =
+                                    previewSize
+                                        ?: info.getMinSize(context.resources.displayMetrics),
                             )
                         putParcelable(AppWidgetManager.EXTRA_APPWIDGET_PREVIEW, snapshot)
                     }
diff --git a/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/SizeMode.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/SizeMode.kt
index e5aa5fd..d3c900a 100644
--- a/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/SizeMode.kt
+++ b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/SizeMode.kt
@@ -19,7 +19,71 @@
 import androidx.compose.ui.unit.DpSize
 import androidx.glance.LocalSize
 
-/** Modes describing how the [GlanceAppWidget] should handle size specification. */
+/**
+ * Modes describing how the [GlanceAppWidget] should handle size specification.
+ *
+ * Note: Size modes that support multiple sizes ([Exact], [Responsive]) run the composable passed to
+ * to [provideContent] concurrently for each size. This has a number of important implications.
+ * Since an instance of the content is running for each size, all of the State objects in the
+ * content will have an instance for each size.
+ *
+ * For example, in Exact mode, let's say the AppWidgetHost asks for 2 sizes, portrait and landscape.
+ * In the code below, there will end up being two instances of the `count` variable, one for each
+ * size:
+ * ```
+ * provideContent {
+ *    var count by remember { mutableStateOf(0) }
+ *    Button(
+ *        text = "Increment count: $count",
+ *        onClick = { count++ }
+ *    )
+ * }
+ * ```
+ *
+ * If the button is clicked while the widget is displayed in portrait size, the `count` variable is
+ * updated for both sizes. This is so that, if the device orientation changes and the host displays
+ * the landscape layout, it will be consistent with the state in portrait. This works because
+ * lambdas that are at the same place in the composition will be mapped to the same default key in
+ * all sizes. So triggering one will trigger the corresponding lambdas in other sizes.
+ *
+ * This means that lambdas will be called multiple times when they are triggered, which can have
+ * unexpected effects if state is not handled correctly. In order to prevent some external action
+ * from being triggered multiple times at once, you should conflate requests so that only one is
+ * active at a time, e.g. using MutableStateFlow.
+ *
+ * To prevent this behavior, you can use the [androidx.compose.runtime.key] composable to set
+ * different default lambda keys for each size, so that they do not trigger each other:
+ * ```
+ * provideContent {
+ *    key(LocalSize.current) {
+ *        var count by remember { mutableStateOf(0) }
+ *        Button(
+ *            text = "Increment count: $count",
+ *            onClick = { count++ }
+ *        )
+ *    }
+ * }
+ * ```
+ *
+ * To disable this behavior on a per-lambda basis, use [androidx.glance.action.action] to set a
+ * custom lambda key based on the current size:
+ * ```
+ * provideContent {
+ *    var count by remember { mutableStateOf(0) }
+ *    Button(
+ *        text = "Increment count: $count",
+ *        onClick = action("incrementCount-${LocalSize.current}") { count++ }
+ *    )
+ * }
+ * ```
+ *
+ * In both of the last two examples, when the button is clicked, only the lambda for the currently
+ * visible size will be triggered.
+ *
+ * Note that the above does not work for effects, which will always be triggered for each size. Use
+ * effects to update state variables in the composition, otherwise be sure to handle any duplicate
+ * triggering that may occur.
+ */
 sealed interface SizeMode {
     /**
      * The [GlanceAppWidget] provides a single UI.
@@ -36,8 +100,9 @@
      * list of sizes is provided by the options bundle (see
      * [android.appwidget.AppWidgetManager.getAppWidgetOptions]).
      *
-     * The composable will be called for each size. During that call, the [LocalSize] will be the
-     * one for which the UI is generated.
+     * The composable will be run concurrently for each size. In each sub-composition, the
+     * [LocalSize] will be the one for which the UI is generated. See the note in [SizeMode] for
+     * more info.
      */
     object Exact : SizeMode {
         override fun toString(): String = "SizeMode.Exact"
@@ -46,14 +111,16 @@
     /**
      * The [GlanceAppWidget] provides a UI for a fixed set of sizes.
      *
-     * On Android 12 and later, the composable will be called once per size provided and the mapping
-     * from size to view will be sent to the system. The framework will then decide which view to
-     * display based on the current size of the App Widget (see [android.widget.RemoteViews] for
-     * details)
+     * On Android 12 and later, the composable will be run concurrently for each size provided and
+     * the mapping from size to view will be sent to the system. The framework will then decide
+     * which view to display based on the current size of the App Widget (see
+     * [android.widget.RemoteViews] for details)
      *
-     * Before Android 12, the composable will be called for each size at which the app widget may be
-     * displayed (like for [Exact]). For each size, the best view will be chosen, which is the
-     * largest one that fits in the available space, or the smallest one if none fit.
+     * Before Android 12, the composable will be run concurrently for each size at which the app
+     * widget may be displayed (like for [Exact]). For each size, the best view will be chosen,
+     * which is the largest one that fits in the available space, or the smallest one if none fit.
+     *
+     * See the note in [SizeMode] for more info about handling concurrent runs for multiple sizes.
      *
      * @param sizes List of sizes to use, must not be empty.
      */
diff --git a/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/action/ApplyAction.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/action/ApplyAction.kt
index b2558fb..fb82ee2 100644
--- a/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/action/ApplyAction.kt
+++ b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/action/ApplyAction.kt
@@ -90,6 +90,7 @@
                                 translationContext,
                                 viewId,
                                 ActionTrampolineType.CALLBACK,
+                                flags.toString()
                             )
                     }
                 },
@@ -106,6 +107,7 @@
                                 translationContext,
                                 viewId,
                                 ActionTrampolineType.CALLBACK,
+                                flags.toString(),
                             )
                     }
                 }
@@ -136,6 +138,7 @@
                                 translationContext,
                                 viewId,
                                 ActionTrampolineType.CALLBACK,
+                                flags.toString(),
                             )
                     }
                 },
@@ -233,6 +236,7 @@
                                 translationContext,
                                 viewId,
                                 ActionTrampolineType.CALLBACK,
+                                flags.toString(),
                             )
                     }
                 }
diff --git a/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/components/Scaffold.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/components/Scaffold.kt
index 9c0db0a..156db80 100644
--- a/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/components/Scaffold.kt
+++ b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/components/Scaffold.kt
@@ -61,13 +61,11 @@
         theModifier = theModifier.cornerRadius(android.R.dimen.system_app_widget_background_radius)
     }
 
-    Box(modifier = theModifier) {
-        Column(GlanceModifier.fillMaxSize()) {
-            titleBar?.invoke()
-            Box(
-                modifier = GlanceModifier.padding(horizontal = horizontalPadding).defaultWeight(),
-                content = content
-            )
-        }
+    Column(modifier = theModifier) {
+        titleBar?.invoke()
+        Box(
+            modifier = GlanceModifier.padding(horizontal = horizontalPadding).defaultWeight(),
+            content = content
+        )
     }
 }
diff --git a/glance/glance-appwidget/src/main/res/drawable-v31/glance_loading_layout_background.xml b/glance/glance-appwidget/src/main/res/drawable-v31/glance_loading_layout_background.xml
index c513e14..58b961c 100644
--- a/glance/glance-appwidget/src/main/res/drawable-v31/glance_loading_layout_background.xml
+++ b/glance/glance-appwidget/src/main/res/drawable-v31/glance_loading_layout_background.xml
@@ -17,5 +17,5 @@
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle">
     <corners android:radius="@android:dimen/system_app_widget_background_radius" />
-    <solid android:color="?android:attr/colorBackground" />
+    <solid android:color="@color/glance_colorWidgetBackground" />
 </shape>
diff --git a/glance/glance-appwidget/src/main/res/drawable/glance_loading_layout_background.xml b/glance/glance-appwidget/src/main/res/drawable/glance_loading_layout_background.xml
index 9327df3..3f6c385 100644
--- a/glance/glance-appwidget/src/main/res/drawable/glance_loading_layout_background.xml
+++ b/glance/glance-appwidget/src/main/res/drawable/glance_loading_layout_background.xml
@@ -17,5 +17,5 @@
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle">
     <corners android:radius="8dp" />
-    <solid android:color="?android:attr/colorBackground" />
+    <solid android:color="@color/glance_colorWidgetBackground" />
 </shape>
diff --git a/glance/glance/src/main/java/androidx/glance/action/Action.kt b/glance/glance/src/main/java/androidx/glance/action/Action.kt
index 6cc12b1..90a4cc1 100644
--- a/glance/glance/src/main/java/androidx/glance/action/Action.kt
+++ b/glance/glance/src/main/java/androidx/glance/action/Action.kt
@@ -39,6 +39,15 @@
 /**
  * Run [block] in response to a user click.
  *
+ * The lambda provided to this function will use the
+ * [androidx.compose.runtime.currentCompositeKeyHash] to set a key for this lambda that will be used
+ * to trigger it when the corresponding UI element is clicked. Since that key is based on the
+ * location within the composition, it will be identical for lambdas generated in a loop (if not
+ * using [androidx.compose.runtime.key]).
+ *
+ * To avoid this, prefer setting explicit keys for your lambdas, by using the overload of
+ * [clickable] that accepts a key parameter.
+ *
  * @param block The action to run.
  */
 @Composable
@@ -48,6 +57,15 @@
 /**
  * Run [block] in response to a user click.
  *
+ * The lambda provided to this function will use the
+ * [androidx.compose.runtime.currentCompositeKeyHash] to set a key for this lambda that will be used
+ * to trigger it when the corresponding UI element is clicked. Since that key is based on the
+ * location within the composition, it will be identical for lambdas generated in a loop (if not
+ * using [androidx.compose.runtime.key]).
+ *
+ * To avoid this, prefer setting explicit keys for your lambdas, by using the overload of
+ * [clickable] that accepts a key parameter.
+ *
  * @param rippleOverride A drawable resource to use as the onClick ripple. Use [NoRippleOverride] if
  *   no custom behavior is needed.
  * @param block The action to run.
@@ -77,10 +95,12 @@
  * @param block The action to run.
  * @param rippleOverride A drawable resource to use as the onClick ripple. Use [NoRippleOverride] if
  *   no custom behavior is needed.
- * @param key A stable and unique key that identifies the action for this element. This ensures that
- *   the correct action is triggered, especially in cases of items that change order. If not
- *   provided we use the key that is automatically generated by the Compose runtime, which is unique
- *   for every exact code location in the composition tree.
+ * @param key A stable and unique key that identifies this action. This key is saved in the
+ *   PendingIntent for the UI element, and used to trigger this action when the element is clicked.
+ *   If not provided we use [androidx.compose.runtime.currentCompositeKeyHash] as the key. Since
+ *   that key is based on the location within the composition, it will be identical for lambdas
+ *   generated in a loop (if not using [androidx.compose.runtime.key]). To avoid this, prefer
+ *   setting explicit keys for your lambdas, e.g. "incrementCount", "openNewYorkWeather", etc.
  */
 @Composable
 fun GlanceModifier.clickable(
diff --git a/glance/glance/src/main/java/androidx/glance/action/ActionParameters.kt b/glance/glance/src/main/java/androidx/glance/action/ActionParameters.kt
index 6d0e80e..75114f1 100644
--- a/glance/glance/src/main/java/androidx/glance/action/ActionParameters.kt
+++ b/glance/glance/src/main/java/androidx/glance/action/ActionParameters.kt
@@ -28,8 +28,9 @@
 abstract class ActionParameters internal constructor() {
 
     /**
-     * Key for [ActionParameters] values. Type T is the type of the associated value. The [Key.name]
-     * must be unique, keys with the same name are considered equal.
+     * Key for [ActionParameters] values. Type T is the type of the associated value. T must be a
+     * primitive or Parcelable type. The [Key.name] must be unique, keys with the same name are
+     * considered equal.
      */
     class Key<T : Any>(val name: String) {
         /**
@@ -157,7 +158,8 @@
 
 /**
  * Returns a new read-only Parameters, from the specified contents. The key element in the given
- * pairs will point to the corresponding value element.
+ * pairs will point to the corresponding value element. All values must be either of primitive or
+ * Parcelable types.
  *
  * If multiple pairs have the same key, the resulting map will contain only the value from the last
  * of those pairs.
@@ -167,7 +169,8 @@
 
 /**
  * Returns a new MutableParameters, from the specified contents. The key element in the given pairs
- * will point to the corresponding value element.
+ * will point to the corresponding value element. All values must be either of primitive or
+ * Parcelable types.
  *
  * If multiple pairs have the same key, the resulting Parameters will contain only the value from
  * the last of those pairs.
diff --git a/glance/glance/src/main/java/androidx/glance/action/LambdaAction.kt b/glance/glance/src/main/java/androidx/glance/action/LambdaAction.kt
index eeaa236..420a7ff 100644
--- a/glance/glance/src/main/java/androidx/glance/action/LambdaAction.kt
+++ b/glance/glance/src/main/java/androidx/glance/action/LambdaAction.kt
@@ -31,9 +31,12 @@
 /**
  * Create an [Action] that runs [block] when triggered.
  *
- * @param key An optional key to be used as a key for the action. If not provided we use the key
- *   that is automatically generated by the Compose runtime which is unique for every exact code
- *   location in the composition tree.
+ * @param key A stable and unique key that identifies this action. This key is saved in the
+ *   PendingIntent for the UI element, and used to trigger this action when the element is clicked.
+ *   If not provided we use [androidx.compose.runtime.currentCompositeKeyHash] as the key. Since
+ *   that key is based on the location within the composition, it will be identical for lambdas
+ *   generated in a loop (if not using [androidx.compose.runtime.key]). To avoid this, prefer
+ *   setting explicit keys for your lambdas.
  * @param block the function to be run when this action is triggered.
  */
 @Composable
diff --git a/gradle.properties b/gradle.properties
index d75bd18..e013251 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -95,6 +95,5 @@
 # Annotation processors discovery from compile classpath is deprecated
 kapt.include.compile.classpath=false
 
-# Disable dependency analysis on test sources
-systemProp.dependency.analysis.test.analysis=false
+# Disable dependency analysis compatibility check
 dependency.analysis.compatibility=NONE
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 4fb3f16..bec1d5d 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -2,27 +2,28 @@
 # -----------------------------------------------------------------------------
 # All of the following should be updated in sync.
 # -----------------------------------------------------------------------------
-androidGradlePlugin = "8.6.0-alpha05"
+androidGradlePlugin = "8.6.0-alpha07"
 # NOTE: When updating the lint version we also need to update the `api` version
 # supported by `IssueRegistry`'s.' For e.g. r.android.com/1331903
-androidLint = "31.6.0-alpha05"
+androidLint = "31.6.0-alpha07"
 # Once you have a chosen version of AGP to upgrade to, go to
 # https://developer.android.com/studio/archive and find the matching version of Studio.
-androidStudio = "2024.1.2.5"
+androidStudio = "2024.1.2.7"
 # -----------------------------------------------------------------------------
 
 androidLintMin = "31.1.0"
-androidxTestRunner = "1.6.0-rc01"
-androidxTestRules = "1.6.0-rc01"
-androidxTestMonitor = "1.7.0-rc01"
-androidxTestCore = "1.6.0-rc01"
-androidxTestExtJunit = "1.2.0-rc01"
-androidxTestExtTruth = "1.6.0-rc01"
+androidxTestRunner = "1.6.1"
+androidxTestRules = "1.6.1"
+androidxTestMonitor = "1.7.1"
+androidxTestCore = "1.6.1"
+androidxTestExtJunit = "1.2.1"
+androidxTestExtTruth = "1.6.0"
 annotationVersion = "1.7.0"
 atomicFu = "0.17.0"
 autoService = "1.0-rc6"
 autoValue = "1.6.3"
 binaryCompatibilityValidator = "0.15.0-Beta.2"
+builder = "8.6.0-alpha05"
 byteBuddy = "1.14.9"
 asm = "9.7"
 cmake = "3.22.1"
@@ -31,22 +32,28 @@
 dependencyAnalysisGradlePlugin = "1.32.0"
 dexmaker = "2.28.3"
 dokka = "1.8.20-dev-214"
-espresso = "3.6.0-rc01"
-espressoDevice = "1.0.0-rc01"
+espresso = "3.6.1"
+espressoDevice = "1.0.1"
 grpc = "1.52.0"
-guavaJre = "31.1-jre"
+guavaJre = "33.2.1-jre"
+hamcrestCore = "1.3"
 hilt = "2.49"
 incap = "0.2"
+javaxInject = "1"
 jcodec = "0.2.5"
 kotlin17 = "1.7.10"
 kotlin18 = "1.8.22"
 kotlin19 = "1.9.24"
 kotlin = "1.9.24"
 kotlinBenchmark = "0.4.8"
+kotlinGradlePluginAnnotations = "1.9.24"
+kotlinGradlePluginApi = "1.9.24"
 kotlinNative = "1.9.24"
 kotlinCompileTesting = "1.4.9"
 kotlinCoroutines = "1.7.3"
+kotlinNativeUtils = "1.9.24"
 kotlinSerialization = "1.6.3"
+kotlinToolingCore = "1.9.24"
 ksp = "1.9.24-1.0.20"
 ktfmt = "0.50"
 leakcanary = "2.13"
@@ -55,12 +62,14 @@
 mockito = "2.25.0"
 moshi = "1.13.0"
 protobuf = "3.22.3"
+shadow = "8.1.1"
 skiko = "0.7.7"
 spdxGradlePlugin = "0.6.0"
 sqldelight = "1.3.0"
 retrofit = "2.7.2"
 wire = "4.9.7"
 core = "1.12.0"
+xmlApis = "1.4.01"
 
 [libraries]
 agpTestingPlatformCoreProto =  { module = "com.google.testing.platform:core-proto", version = "0.0.8-alpha08" }
@@ -98,7 +107,9 @@
 assertj = { module = "org.assertj:assertj-core", version = "3.23.1" }
 asm = { module = "org.ow2.asm:asm", version.ref = "asm"}
 asmCommons = { module = "org.ow2.asm:asm-commons", version.ref = "asm"}
+jetbrainsBinaryCompatibilityValidator = { module = "org.jetbrains.kotlinx:binary-compatibility-validator", version.ref = "binaryCompatibilityValidator" }
 binaryCompatibilityValidator = { module = "org.jetbrains.kotlinx.binary-compatibility-validator:org.jetbrains.kotlinx.binary-compatibility-validator.gradle.plugin", version.ref = "binaryCompatibilityValidator"}
+builder = { module = "com.android.tools.build:builder", version.ref = "builder" }
 byteBuddy = { module = "net.bytebuddy:byte-buddy", version.ref = "byteBuddy" }
 byteBuddyAgent = { module = "net.bytebuddy:byte-buddy-agent", version.ref = "byteBuddy" }
 checkerframework = { module = "org.checkerframework:checker-qual", version = "2.5.3" }
@@ -136,15 +147,19 @@
 firebaseAppindexing = { module = "com.google.firebase:firebase-appindexing", version = "19.2.0" }
 freemarker = { module = "org.freemarker:freemarker", version = "2.3.31"}
 googletest = { module = "com.android.ndk.thirdparty:googletest", version = "1.11.0-beta-1" }
+hamcrestCore = { module = "org.hamcrest:hamcrest-core", version.ref = "hamcrestCore" }
 hiltAndroid = { module = "com.google.dagger:hilt-android", version.ref = "hilt" }
 hiltAndroidTesting = { module = "com.google.dagger:hilt-android-testing", version.ref = "hilt" }
 hiltAndroidGradlePluginz = { module = "com.google.dagger:hilt-android-gradle-plugin", version.ref = "hilt" }
 hiltCompiler = { module = "com.google.dagger:hilt-compiler", version.ref = "hilt" }
 hiltCore = { module = "com.google.dagger:hilt-core", version.ref = "hilt" }
+intellijCore = { module = "com.android.tools.external.com-intellij:intellij-core", version.ref = "androidLint" }
 intellijAnnotations = { module = "com.intellij:annotations", version = "12.0" }
 javapoet = { module = "com.squareup:javapoet", version = "1.13.0" }
+javaxInject = { module = "javax.inject:javax.inject", version.ref = "javaxInject" }
 jcodec = { module = "org.jcodec:jcodec", version.ref = "jcodec" }
 jcodecJavaSe = { module = "org.jcodec:jcodec-javase", version.ref = "jcodec" }
+johnrengelmanShadow = { module = "com.github.johnrengelman:shadow", version.ref = "shadow" }
 json = { module = "org.json:json", version = "20180813" }
 jsoup = { module = "org.jsoup:jsoup", version = "1.16.2" }
 jsqlparser = { module = "com.github.jsqlparser:jsqlparser", version = "3.1" }
@@ -165,6 +180,11 @@
 guavaTestlib = { module = "com.google.guava:guava-testlib", version.ref = "guavaJre" }
 gradleIncapHelper = { module = "net.ltgt.gradle.incap:incap", version.ref = "incap" }
 gradleIncapHelperProcessor = { module = "net.ltgt.gradle.incap:incap-processor", version.ref = "incap" }
+intellijKotlinCompiler = { module = "com.android.tools.external.com-intellij:kotlin-compiler", version.ref = "androidLint" }
+kotlinNativeUtils = { module = "org.jetbrains.kotlin:kotlin-native-utils", version.ref = "kotlinNativeUtils" }
+kotlinGradlePluginApi = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin-api", version.ref = "kotlinGradlePluginApi" }
+kotlinToolingCore = { module = "org.jetbrains.kotlin:kotlin-tooling-core", version.ref = "kotlinToolingCore" }
+kotlinGradlePluginAnnotations = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin-annotations", version.ref = "kotlinGradlePluginAnnotations" }
 kotlinAnnotationProcessingEmbeddable = { module = "org.jetbrains.kotlin:kotlin-annotation-processing-embeddable" }
 kotlinBenchmarkRuntime = { module = "org.jetbrains.kotlinx:kotlinx-benchmark-runtime", version.ref = "kotlinBenchmark" }
 kotlinBom = { module = "org.jetbrains.kotlin:kotlin-bom", version.ref = "kotlin" }
@@ -208,6 +228,7 @@
 kxml2 = { module = "net.sf.kxml:kxml2", version = "2.3.0" }
 leakcanary = { module = "com.squareup.leakcanary:leakcanary-android", version.ref = "leakcanary" }
 leakcanaryInstrumentation = { module = "com.squareup.leakcanary:leakcanary-android-instrumentation", version.ref = "leakcanary" }
+lintModel = { module = "com.android.tools.lint:lint-model", version.ref = "androidLint" }
 material = { module = "com.google.android.material:material", version = "1.2.1" }
 media3Common = { module = "androidx.media3:media3-common", version.ref = "media3" }
 media3Cast = { module = "androidx.media3:media3-cast", version.ref = "media3" }
@@ -234,7 +255,7 @@
 okhttpMockwebserver = { module = "com.squareup.okhttp3:mockwebserver", version = "3.14.7" }
 okio = { module = "com.squareup.okio:okio", version = "3.4.0" }
 opentest4j = { module = "org.opentest4j:opentest4j", version = "1.2.0" }
-playFeatureDelivery = { module = "com.google.android.play:feature-delivery", version = "2.0.1" }
+playFeatureDelivery = { module = "com.google.android.play:feature-delivery", version = "2.1.0" }
 playCore = { module = "com.google.android.play:core", version = "1.10.3" }
 playServicesAuth = {module = "com.google.android.gms:play-services-auth", version = "21.1.1"}
 playServicesBase = { module = "com.google.android.gms:play-services-base", version = "17.0.0" }
@@ -253,6 +274,7 @@
 robolectric = { module = "org.robolectric:robolectric", version = "4.12.2" }
 rxjava2 = { module = "io.reactivex.rxjava2:rxjava", version = "2.2.9" }
 rxjava3 = { module = "io.reactivex.rxjava3:rxjava", version = "3.0.0" }
+sdklib = { module = "com.android.tools:sdklib", version.ref = "androidLint" }
 shadow = { module = "com.github.johnrengelman.shadow:com.github.johnrengelman.shadow.gradle.plugin", version = "8.1.1" }
 skiko = { module = "org.jetbrains.skiko:skiko-awt", version.ref = "skiko" }
 skikoCommon = { module = "org.jetbrains.skiko:skiko", version.ref = "skiko" }
@@ -277,10 +299,12 @@
 testUiautomator = { module = "androidx.test.uiautomator:uiautomator", version = "2.2.0" }
 truth = { module = "com.google.truth:truth", version = "1.0.1" }
 toml = { module = "org.tomlj:tomlj", version = "1.0.0" }
+uast = { module = "com.android.tools.external.org-jetbrains:uast", version.ref = "androidLint" }
 viewBinding = { module = "androidx.databinding:viewbinding", version = "4.1.2" }
 wireGradlePluginz = { module = "com.squareup.wire:wire-gradle-plugin", version.ref = "wire" }
 wireRuntime = { module = "com.squareup.wire:wire-runtime", version.ref = "wire" }
 xerces = { module = "xerces:xercesImpl", version = "2.12.0" }
+xmlApis = { module = "xml-apis:xml-apis", version.ref = "xmlApis" }
 xpp3 = { module = "xpp3:xpp3", version = "1.1.4c" }
 xmlpull = { module = "xmlpull:xmlpull", version = "1.1.3.1" }
 androidx-core = { group = "androidx.core", name = "core", version.ref = "core" }
diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml
index dd554b9..16a5511 100644
--- a/gradle/verification-metadata.xml
+++ b/gradle/verification-metadata.xml
@@ -329,7 +329,7 @@
             <trusting group="com.fasterxml.jackson.core"/>
             <trusting group="com.fasterxml.jackson.module"/>
          </trusted-key>
-         <trusted-key id="8B39C4ACE0F448789FE19C8BAC0E2034B1389C89" group="androidx.build.gradle.gcpbuildcache" name="gcpbuildcache" />
+         <trusted-key id="8B39C4ACE0F448789FE19C8BAC0E2034B1389C89" group="androidx.build.gradle.gcpbuildcache" name="gcpbuildcache"/>
          <trusted-key id="8DF3B0AA23ED78BE5233F6C2DEA3D207428EF16D" group="com.linkedin.dexmaker"/>
          <trusted-key id="8E3A02905A1AE67E7B0F9ACD3967D4EDA591B991" group="org.jetbrains.kotlinx" name="kotlinx-html-jvm"/>
          <trusted-key id="8F9A3C6D105B9F57844A721D79E193516BE7998F" group="org.dom4j" name="dom4j"/>
@@ -705,6 +705,11 @@
             <sha256 value="f4d85c3e4d411694337cb873abea09b242b664bb013320be6105327c45991537" origin="Generated by Gradle" reason="https://github.com/google/guava/issues/7154"/>
          </artifact>
       </component>
+      <component group="com.google.guava" name="guava" version="33.2.1-jre">
+         <artifact name="guava-33.2.1-android.jar">
+            <sha256 value="6b55fbe6ffee621454c03df7bea720d189789e136391a524e29506ff40654180" origin="Generated by Gradle" reason="https://github.com/google/guava/issues/7154"/>
+         </artifact>
+      </component>
       <component group="com.google.j2objc" name="j2objc-annotations" version="3.0.0">
          <artifact name="j2objc-annotations-3.0.0.pom">
             <pgp value="BDB5FA4FE719D787FB3D3197F6D4A1D411E9D1AE"/>
diff --git a/health/connect/connect-client/api/current.txt b/health/connect/connect-client/api/current.txt
index f01a72a..6f9a11e 100644
--- a/health/connect/connect-client/api/current.txt
+++ b/health/connect/connect-client/api/current.txt
@@ -1,6 +1,9 @@
 // Signature format: 4.0
 package androidx.health.connect.client {
 
+  @SuppressCompatibility @kotlin.RequiresOptIn(message="This is an experimental Health Connect API and is likely to change in the future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalHealthConnectApi {
+  }
+
   @kotlin.jvm.JvmDefaultWithCompatibility public interface HealthConnectClient {
     method public suspend Object? aggregate(androidx.health.connect.client.request.AggregateRequest request, kotlin.coroutines.Continuation<? super androidx.health.connect.client.aggregate.AggregationResult>);
     method public suspend Object? aggregateGroupByDuration(androidx.health.connect.client.request.AggregateGroupByDurationRequest request, kotlin.coroutines.Continuation<? super java.util.List<androidx.health.connect.client.aggregate.AggregationResultGroupedByDuration>>);
diff --git a/health/connect/connect-client/api/restricted_current.txt b/health/connect/connect-client/api/restricted_current.txt
index 9c0d728..829b64ab 100644
--- a/health/connect/connect-client/api/restricted_current.txt
+++ b/health/connect/connect-client/api/restricted_current.txt
@@ -1,6 +1,9 @@
 // Signature format: 4.0
 package androidx.health.connect.client {
 
+  @SuppressCompatibility @kotlin.RequiresOptIn(message="This is an experimental Health Connect API and is likely to change in the future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalHealthConnectApi {
+  }
+
   @kotlin.jvm.JvmDefaultWithCompatibility public interface HealthConnectClient {
     method public suspend Object? aggregate(androidx.health.connect.client.request.AggregateRequest request, kotlin.coroutines.Continuation<? super androidx.health.connect.client.aggregate.AggregationResult>);
     method public suspend Object? aggregateGroupByDuration(androidx.health.connect.client.request.AggregateGroupByDurationRequest request, kotlin.coroutines.Continuation<? super java.util.List<androidx.health.connect.client.aggregate.AggregationResultGroupedByDuration>>);
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/ExperimentalHealthConnectApi.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/ExperimentalHealthConnectApi.kt
new file mode 100644
index 0000000..fd76bb6
--- /dev/null
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/ExperimentalHealthConnectApi.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.health.connect.client
+
+@RequiresOptIn(
+    message = "This is an experimental Health Connect API and is likely to change in the future."
+)
+@Retention(AnnotationRetention.BINARY)
+public annotation class ExperimentalHealthConnectApi
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/changes/DeletionChange.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/changes/DeletionChange.kt
index 222b01b..4a6683a 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/changes/DeletionChange.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/changes/DeletionChange.kt
@@ -15,6 +15,7 @@
  */
 package androidx.health.connect.client.changes
 
+import androidx.annotation.RestrictTo
 import androidx.health.connect.client.records.Record
 import androidx.health.connect.client.records.metadata.Metadata
 
@@ -28,7 +29,9 @@
  *
  * @property recordId [Metadata.id] of deleted [Record].
  */
-class DeletionChange internal constructor(public val recordId: String) : Change {
+class DeletionChange
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+constructor(public val recordId: String) : Change {
 
     /*
      * Generated by the IDE: Code -> Generate -> "equals() and hashCode()".
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/changes/UpsertionChange.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/changes/UpsertionChange.kt
index a36ac4a..3ad73fa 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/changes/UpsertionChange.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/changes/UpsertionChange.kt
@@ -15,6 +15,7 @@
  */
 package androidx.health.connect.client.changes
 
+import androidx.annotation.RestrictTo
 import androidx.health.connect.client.records.Record
 
 /**
@@ -22,7 +23,9 @@
  *
  * @property record Updated or inserted record.
  */
-class UpsertionChange internal constructor(public val record: Record) : Change {
+class UpsertionChange
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+constructor(public val record: Record) : Change {
 
     /*
      * Generated by the IDE: Code -> Generate -> "equals() and hashCode()".
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/HealthConnectClientImpl.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/HealthConnectClientImpl.kt
index bc4c2c3..97bb194 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/HealthConnectClientImpl.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/HealthConnectClientImpl.kt
@@ -64,18 +64,7 @@
 class HealthConnectClientImpl
 internal constructor(
     private val delegate: HealthDataAsyncClient,
-    private val allPermissions: List<String> = buildList {
-        addAll(
-            HealthPermission.RECORD_TYPE_TO_PERMISSION.flatMap {
-                listOf(
-                    HealthPermission.WRITE_PERMISSION_PREFIX + it.value,
-                    HealthPermission.READ_PERMISSION_PREFIX + it.value
-                )
-            }
-        )
-        add(HealthPermission.PERMISSION_WRITE_EXERCISE_ROUTE)
-        add(HealthPermission.PERMISSION_READ_HEALTH_DATA_IN_BACKGROUND)
-    },
+    private val allPermissions: List<String> = HealthPermission.ALL_PERMISSIONS,
 ) : HealthConnectClient, PermissionController {
 
     override suspend fun getGrantedPermissions(): Set<String> {
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/converters/records/ProtoToRecordUtils.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/converters/records/ProtoToRecordUtils.kt
index f87c7b0..e460b00 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/converters/records/ProtoToRecordUtils.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/converters/records/ProtoToRecordUtils.kt
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-@file:RestrictTo(RestrictTo.Scope.LIBRARY)
+@file:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
 
 package androidx.health.connect.client.impl.converters.records
 
@@ -36,28 +36,28 @@
 
 /** Internal helper functions to convert proto to records. */
 @get:SuppressWarnings("GoodTime") // Safe to use for deserialization
-internal val DataProto.DataPoint.startTime: Instant
+val DataProto.DataPoint.startTime: Instant
     get() = Instant.ofEpochMilli(startTimeMillis)
 
 @get:SuppressWarnings("GoodTime") // Safe to use for deserialization
-internal val DataProto.DataPoint.endTime: Instant
+val DataProto.DataPoint.endTime: Instant
     get() = Instant.ofEpochMilli(endTimeMillis)
 
 @get:SuppressWarnings("GoodTime") // Safe to use for deserialization
-internal val DataProto.DataPoint.time: Instant
+val DataProto.DataPoint.time: Instant
     get() = Instant.ofEpochMilli(instantTimeMillis)
 
 @get:SuppressWarnings("GoodTime") // Safe to use for deserialization
-internal val DataProto.DataPoint.startZoneOffset: ZoneOffset?
+val DataProto.DataPoint.startZoneOffset: ZoneOffset?
     get() =
         if (hasStartZoneOffsetSeconds()) ZoneOffset.ofTotalSeconds(startZoneOffsetSeconds) else null
 
 @get:SuppressWarnings("GoodTime") // Safe to use for deserialization
-internal val DataProto.DataPoint.endZoneOffset: ZoneOffset?
+val DataProto.DataPoint.endZoneOffset: ZoneOffset?
     get() = if (hasEndZoneOffsetSeconds()) ZoneOffset.ofTotalSeconds(endZoneOffsetSeconds) else null
 
 @get:SuppressWarnings("GoodTime") // HealthDataClientImplSafe to use for deserialization
-internal val DataProto.DataPoint.zoneOffset: ZoneOffset?
+val DataProto.DataPoint.zoneOffset: ZoneOffset?
     get() = if (hasZoneOffsetSeconds()) ZoneOffset.ofTotalSeconds(zoneOffsetSeconds) else null
 
 internal fun DataPointOrBuilder.getLong(key: String, defaultVal: Long = 0): Long =
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/permission/HealthPermission.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/permission/HealthPermission.kt
index 93d5287..a63bb6d 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/permission/HealthPermission.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/permission/HealthPermission.kt
@@ -348,6 +348,23 @@
                 WheelchairPushesRecord::class to
                     READ_WHEELCHAIR_PUSHES.substringAfter(READ_PERMISSION_PREFIX),
             )
+
+        /**
+         * Exposes all write and read permissions.
+         *
+         * @return A list of permissions as Strings
+         */
+        @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+        @JvmField
+        public val ALL_PERMISSIONS: List<String> = buildList {
+            addAll(
+                RECORD_TYPE_TO_PERMISSION.flatMap {
+                    listOf(WRITE_PERMISSION_PREFIX + it.value, READ_PERMISSION_PREFIX + it.value)
+                }
+            )
+            add(PERMISSION_WRITE_EXERCISE_ROUTE)
+            add(PERMISSION_READ_HEALTH_DATA_IN_BACKGROUND)
+        }
     }
 
     override fun equals(other: Any?): Boolean {
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/request/ChangesTokenRequest.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/request/ChangesTokenRequest.kt
index 669e483..0a42c02c 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/request/ChangesTokenRequest.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/request/ChangesTokenRequest.kt
@@ -15,6 +15,7 @@
  */
 package androidx.health.connect.client.request
 
+import androidx.annotation.RestrictTo
 import androidx.health.connect.client.records.Record
 import androidx.health.connect.client.records.metadata.DataOrigin
 import kotlin.reflect.KClass
@@ -27,8 +28,8 @@
  *   filter.
  */
 class ChangesTokenRequest(
-    internal val recordTypes: Set<KClass<out Record>>,
-    internal val dataOriginFilters: Set<DataOrigin> = setOf()
+    @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) val recordTypes: Set<KClass<out Record>>,
+    @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) val dataOriginFilters: Set<DataOrigin> = setOf()
 ) {
     /*
      * Generated by the IDE: Code -> Generate -> "equals() and hashCode()".
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/request/ReadRecordsRequest.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/request/ReadRecordsRequest.kt
index ebb1336..c52e70d 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/request/ReadRecordsRequest.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/request/ReadRecordsRequest.kt
@@ -15,6 +15,7 @@
  */
 package androidx.health.connect.client.request
 
+import androidx.annotation.RestrictTo
 import androidx.health.connect.client.records.Record
 import androidx.health.connect.client.records.metadata.DataOrigin
 import androidx.health.connect.client.time.TimeRangeFilter
@@ -65,12 +66,13 @@
  * @see androidx.health.connect.client.HealthConnectClient.readRecords
  */
 public class ReadRecordsRequest<T : Record>(
-    internal val recordType: KClass<T>,
-    internal val timeRangeFilter: TimeRangeFilter,
-    internal val dataOriginFilter: Set<DataOrigin> = emptySet(),
-    internal val ascendingOrder: Boolean = true,
-    internal val pageSize: Int = 1000,
-    internal val pageToken: String? = null,
+    @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) val recordType: KClass<T>,
+    @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) val timeRangeFilter: TimeRangeFilter,
+    @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    val dataOriginFilter: Set<DataOrigin> = emptySet(),
+    @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) val ascendingOrder: Boolean = true,
+    @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) val pageSize: Int = 1000,
+    @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) val pageToken: String? = null,
 ) {
     init {
         require(pageSize > 0) { "pageSize must be positive." }
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/response/ChangesResponse.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/response/ChangesResponse.kt
index 205c6ac..b2d38ab 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/response/ChangesResponse.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/response/ChangesResponse.kt
@@ -15,6 +15,7 @@
  */
 package androidx.health.connect.client.response
 
+import androidx.annotation.RestrictTo
 import androidx.health.connect.client.changes.Change
 
 /**
@@ -30,7 +31,8 @@
  * @see [androidx.health.connect.client.HealthConnectClient.getChanges]
  */
 class ChangesResponse
-internal constructor(
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+constructor(
     public val changes: List<Change>,
     public val nextChangesToken: String,
     @get:JvmName("hasMore") public val hasMore: Boolean,
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/response/InsertRecordsResponse.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/response/InsertRecordsResponse.kt
index aa61efc..5265587 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/response/InsertRecordsResponse.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/response/InsertRecordsResponse.kt
@@ -15,13 +15,16 @@
  */
 package androidx.health.connect.client.response
 
+import androidx.annotation.RestrictTo
+
 /**
  * Response to record insertion.
  *
  * @see [androidx.health.connect.client.HealthConnectClient.insertRecords]
  */
 public class InsertRecordsResponse
-internal constructor(
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+constructor(
     /*
      * Contains
      * [androidx.health.connect.client.metadata.Metadata.recordId] of inserted [Record] in same order as
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/response/ReadRecordResponse.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/response/ReadRecordResponse.kt
index 40afd51..375fc0d 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/response/ReadRecordResponse.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/response/ReadRecordResponse.kt
@@ -15,6 +15,7 @@
  */
 package androidx.health.connect.client.response
 
+import androidx.annotation.RestrictTo
 import androidx.health.connect.client.records.Record
 
 /**
@@ -22,4 +23,6 @@
  *
  * @see [androidx.health.connect.client.HealthConnectClient.readRecord]
  */
-class ReadRecordResponse<T : Record> internal constructor(val record: T)
+class ReadRecordResponse<T : Record>
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+constructor(val record: T)
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/response/ReadRecordsResponse.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/response/ReadRecordsResponse.kt
index e7e713e..6f51694 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/response/ReadRecordsResponse.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/response/ReadRecordsResponse.kt
@@ -15,6 +15,7 @@
  */
 package androidx.health.connect.client.response
 
+import androidx.annotation.RestrictTo
 import androidx.health.connect.client.records.Record
 
 /**
@@ -28,4 +29,5 @@
  * @see androidx.health.connect.client.HealthConnectClient.readRecords
  */
 class ReadRecordsResponse<T : Record>
-internal constructor(val records: List<T>, val pageToken: String?)
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+constructor(val records: List<T>, val pageToken: String?)
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/time/TimeRangeFilter.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/time/TimeRangeFilter.kt
index c074c2a..864e010 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/time/TimeRangeFilter.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/time/TimeRangeFilter.kt
@@ -15,6 +15,7 @@
  */
 package androidx.health.connect.client.time
 
+import androidx.annotation.RestrictTo
 import androidx.health.connect.client.records.Record
 import java.time.Instant
 import java.time.LocalDateTime
@@ -34,11 +35,12 @@
  *   zoneOffset will assume the current system zone offset at query time.
  */
 class TimeRangeFilter
-internal constructor(
-    internal val startTime: Instant? = null,
-    internal val endTime: Instant? = null,
-    internal val localStartTime: LocalDateTime? = null,
-    internal val localEndTime: LocalDateTime? = null,
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+constructor(
+    @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) val startTime: Instant? = null,
+    @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) val endTime: Instant? = null,
+    @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) val localStartTime: LocalDateTime? = null,
+    @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) val localEndTime: LocalDateTime? = null,
 ) {
     companion object {
         /**
diff --git a/health/connect/connect-testing/api/current.txt b/health/connect/connect-testing/api/current.txt
index e6f50d0..0183341 100644
--- a/health/connect/connect-testing/api/current.txt
+++ b/health/connect/connect-testing/api/current.txt
@@ -1 +1,41 @@
 // Signature format: 4.0
+package androidx.health.connect.client.testing {
+
+  @SuppressCompatibility @androidx.health.connect.client.ExperimentalHealthConnectApi public final class FakeHealthConnectClient implements androidx.health.connect.client.HealthConnectClient {
+    ctor public FakeHealthConnectClient(optional String packageName, optional java.time.Clock clock, optional androidx.health.connect.client.PermissionController permissionController);
+    method public suspend Object? aggregate(androidx.health.connect.client.request.AggregateRequest request, kotlin.coroutines.Continuation<? super androidx.health.connect.client.aggregate.AggregationResult>);
+    method public suspend Object? aggregateGroupByDuration(androidx.health.connect.client.request.AggregateGroupByDurationRequest request, kotlin.coroutines.Continuation<? super java.util.List<? extends androidx.health.connect.client.aggregate.AggregationResultGroupedByDuration>>);
+    method public suspend Object? aggregateGroupByPeriod(androidx.health.connect.client.request.AggregateGroupByPeriodRequest request, kotlin.coroutines.Continuation<? super java.util.List<? extends androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod>>);
+    method public suspend Object? deleteRecords(kotlin.reflect.KClass<? extends androidx.health.connect.client.records.Record> recordType, androidx.health.connect.client.time.TimeRangeFilter timeRangeFilter, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public suspend Object? deleteRecords(kotlin.reflect.KClass<? extends androidx.health.connect.client.records.Record> recordType, java.util.List<java.lang.String> recordIdsList, java.util.List<java.lang.String> clientRecordIdsList, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public void expireToken(String token);
+    method public suspend Object? getChanges(String changesToken, kotlin.coroutines.Continuation<? super androidx.health.connect.client.response.ChangesResponse>);
+    method public suspend Object? getChangesToken(androidx.health.connect.client.request.ChangesTokenRequest request, kotlin.coroutines.Continuation<? super java.lang.String>);
+    method public int getPageSizeGetChanges();
+    method public androidx.health.connect.client.PermissionController getPermissionController();
+    method public suspend Object? insertRecords(java.util.List<? extends androidx.health.connect.client.records.Record> records, kotlin.coroutines.Continuation<? super androidx.health.connect.client.response.InsertRecordsResponse>);
+    method public suspend <T extends androidx.health.connect.client.records.Record> Object? readRecord(kotlin.reflect.KClass<T> recordType, String recordId, kotlin.coroutines.Continuation<? super androidx.health.connect.client.response.ReadRecordResponse<T>>);
+    method public suspend <T extends androidx.health.connect.client.records.Record> Object? readRecords(androidx.health.connect.client.request.ReadRecordsRequest<T> request, kotlin.coroutines.Continuation<? super androidx.health.connect.client.response.ReadRecordsResponse<T>>);
+    method public void setPageSizeGetChanges(int);
+    method public suspend Object? updateRecords(java.util.List<? extends androidx.health.connect.client.records.Record> records, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    property public final int pageSizeGetChanges;
+    property public androidx.health.connect.client.PermissionController permissionController;
+    field public static final androidx.health.connect.client.testing.FakeHealthConnectClient.Companion Companion;
+    field public static final String DEFAULT_PACKAGE_NAME = "androidx.health.connect.test";
+  }
+
+  public static final class FakeHealthConnectClient.Companion {
+  }
+
+  @SuppressCompatibility @androidx.health.connect.client.ExperimentalHealthConnectApi public final class FakePermissionController implements androidx.health.connect.client.PermissionController {
+    ctor public FakePermissionController(optional boolean grantAll);
+    method public suspend Object? getGrantedPermissions(kotlin.coroutines.Continuation<? super java.util.Set<? extends java.lang.String>>);
+    method public void grantPermission(String permission);
+    method public void grantPermissions(java.util.Set<java.lang.String> permission);
+    method public void replaceGrantedPermissions(java.util.Set<java.lang.String> permissions);
+    method public suspend Object? revokeAllPermissions(kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public void revokePermission(String permission);
+  }
+
+}
+
diff --git a/health/connect/connect-testing/api/restricted_current.txt b/health/connect/connect-testing/api/restricted_current.txt
index e6f50d0..0183341 100644
--- a/health/connect/connect-testing/api/restricted_current.txt
+++ b/health/connect/connect-testing/api/restricted_current.txt
@@ -1 +1,41 @@
 // Signature format: 4.0
+package androidx.health.connect.client.testing {
+
+  @SuppressCompatibility @androidx.health.connect.client.ExperimentalHealthConnectApi public final class FakeHealthConnectClient implements androidx.health.connect.client.HealthConnectClient {
+    ctor public FakeHealthConnectClient(optional String packageName, optional java.time.Clock clock, optional androidx.health.connect.client.PermissionController permissionController);
+    method public suspend Object? aggregate(androidx.health.connect.client.request.AggregateRequest request, kotlin.coroutines.Continuation<? super androidx.health.connect.client.aggregate.AggregationResult>);
+    method public suspend Object? aggregateGroupByDuration(androidx.health.connect.client.request.AggregateGroupByDurationRequest request, kotlin.coroutines.Continuation<? super java.util.List<? extends androidx.health.connect.client.aggregate.AggregationResultGroupedByDuration>>);
+    method public suspend Object? aggregateGroupByPeriod(androidx.health.connect.client.request.AggregateGroupByPeriodRequest request, kotlin.coroutines.Continuation<? super java.util.List<? extends androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod>>);
+    method public suspend Object? deleteRecords(kotlin.reflect.KClass<? extends androidx.health.connect.client.records.Record> recordType, androidx.health.connect.client.time.TimeRangeFilter timeRangeFilter, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public suspend Object? deleteRecords(kotlin.reflect.KClass<? extends androidx.health.connect.client.records.Record> recordType, java.util.List<java.lang.String> recordIdsList, java.util.List<java.lang.String> clientRecordIdsList, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public void expireToken(String token);
+    method public suspend Object? getChanges(String changesToken, kotlin.coroutines.Continuation<? super androidx.health.connect.client.response.ChangesResponse>);
+    method public suspend Object? getChangesToken(androidx.health.connect.client.request.ChangesTokenRequest request, kotlin.coroutines.Continuation<? super java.lang.String>);
+    method public int getPageSizeGetChanges();
+    method public androidx.health.connect.client.PermissionController getPermissionController();
+    method public suspend Object? insertRecords(java.util.List<? extends androidx.health.connect.client.records.Record> records, kotlin.coroutines.Continuation<? super androidx.health.connect.client.response.InsertRecordsResponse>);
+    method public suspend <T extends androidx.health.connect.client.records.Record> Object? readRecord(kotlin.reflect.KClass<T> recordType, String recordId, kotlin.coroutines.Continuation<? super androidx.health.connect.client.response.ReadRecordResponse<T>>);
+    method public suspend <T extends androidx.health.connect.client.records.Record> Object? readRecords(androidx.health.connect.client.request.ReadRecordsRequest<T> request, kotlin.coroutines.Continuation<? super androidx.health.connect.client.response.ReadRecordsResponse<T>>);
+    method public void setPageSizeGetChanges(int);
+    method public suspend Object? updateRecords(java.util.List<? extends androidx.health.connect.client.records.Record> records, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    property public final int pageSizeGetChanges;
+    property public androidx.health.connect.client.PermissionController permissionController;
+    field public static final androidx.health.connect.client.testing.FakeHealthConnectClient.Companion Companion;
+    field public static final String DEFAULT_PACKAGE_NAME = "androidx.health.connect.test";
+  }
+
+  public static final class FakeHealthConnectClient.Companion {
+  }
+
+  @SuppressCompatibility @androidx.health.connect.client.ExperimentalHealthConnectApi public final class FakePermissionController implements androidx.health.connect.client.PermissionController {
+    ctor public FakePermissionController(optional boolean grantAll);
+    method public suspend Object? getGrantedPermissions(kotlin.coroutines.Continuation<? super java.util.Set<? extends java.lang.String>>);
+    method public void grantPermission(String permission);
+    method public void grantPermissions(java.util.Set<java.lang.String> permission);
+    method public void replaceGrantedPermissions(java.util.Set<java.lang.String> permissions);
+    method public suspend Object? revokeAllPermissions(kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public void revokePermission(String permission);
+  }
+
+}
+
diff --git a/health/connect/connect-testing/build.gradle b/health/connect/connect-testing/build.gradle
index 3d2bacd..57c2591 100644
--- a/health/connect/connect-testing/build.gradle
+++ b/health/connect/connect-testing/build.gradle
@@ -22,6 +22,7 @@
  * modifying its settings.
  */
 import androidx.build.LibraryType
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
 
 plugins {
     id("AndroidXPlugin")
@@ -31,11 +32,23 @@
 
 dependencies {
     api(libs.kotlinStdlib)
-    // Add dependencies here
+    implementation project(':health:connect:connect-client')
+    implementation(project(":health:connect:connect-client-proto"))
+
+    testImplementation(libs.kotlinTest)
+    testImplementation(libs.junit)
+    testImplementation(libs.truth)
+    testImplementation(libs.kotlinCoroutinesTest)
 }
 
 android {
+    defaultConfig {
+        minSdkVersion 26
+    }
     namespace "androidx.health.connect.testing"
+    testOptions.unitTests.includeAndroidResources = true
+    compileSdk = 34
+    compileSdkExtension = 10
 }
 
 androidx {
@@ -43,5 +56,11 @@
     mavenVersion = LibraryVersions.HEALTH_CONNECT_TESTING_QUARANTINE
     type = LibraryType.PUBLISHED_TEST_LIBRARY
     inceptionYear = "2024"
-    description = "Test HealthConnect by providing a fake HealthConnectClient. This library should be added as a test dependency when writting unit tests that call HealthConnect APIs."
+    description = "Test utils for Health Connect. This library should be added as a test dependency when writing unit tests that call HealthConnect APIs."
+}
+
+tasks.withType(KotlinCompile).configureEach {
+    kotlinOptions {
+        freeCompilerArgs += ["-opt-in=kotlin.RequiresOptIn", "-opt-in=androidx.health.connect.client.ExperimentalHealthConnectApi"]
+    }
 }
diff --git a/health/connect/connect-testing/src/main/java/androidx/health/connect/client/testing/FakeHealthConnectClient.kt b/health/connect/connect-testing/src/main/java/androidx/health/connect/client/testing/FakeHealthConnectClient.kt
new file mode 100644
index 0000000..3b5ac8d
--- /dev/null
+++ b/health/connect/connect-testing/src/main/java/androidx/health/connect/client/testing/FakeHealthConnectClient.kt
@@ -0,0 +1,376 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.health.connect.client.testing
+
+import androidx.health.connect.client.ExperimentalHealthConnectApi
+import androidx.health.connect.client.HealthConnectClient
+import androidx.health.connect.client.PermissionController
+import androidx.health.connect.client.aggregate.AggregationResult
+import androidx.health.connect.client.aggregate.AggregationResultGroupedByDuration
+import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod
+import androidx.health.connect.client.changes.Change
+import androidx.health.connect.client.changes.DeletionChange
+import androidx.health.connect.client.changes.UpsertionChange
+import androidx.health.connect.client.impl.converters.datatype.RECORDS_TYPE_NAME_MAP
+import androidx.health.connect.client.impl.converters.records.toProto
+import androidx.health.connect.client.impl.converters.records.toRecord
+import androidx.health.connect.client.records.Record
+import androidx.health.connect.client.request.AggregateGroupByDurationRequest
+import androidx.health.connect.client.request.AggregateGroupByPeriodRequest
+import androidx.health.connect.client.request.AggregateRequest
+import androidx.health.connect.client.request.ChangesTokenRequest
+import androidx.health.connect.client.request.ReadRecordsRequest
+import androidx.health.connect.client.response.ChangesResponse
+import androidx.health.connect.client.response.InsertRecordsResponse
+import androidx.health.connect.client.response.ReadRecordResponse
+import androidx.health.connect.client.response.ReadRecordsResponse
+import androidx.health.connect.client.time.TimeRangeFilter
+import java.time.Clock
+import kotlin.reflect.KClass
+
+/**
+ * Fake [HealthConnectClient] to be used in tests for components that use it as a dependency.
+ *
+ * Features:
+ * * Add, remove, delete and read records using an in-memory object, supporting pagination.
+ * * Token generation and change tracking.
+ *
+ * Note that this fake does not check for permissions.
+ *
+ * @param packageName the name of the package to use to generate unique record IDs.
+ * @param clock used to close open-ended [TimeRangeFilter]s and record update times.
+ * @param permissionController grants and revokes permissions.
+ */
+@ExperimentalHealthConnectApi
+public class FakeHealthConnectClient(
+    private val packageName: String = DEFAULT_PACKAGE_NAME,
+    private val clock: Clock = Clock.systemDefaultZone(),
+    override val permissionController: PermissionController = FakePermissionController()
+) : HealthConnectClient {
+
+    private val idsToRecords: MutableMap<String, Record> = mutableMapOf()
+    private val deletedIdsToRecords: MutableMap<String, Record> = mutableMapOf()
+
+    // Changes are tracked with a map of changes. The key is incremented with each change.
+    private val tokens = mutableMapOf<String, TokenInfo>()
+    private val timeToChanges: MutableMap<Long, Change> = mutableMapOf()
+    private var timeToChangesLastKey = 0L
+
+    private var idCounter = 0
+
+    /**
+     * Overrides the page size to test pagination when calling [getChanges].
+     *
+     * This is typically used with a low number (such as 2) so that a low number of inserted records
+     * (such as 3) generate multiple pages. Use it to test token expiration as well.
+     */
+    public var pageSizeGetChanges: Int = 1000
+
+    /**
+     * Fake implementation that inserts one or more [Record]s into the in-memory store.
+     *
+     * Supports deduplication of
+     * [androidx.health.connect.client.records.metadata.Metadata.clientRecordId]s using
+     * [androidx.health.connect.client.records.metadata.Metadata.clientRecordVersion] to determine
+     * precedence.
+     */
+    override suspend fun insertRecords(records: List<Record>): InsertRecordsResponse {
+        val recordIdsList = mutableListOf<String>()
+        records.forEach { record ->
+            val recordId =
+                record.metadata.clientRecordId?.toRecordId(packageName) ?: "testHCid${idCounter++}"
+            recordIdsList += recordId
+            val insertedRecord =
+                toRecord(
+                    record
+                        .toProto()
+                        .toBuilder()
+                        .setUid(recordId)
+                        .setUpdateTimeMillis(clock.millis())
+                        .build()
+                )
+            // If the recordId exists and the existing clientRecordVersion is higher, don't insert.
+            val newClientRecordVersion = insertedRecord.metadata.clientRecordVersion
+            val existingClientRecordVersion =
+                idsToRecords[recordId]?.metadata?.clientRecordVersion ?: -1
+            if (newClientRecordVersion >= existingClientRecordVersion) {
+                idsToRecords[recordId] = insertedRecord
+                addUpsertionChange(insertedRecord)
+            }
+        }
+        return InsertRecordsResponse(recordIdsList)
+    }
+
+    override suspend fun updateRecords(records: List<Record>) {
+        // Check if all records belong to the package
+        if (records.any { it.packageName != packageName }) {
+            throw SecurityException("Trying to delete records owned by another package")
+        }
+
+        // Fake implementation
+        records.forEach { record ->
+            val recordId =
+                record.metadata.clientRecordId?.toRecordId(packageName) ?: record.metadata.id
+
+            val updatedRecord =
+                toRecord(record.toProto().toBuilder().setUpdateTimeMillis(clock.millis()).build())
+            idsToRecords[recordId] = updatedRecord
+            removeUpsertion(recordId)
+            addUpsertionChange(updatedRecord)
+        }
+    }
+
+    override suspend fun deleteRecords(
+        recordType: KClass<out Record>,
+        recordIdsList: List<String>,
+        clientRecordIdsList: List<String>
+    ) {
+        // Check if all records belong to the package in recordsIdsList
+        if (
+            recordIdsList
+                .asSequence()
+                .mapNotNull { idsToRecords[it]?.packageName }
+                .any { it != packageName }
+        ) {
+            throw SecurityException("Trying to delete records owned by another package")
+        }
+
+        // Check if all records belong to the package in clientRecordIdsList
+        if (
+            clientRecordIdsList
+                .asSequence()
+                .mapNotNull { idsToRecords[it.toRecordId(packageName)]?.packageName }
+                .any { it != packageName }
+        ) {
+            throw SecurityException("Trying to delete records owned by another package")
+        }
+
+        // Fake implementation
+        recordIdsList.forEach { recordId ->
+            idsToRecords[recordId]?.let { deletedIdsToRecords[recordId] = it }
+            idsToRecords.remove(recordId)
+            removeUpsertion(recordId)
+            addDeletionChange(recordId)
+        }
+        clientRecordIdsList.forEach {
+            val recordId = it.toRecordId(packageName)
+            idsToRecords[recordId]?.let { deletedIdsToRecords[recordId] = it }
+            idsToRecords.remove(recordId)
+            addDeletionChange(recordId)
+        }
+    }
+
+    override suspend fun deleteRecords(
+        recordType: KClass<out Record>,
+        timeRangeFilter: TimeRangeFilter
+    ) {
+        val recordIdsToRemove =
+            idsToRecords
+                .filterValues { record ->
+                    record::class == recordType && record.isWithin(timeRangeFilter, clock)
+                }
+                .keys
+        for (recordId in recordIdsToRemove) {
+            idsToRecords[recordId]?.let { deletedIdsToRecords[recordId] = it }
+            idsToRecords.remove(recordId)
+            removeUpsertion(recordId)
+            addDeletionChange(recordId)
+        }
+    }
+
+    @Suppress("UNCHECKED_CAST")
+    override suspend fun <T : Record> readRecord(
+        recordType: KClass<T>,
+        recordId: String
+    ): ReadRecordResponse<T> {
+        return ReadRecordResponse(idsToRecords[recordId.toRecordId(packageName)] as T)
+    }
+
+    /**
+     * Returns records that match the attributes in a [ReadRecordsRequest].
+     *
+     * Features a simple paging implementation. Records must not be updated in between calls.
+     *
+     * @throws IllegalStateException if paging is requested.
+     */
+    @Suppress("UNCHECKED_CAST")
+    public override suspend fun <T : Record> readRecords(
+        request: ReadRecordsRequest<T>
+    ): ReadRecordsResponse<T> {
+        val startIndex = request.pageToken?.toIntOrNull() ?: 0
+        val allRecords =
+            idsToRecords
+                .filterValues { record ->
+                    record::class == request.recordType &&
+                        record.isWithin(request.timeRangeFilter, clock) &&
+                        (request.dataOriginFilter.isEmpty() ||
+                            request.dataOriginFilter.contains(record.metadata.dataOrigin))
+                }
+                .values
+                .map { record -> record as T }
+
+        val recordsPending = allRecords.drop(startIndex)
+        val hasMorePages = recordsPending.size > request.pageSize
+
+        // Increment the token if there are more pages
+        val nextPageToken =
+            if (hasMorePages) {
+                // Next page token
+                (request.pageToken?.toLongOrNull() ?: 0) + request.pageSize
+            } else {
+                null
+            }
+        // Fake implementation
+        return ReadRecordsResponse(
+            records = recordsPending.take(request.pageSize),
+            pageToken = nextPageToken?.toString()
+        )
+    }
+
+    /** @throws IllegalStateException if no overrides are configured. */
+    override suspend fun aggregate(request: AggregateRequest): AggregationResult {
+        TODO("This function should be mocked in tests.")
+    }
+
+    /** @throws IllegalStateException if no overrides are configured. */
+    override suspend fun aggregateGroupByDuration(
+        request: AggregateGroupByDurationRequest
+    ): List<AggregationResultGroupedByDuration> {
+        TODO("This function should be mocked in tests.")
+    }
+
+    /** @throws IllegalStateException if no overrides are configured. */
+    override suspend fun aggregateGroupByPeriod(
+        request: AggregateGroupByPeriodRequest
+    ): List<AggregationResultGroupedByPeriod> {
+        TODO("This function should be mocked in tests.")
+    }
+
+    /**
+     * Returns a fake token which contains the key to the next change. Used with [getChanges] to
+     * track changes from the moment this function is called.
+     */
+    override suspend fun getChangesToken(request: ChangesTokenRequest): String {
+        if (request.recordTypes.isEmpty()) {
+            throw IllegalArgumentException("Record types must not be empty")
+        }
+        if (request.dataOriginFilters.isNotEmpty()) {
+            throw UnsupportedOperationException(
+                "Data origin filters are not supported in the " +
+                    "fake. Use [StubResponse]s with [overrides.getChangesToken] and " +
+                    "[overrides.getChanges] to set a response."
+            )
+        }
+        val nextInstant = timeToChangesLastKey + 1
+        val newToken = generateNewToken(nextInstant, request.recordTypes)
+        tokens[newToken] = TokenInfo(recordTypes = request.recordTypes, time = nextInstant)
+        return newToken
+    }
+
+    /** Set a particular token as expired. This is used to test the response of [getChanges]. */
+    public fun expireToken(token: String) {
+        val tokenInfo = tokens[token] ?: throw IllegalStateException("Token not found")
+        tokens[token] = tokenInfo.copy(expired = true)
+    }
+
+    private fun generateNewToken(time: Long, recordTypes: Set<KClass<out Record>>): String {
+        val recordTypesHash =
+            recordTypes
+                .mapNotNull { record ->
+                    // Get a string representation of each record
+                    RECORDS_TYPE_NAME_MAP.filterValues { it == record }.keys.firstOrNull()
+                }
+                .sorted() // Sort them alphabetically so that the order doesn't matter
+                .takeIf { it.isNotEmpty() }
+                ?.joinToString(",", prefix = "_") ?: ""
+
+        return "$time$recordTypesHash"
+    }
+
+    override suspend fun getChanges(changesToken: String): ChangesResponse {
+        // The token is related to a moment in time in [tokenToTime] and to a set of Record types
+        // in [tokenToRecordTypes].
+        val tokenInfo = tokens[changesToken] ?: throw IllegalStateException("Token not found")
+        val timeInToken = tokenInfo.time
+        val recordTypes = tokenInfo.recordTypes
+
+        val changes =
+            timeToChanges
+                .filterKeys { key -> key >= timeInToken }
+                .filterValues { change: Change ->
+                    // Only return changes whose records are of the requested types
+                    when (change) {
+                        is UpsertionChange -> recordTypes.contains(change.record::class)
+                        is DeletionChange -> {
+                            val record = deletedIdsToRecords[change.recordId] ?: false
+                            recordTypes.contains(record::class)
+                        }
+                        else -> throw NotImplementedError()
+                    }
+                }
+                .values
+        val hasMoreChanges = changes.size > pageSizeGetChanges
+        val nextChangesToken =
+            if (hasMoreChanges) {
+                // Next page token
+                generateNewToken(timeInToken + pageSizeGetChanges, recordTypes)
+            } else {
+                // Future changes token
+                generateNewToken(timeToChangesLastKey + 1, recordTypes)
+            }
+
+        // Store metadata for new token
+        tokens[nextChangesToken] = tokenInfo.copy(time = tokenInfo.time + pageSizeGetChanges)
+
+        return ChangesResponse(
+            changes.take(pageSizeGetChanges).toList(),
+            hasMore = hasMoreChanges,
+            changesTokenExpired = tokenInfo.expired,
+            nextChangesToken = nextChangesToken
+        )
+    }
+
+    private fun String.toRecordId(packageName: String): String {
+        return "$packageName:$this"
+    }
+
+    private fun addDeletionChange(recordId: String) {
+        timeToChanges[++timeToChangesLastKey] = DeletionChange(recordId)
+    }
+
+    private fun addUpsertionChange(updatedRecord: Record) {
+        timeToChanges[++timeToChangesLastKey] = UpsertionChange(updatedRecord)
+    }
+
+    private fun removeUpsertion(recordId: String) {
+        timeToChanges
+            .filterValues { it is UpsertionChange && it.record.metadata.id == recordId }
+            .keys
+            .forEach { timeToChanges.remove(it) }
+    }
+
+    public companion object {
+        /** Default package name used in [FakeHealthConnectClient]. */
+        public const val DEFAULT_PACKAGE_NAME: String = "androidx.health.connect.test"
+    }
+}
+
+private data class TokenInfo(
+    val time: Long,
+    val recordTypes: Set<KClass<out Record>>,
+    val expired: Boolean = false
+)
diff --git a/health/connect/connect-testing/src/main/java/androidx/health/connect/client/testing/FakePermissionController.kt b/health/connect/connect-testing/src/main/java/androidx/health/connect/client/testing/FakePermissionController.kt
new file mode 100644
index 0000000..539f319
--- /dev/null
+++ b/health/connect/connect-testing/src/main/java/androidx/health/connect/client/testing/FakePermissionController.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.health.connect.client.testing
+
+import androidx.health.connect.client.ExperimentalHealthConnectApi
+import androidx.health.connect.client.HealthConnectClient
+import androidx.health.connect.client.PermissionController
+import androidx.health.connect.client.permission.HealthPermission
+
+/**
+ * A fake [PermissionController] that enables full control of permissions in tests for a
+ * [HealthConnectClient].
+ *
+ * @param grantAll grants all permissions on creation
+ */
+@ExperimentalHealthConnectApi
+public class FakePermissionController(grantAll: Boolean = true) : PermissionController {
+    private val grantedPermissions =
+        if (grantAll) HealthPermission.ALL_PERMISSIONS.toMutableSet() else mutableSetOf()
+
+    /** Replaces the set of permissions returned by [getGrantedPermissions] with a new set. */
+    public fun replaceGrantedPermissions(permissions: Set<String>) {
+        grantedPermissions.clear()
+        grantedPermissions.addAll(permissions)
+    }
+
+    /** Adds a permission to the set of granted permissions returned by [getGrantedPermissions]. */
+    public fun grantPermission(permission: String) {
+        grantedPermissions.add(permission)
+    }
+
+    /** Adds permissions to the set of granted permissions returned by [getGrantedPermissions]. */
+    public fun grantPermissions(permission: Set<String>) {
+        grantedPermissions.addAll(permission)
+    }
+
+    /**
+     * Removes a permission from the set of granted permissions returned by [getGrantedPermissions].
+     */
+    public fun revokePermission(permission: String) {
+        grantedPermissions.remove(permission)
+    }
+
+    /** Returns a fake set of permissions. */
+    override suspend fun getGrantedPermissions(): Set<String> {
+        return grantedPermissions.toSet()
+    }
+
+    /** Clears the set of permissions returned by [getGrantedPermissions]. */
+    override suspend fun revokeAllPermissions() {
+        grantedPermissions.clear()
+    }
+}
diff --git a/health/connect/connect-testing/src/main/java/androidx/health/connect/client/testing/RecordTestUtils.kt b/health/connect/connect-testing/src/main/java/androidx/health/connect/client/testing/RecordTestUtils.kt
new file mode 100644
index 0000000..3c3dd99
--- /dev/null
+++ b/health/connect/connect-testing/src/main/java/androidx/health/connect/client/testing/RecordTestUtils.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.health.connect.client.testing
+
+import androidx.health.connect.client.impl.converters.records.endTime
+import androidx.health.connect.client.impl.converters.records.startTime
+import androidx.health.connect.client.impl.converters.records.time
+import androidx.health.connect.client.impl.converters.records.toProto
+import androidx.health.connect.client.impl.converters.records.zoneOffset
+import androidx.health.connect.client.records.Record
+import androidx.health.connect.client.time.TimeRangeFilter
+import androidx.health.platform.client.proto.DataProto
+import java.time.Clock
+import java.time.Instant
+import java.time.LocalDateTime
+import java.time.ZoneId
+
+internal fun Record.isWithin(filter: TimeRangeFilter, clock: Clock): Boolean {
+    val proto: DataProto.DataPoint = toProto()
+    val timeRangeFilter = filter.sanitize(clock)
+
+    if (timeRangeFilter.isLocalBasedFilter()) {
+        if (proto.hasInstantTimeMillis()) {
+            val time =
+                LocalDateTime.ofInstant(proto.time, proto.zoneOffset ?: ZoneId.systemDefault())
+            return !time.isBefore(timeRangeFilter.localStartTime) &&
+                timeRangeFilter.localEndTime!!.isAfter(time)
+        }
+        val startTime =
+            LocalDateTime.ofInstant(proto.startTime, proto.zoneOffset ?: ZoneId.systemDefault())
+        return !startTime.isBefore(timeRangeFilter.localStartTime) &&
+            timeRangeFilter.localEndTime!!.isAfter(startTime)
+    }
+
+    if (proto.hasInstantTimeMillis()) {
+        return proto.time >= timeRangeFilter.startTime && // Inclusive
+            proto.time.isBefore(timeRangeFilter.endTime) // Exclusive
+    }
+
+    return proto.startTime >= timeRangeFilter.startTime && // Inclusive
+        proto.endTime.isBefore(timeRangeFilter.endTime) // Exclusive
+}
+
+private fun TimeRangeFilter.sanitize(clock: Clock): TimeRangeFilter {
+    if (isLocalBasedFilter()) {
+        return TimeRangeFilter.between(
+            startTime =
+                localStartTime ?: LocalDateTime.ofInstant(Instant.EPOCH, ZoneId.systemDefault()),
+            endTime =
+                localEndTime ?: LocalDateTime.ofInstant(clock.instant(), ZoneId.systemDefault())
+        )
+    }
+    return TimeRangeFilter.between(
+        startTime = startTime ?: Instant.EPOCH,
+        endTime = endTime ?: clock.instant()
+    )
+}
+
+private fun TimeRangeFilter.isLocalBasedFilter(): Boolean {
+    return localStartTime != null || localEndTime != null
+}
+
+/** Gets the package name from metadata */
+internal val Record.packageName: String
+    get() = this.metadata.dataOrigin.packageName
diff --git a/health/connect/connect-testing/src/test/java/androidx/health/connect/client/testing/FakeHealthConnectClientChangesTest.kt b/health/connect/connect-testing/src/test/java/androidx/health/connect/client/testing/FakeHealthConnectClientChangesTest.kt
new file mode 100644
index 0000000..bf7a5a1
--- /dev/null
+++ b/health/connect/connect-testing/src/test/java/androidx/health/connect/client/testing/FakeHealthConnectClientChangesTest.kt
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.health.connect.client.testing
+
+import androidx.health.connect.client.changes.DeletionChange
+import androidx.health.connect.client.changes.UpsertionChange
+import androidx.health.connect.client.records.Record
+import androidx.health.connect.client.records.metadata.DataOrigin
+import androidx.health.connect.client.request.ChangesTokenRequest
+import androidx.health.connect.client.request.ReadRecordsRequest
+import androidx.health.connect.client.testing.testdata.generateRunningRecords
+import androidx.health.connect.client.testing.testdata.hydrationRecord1
+import androidx.health.connect.client.testing.testdata.runRecord1
+import androidx.health.connect.client.time.TimeRangeFilter
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.runTest
+import org.junit.Assert
+import org.junit.Test
+
+/** Unit tests for functions related to changes in [FakeHealthConnectClient]. */
+class FakeHealthConnectClientChangesTest {
+
+    @Test
+    fun defaultToken_isOne() = runTest {
+        val fake = FakeHealthConnectClient()
+        val token = fake.getChangesToken(ChangesTokenRequest(recordTypes = setOf(Record::class)))
+        assertThat(token).startsWith("1")
+    }
+
+    @Test
+    fun insertAndGetChanges_returnsUpsertionChange() = runTest {
+        val fake = FakeHealthConnectClient()
+
+        val changesToken =
+            fake.getChangesToken(ChangesTokenRequest(recordTypes = setOf(runRecord1::class)))
+        fake.insertRecords(listOf(runRecord1))
+        val changesResponse = fake.getChanges(changesToken)
+
+        assertThat(changesResponse.changes).hasSize(1)
+        assertThat(changesResponse.changes.first()).isInstanceOf(UpsertionChange::class.java)
+    }
+
+    @Test
+    fun insertAndDeleteAndGetChanges_returnsUpsertionAndDeletionChanges() = runTest {
+        val fake = FakeHealthConnectClient()
+
+        val changesToken =
+            fake.getChangesToken(ChangesTokenRequest(recordTypes = setOf(runRecord1::class)))
+        fake.insertRecords(listOf(runRecord1))
+        fake.deleteRecords(
+            runRecord1::class,
+            clientRecordIdsList = listOf(runRecord1.metadata.clientRecordId!!),
+            recordIdsList = emptyList()
+        )
+        val changesResponse = fake.getChanges(changesToken)
+
+        assertThat(changesResponse.changes).hasSize(2)
+        assertThat((changesResponse.changes[0] as UpsertionChange).record.metadata.clientRecordId)
+            .isEqualTo(runRecord1.metadata.clientRecordId)
+        assertThat(changesResponse.changes[1]).isInstanceOf(DeletionChange::class.java)
+    }
+
+    @Test
+    fun insertAndDeleteAndGetChangesByRecordIds_returnsOnlyDeletionChanges() = runTest {
+        val fake = FakeHealthConnectClient()
+
+        val changesToken =
+            fake.getChangesToken(ChangesTokenRequest(recordTypes = setOf(runRecord1::class)))
+        fake.insertRecords(listOf(runRecord1))
+        val recordWithId =
+            fake.readRecords(
+                ReadRecordsRequest(
+                    timeRangeFilter =
+                        TimeRangeFilter(
+                            startTime = runRecord1.startTime.minusSeconds(1),
+                            endTime = runRecord1.endTime.plusSeconds(1)
+                        ),
+                    recordType = runRecord1::class
+                )
+            )
+        fake.deleteRecords(
+            runRecord1::class,
+            recordIdsList = listOf(recordWithId.records.first().metadata.id),
+            clientRecordIdsList = emptyList()
+        )
+        val changesResponse = fake.getChanges(changesToken)
+
+        assertThat(changesResponse.changes).hasSize(1)
+        assertThat(changesResponse.changes[0]).isInstanceOf(DeletionChange::class.java)
+    }
+
+    @Test
+    fun pagination_onePage() = runTest {
+        val fake = FakeHealthConnectClient()
+        val records = generateRunningRecords(3)
+
+        val changesToken =
+            fake.getChangesToken(ChangesTokenRequest(recordTypes = setOf(records.first()::class)))
+        fake.insertRecords(records)
+        val changesResponse = fake.getChanges(changesToken)
+
+        assertThat(changesResponse.changes).hasSize(3)
+        assertThat(changesResponse.hasMore).isFalse()
+        assertThat(changesResponse.nextChangesToken).startsWith("4")
+    }
+
+    @Test
+    fun pagination_twoPages() = runTest {
+        val fake = FakeHealthConnectClient().apply { pageSizeGetChanges = 2 }
+        val records = generateRunningRecords(3)
+
+        val changesToken =
+            fake.getChangesToken(ChangesTokenRequest(recordTypes = setOf(records.first()::class)))
+        fake.insertRecords(records)
+        val changesResponse = fake.getChanges(changesToken)
+
+        assertThat(changesResponse.changes).hasSize(2)
+        assertThat(changesResponse.hasMore).isTrue()
+        assertThat(changesResponse.nextChangesToken).startsWith("3")
+    }
+
+    @Test
+    fun pagination_twoPages_secondPageCorrect() = runTest {
+        val fake = FakeHealthConnectClient().apply { pageSizeGetChanges = 2 }
+        val records = generateRunningRecords(3)
+
+        val changesToken =
+            fake.getChangesToken(ChangesTokenRequest(recordTypes = setOf(records.first()::class)))
+        fake.insertRecords(records)
+        val page1 = fake.getChanges(changesToken)
+        val page2 = fake.getChanges(page1.nextChangesToken)
+
+        assertThat(page2.changes).hasSize(1)
+        assertThat(page2.hasMore).isFalse()
+        assertThat(page2.nextChangesToken).startsWith("4")
+    }
+
+    @Test
+    fun getChangesToken_differentFilters_differentResults() = runTest {
+        val fake = FakeHealthConnectClient()
+
+        val changesToken1 =
+            fake.getChangesToken(ChangesTokenRequest(recordTypes = setOf(runRecord1::class)))
+        val changesToken2 =
+            fake.getChangesToken(ChangesTokenRequest(recordTypes = setOf(hydrationRecord1::class)))
+
+        fake.insertRecords(listOf(runRecord1))
+        val changesResponse1 = fake.getChanges(changesToken1)
+        val changesResponse2 = fake.getChanges(changesToken2)
+
+        assertThat(changesResponse1.changes).hasSize(1)
+        assertThat(changesResponse2.changes).hasSize(0)
+        fake.insertRecords(listOf(hydrationRecord1))
+
+        val changesResponse2AfterInsert = fake.getChanges(changesToken2)
+        assertThat(changesResponse2AfterInsert.changes).hasSize(1)
+    }
+
+    @Test
+    fun getChangesTokenExpiration_resultWithExpiredToken() = runTest {
+        val fake = FakeHealthConnectClient()
+        val records = generateRunningRecords(3)
+
+        val changesToken =
+            fake.getChangesToken(ChangesTokenRequest(recordTypes = setOf(runRecord1::class)))
+        fake.expireToken(changesToken)
+        fake.insertRecords(records)
+        val changesResponse = fake.getChanges(changesToken)
+
+        assertThat(changesResponse.changesTokenExpired).isTrue()
+    }
+
+    @Test
+    fun getChangesDefaultTokenExpiration_noExpiredToken() = runTest {
+        val fake = FakeHealthConnectClient()
+        val records = generateRunningRecords(3)
+
+        val changesToken =
+            fake.getChangesToken(ChangesTokenRequest(recordTypes = setOf(records.first()::class)))
+        fake.insertRecords(records)
+        val changesResponse = fake.getChanges(changesToken)
+
+        assertThat(changesResponse.changesTokenExpired).isFalse()
+    }
+
+    @Test
+    fun getChangesToken_noRecordType_throws() = runTest {
+        val fake = FakeHealthConnectClient()
+        Assert.assertThrows(IllegalArgumentException::class.java) {
+            runBlocking { fake.getChangesToken(ChangesTokenRequest(recordTypes = emptySet())) }
+        }
+    }
+
+    @Test
+    fun getChangesToken_dataOriginsSet_throws() = runTest {
+        val fake = FakeHealthConnectClient()
+        Assert.assertThrows(UnsupportedOperationException::class.java) {
+            runBlocking {
+                fake.getChangesToken(
+                    ChangesTokenRequest(
+                        recordTypes = setOf(Record::class),
+                        dataOriginFilters = setOf(DataOrigin("test"))
+                    )
+                )
+            }
+        }
+    }
+}
diff --git a/health/connect/connect-testing/src/test/java/androidx/health/connect/client/testing/FakeHealthConnectClientClockTest.kt b/health/connect/connect-testing/src/test/java/androidx/health/connect/client/testing/FakeHealthConnectClientClockTest.kt
new file mode 100644
index 0000000..c40a364
--- /dev/null
+++ b/health/connect/connect-testing/src/test/java/androidx/health/connect/client/testing/FakeHealthConnectClientClockTest.kt
@@ -0,0 +1,289 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.health.connect.client.testing
+
+import androidx.health.connect.client.records.ExerciseSessionRecord
+import androidx.health.connect.client.records.HeightRecord
+import androidx.health.connect.client.records.metadata.Metadata
+import androidx.health.connect.client.request.ReadRecordsRequest
+import androidx.health.connect.client.time.TimeRangeFilter
+import androidx.health.connect.client.units.Length
+import com.google.common.truth.Truth.assertThat
+import java.time.Clock
+import java.time.Instant
+import java.time.LocalDateTime
+import java.time.ZoneOffset
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+
+/**
+ * Tests for the [Clock] parameter in [FakeHealthConnectClient] which is used for open-ended time
+ * ranges. It unit tests the [isWithin] and [sanitize] functions.
+ */
+class FakeHealthConnectClientClockTest {
+    private val fixedInstant = Instant.parse("2000-01-01T10:00:00Z")
+
+    private val clock = Clock.fixed(fixedInstant, ZoneOffset.UTC)
+    private val zoneOffset = clock.zone.rules.getOffset(fixedInstant)
+
+    private val record1 =
+        ExerciseSessionRecord(
+            startTime = fixedInstant.minusSeconds(60),
+            startZoneOffset = zoneOffset,
+            endTime = fixedInstant.minusSeconds(30),
+            endZoneOffset = zoneOffset,
+            exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_RUNNING,
+            title = "Record1",
+            exerciseRoute = null,
+            metadata = Metadata(clientRecordId = "FakeHealthConnectData1")
+        )
+
+    private val record2 =
+        ExerciseSessionRecord(
+            startTime = fixedInstant.minusSeconds(29),
+            startZoneOffset = zoneOffset,
+            endTime = fixedInstant.minusSeconds(1),
+            endZoneOffset = zoneOffset,
+            exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_RUNNING,
+            title = "Record2",
+            exerciseRoute = null,
+            metadata = Metadata(clientRecordId = "FakeHealthConnectData2")
+        )
+
+    private val fake =
+        FakeHealthConnectClient(clock = clock).apply {
+            runBlocking { insertRecords(listOf(record1, record2)) }
+        }
+
+    @Test
+    fun timeRangeFilter_openEnded_endTime() = runTest {
+        // Read records that start when record 2 starts
+        val records =
+            fake.readRecords(
+                ReadRecordsRequest(
+                    record1::class,
+                    // No endTime, defaults to clock
+                    timeRangeFilter = TimeRangeFilter(startTime = record2.startTime),
+                )
+            )
+
+        // Only record2 should be returned
+        assertThat(records.records).hasSize(1)
+        assertThat(records.records.first().title).isEqualTo(record2.title)
+    }
+
+    @Test
+    fun timeRangeFilter_openEndedEndTime_clockMiddle() = runTest {
+        // Record 2 is in the future for this clock
+        val clock = Clock.fixed(record1.endTime.plusMillis(1), ZoneOffset.UTC)
+        val fake =
+            FakeHealthConnectClient(clock = clock).apply {
+                runBlocking { insertRecords(listOf(record1, record2)) }
+            }
+        val records =
+            fake.readRecords(
+                ReadRecordsRequest(
+                    record1::class,
+                    // No endTime, defaults to clock
+                    timeRangeFilter = TimeRangeFilter(startTime = record1.startTime.minusMillis(1)),
+                )
+            )
+
+        // Only record1 should be returned
+        assertThat(records.records).hasSize(1)
+        assertThat(records.records.first().title).isEqualTo(record1.title)
+    }
+
+    @Test
+    fun timeRangeFilter_openEndedStartTimeEpoch_endTimeIsEnd() = runTest {
+
+        // Read records that end when record 2 ends
+        val records =
+            fake.readRecords(
+                ReadRecordsRequest(
+                    record1::class,
+                    // No startTime defaults to EPOCH
+                    timeRangeFilter = TimeRangeFilter(endTime = record2.endTime.plusMillis(1)),
+                )
+            )
+
+        // Both records should be returned
+        assertThat(records.records).hasSize(2)
+    }
+
+    @Test
+    fun timeRangeFilter_openEndedStartTimeEpoch_endTimeIsMiddle() = runTest {
+
+        // Read records that end when record 1 ends
+        val records =
+            fake.readRecords(
+                ReadRecordsRequest(
+                    record1::class,
+                    // No startTime defaults to EPOCH
+                    timeRangeFilter = TimeRangeFilter(endTime = record1.endTime.plusMillis(1)),
+                )
+            )
+
+        // Only record1 should be returned
+        assertThat(records.records).hasSize(1)
+        assertThat(records.records.first().title).isEqualTo(record1.title)
+    }
+
+    @Test
+    fun timeRangeFilterlocalTime_noEndTime() = runTest {
+
+        // Read records that end when record 1 ends
+        val records =
+            fake.readRecords(
+                ReadRecordsRequest(
+                    record1::class,
+                    // No endTime, defaults to clock
+                    timeRangeFilter =
+                        TimeRangeFilter(
+                            localStartTime = LocalDateTime.of(2000, 1, 1, 9, 59, 30, 1)
+                        ),
+                )
+            )
+
+        // Only record1 should be returned
+        assertThat(records.records).hasSize(1)
+        assertThat(records.records.first().title).isEqualTo(record2.title)
+    }
+
+    @Test
+    fun timeRangeFilter_noEndTimeInstant() = runTest {
+        // Given a record with a fixed time, before the clock.
+        val heightRecord =
+            HeightRecord(
+                time = fixedInstant.minusSeconds(29),
+                metadata = Metadata(clientRecordId = "HeightRecord#1"),
+                height = Length.meters(1.8),
+                zoneOffset = zoneOffset
+            )
+        val fake =
+            FakeHealthConnectClient(clock = clock).apply {
+                runBlocking { insertRecords(listOf(heightRecord)) }
+            }
+        // Records that start before the record.
+        val recordsIncluding =
+            fake.readRecords(
+                ReadRecordsRequest(
+                    heightRecord::class,
+                    // No endTime, defaults to clock
+                    timeRangeFilter = TimeRangeFilter(startTime = fixedInstant.minusSeconds(30)),
+                )
+            )
+        // Records that start after the record.
+        val recordsExcluding =
+            fake.readRecords(
+                ReadRecordsRequest(
+                    heightRecord::class,
+                    // No endTime, defaults to clock
+                    timeRangeFilter = TimeRangeFilter(startTime = fixedInstant.minusSeconds(1)),
+                )
+            )
+
+        // Only record1 should be returned
+        assertThat(recordsIncluding.records).hasSize(1)
+        assertThat(recordsExcluding.records).hasSize(0)
+    }
+
+    @Test
+    fun timeRangeFilterlocalTime_noEndTimeInstant() = runTest {
+        // Given a record with a fixed time, before the clock.
+        val heightRecord =
+            HeightRecord(
+                time = fixedInstant.minusSeconds(29),
+                metadata = Metadata(clientRecordId = "HeightRecord#1"),
+                height = Length.meters(1.8),
+                zoneOffset = zoneOffset
+            )
+        val fake =
+            FakeHealthConnectClient(clock = clock).apply {
+                runBlocking { insertRecords(listOf(heightRecord)) }
+            }
+        // Records that start before the record.
+        val recordsIncluding =
+            fake.readRecords(
+                ReadRecordsRequest(
+                    heightRecord::class,
+                    // No endTime, defaults to clock
+                    timeRangeFilter =
+                        TimeRangeFilter(
+                            localStartTime = LocalDateTime.of(2000, 1, 1, 9, 59, 30, 1)
+                        ),
+                )
+            )
+        // Records that start after the record.
+        val recordsExcluding =
+            fake.readRecords(
+                ReadRecordsRequest(
+                    heightRecord::class,
+                    // No endTime, defaults to clock
+                    timeRangeFilter =
+                        TimeRangeFilter(
+                            localStartTime = LocalDateTime.of(2000, 1, 1, 9, 59, 31, 1)
+                        ),
+                )
+            )
+
+        // Only record1 should be returned
+        assertThat(recordsIncluding.records).hasSize(1)
+        assertThat(recordsExcluding.records).hasSize(0)
+    }
+
+    @Test
+    fun timeRangeFilterlocalTime_noStartTimeInstant() = runTest {
+        // Given a record with a fixed time, before the clock.
+        val heightRecord =
+            HeightRecord(
+                time = fixedInstant.minusSeconds(29),
+                metadata = Metadata(clientRecordId = "HeightRecord#1"),
+                height = Length.meters(1.8),
+                zoneOffset = zoneOffset
+            )
+        val fake =
+            FakeHealthConnectClient(clock = clock).apply {
+                runBlocking { insertRecords(listOf(heightRecord)) }
+            }
+        // Records that end before the record.
+        val recordsIncluding =
+            fake.readRecords(
+                ReadRecordsRequest(
+                    heightRecord::class,
+                    // No startTime, defaults to EPOCH
+                    timeRangeFilter =
+                        TimeRangeFilter(localEndTime = LocalDateTime.of(2000, 1, 1, 9, 59, 30)),
+                )
+            )
+        // Records that end after the record.
+        val recordsExcluding =
+            fake.readRecords(
+                ReadRecordsRequest(
+                    heightRecord::class,
+                    // No endTime, defaults to clock
+                    timeRangeFilter =
+                        TimeRangeFilter(localEndTime = LocalDateTime.of(2000, 1, 1, 9, 59, 59)),
+                )
+            )
+
+        // Only record2 should be returned
+        assertThat(recordsIncluding.records).hasSize(0)
+        assertThat(recordsExcluding.records).hasSize(1)
+    }
+}
diff --git a/health/connect/connect-testing/src/test/java/androidx/health/connect/client/testing/FakeHealthConnectClientRecordsTest.kt b/health/connect/connect-testing/src/test/java/androidx/health/connect/client/testing/FakeHealthConnectClientRecordsTest.kt
new file mode 100644
index 0000000..c1e664a
--- /dev/null
+++ b/health/connect/connect-testing/src/test/java/androidx/health/connect/client/testing/FakeHealthConnectClientRecordsTest.kt
@@ -0,0 +1,360 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.health.connect.client.testing
+
+import androidx.health.connect.client.request.ReadRecordsRequest
+import androidx.health.connect.client.testing.testdata.generateRunningRecords
+import androidx.health.connect.client.testing.testdata.runRecord1
+import androidx.health.connect.client.testing.testdata.runRecord1Updated
+import androidx.health.connect.client.time.TimeRangeFilter
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.runTest
+import org.junit.Assert.assertThrows
+import org.junit.Test
+
+/** Unit tests for functions related to [Record] in [FakeHealthConnectClient]. */
+class FakeHealthConnectClientRecordsTest {
+
+    @Test
+    fun insertSingleRecordAndRead_responseHasOneRecord() {
+        runTest {
+            val fake = FakeHealthConnectClient()
+            fake.insertRecords(listOf(runRecord1))
+            val response =
+                fake.readRecords(
+                    ReadRecordsRequest(
+                        timeRangeFilter =
+                            TimeRangeFilter(
+                                startTime = runRecord1.startTime.minusSeconds(1),
+                                endTime = runRecord1.endTime.plusSeconds(1)
+                            ),
+                        recordType = runRecord1::class
+                    )
+                )
+            assertThat(response.records).hasSize(1)
+            assertThat(response.records.first().metadata.clientRecordId)
+                .isEqualTo(runRecord1.metadata.clientRecordId)
+        }
+    }
+
+    @Test
+    fun updateRecordAndRead_responseHasUpdated() {
+        // Given
+        val fakeRecord = runRecord1
+        val updatedRecord = runRecord1Updated
+        runTest {
+            val fake = FakeHealthConnectClient()
+            fake.insertRecords(listOf(fakeRecord))
+            fake.updateRecords(listOf(updatedRecord))
+            val responseOldRange =
+                fake.readRecords(
+                    ReadRecordsRequest(
+                        timeRangeFilter =
+                            TimeRangeFilter(
+                                startTime = fakeRecord.startTime.minusSeconds(1),
+                                endTime = fakeRecord.endTime.plusSeconds(1)
+                            ),
+                        recordType = fakeRecord::class
+                    )
+                )
+
+            val responseNewRange =
+                fake.readRecords(
+                    ReadRecordsRequest(
+                        timeRangeFilter =
+                            TimeRangeFilter(
+                                startTime = updatedRecord.startTime.minusSeconds(1),
+                                endTime = updatedRecord.endTime.plusSeconds(1)
+                            ),
+                        recordType = fakeRecord::class
+                    )
+                )
+
+            assertThat(responseOldRange.records).hasSize(0)
+            assertThat(responseNewRange.records).hasSize(1)
+        }
+    }
+
+    @Test
+    fun insertMultipleRecordsAndDeleteclientRecordIds_responseIsEmpty() = runTest {
+        val fake = FakeHealthConnectClient()
+        val records = generateRunningRecords(5)
+        fake.insertRecords(records)
+
+        val clientRecordIds = records.map { it.metadata.clientRecordId!! }
+        fake.deleteRecords(records.first()::class, emptyList(), clientRecordIds)
+
+        val response =
+            fake.readRecords(
+                ReadRecordsRequest(
+                    timeRangeFilter =
+                        TimeRangeFilter(
+                            startTime = records.first().startTime.minusSeconds(1),
+                            endTime = records.last().endTime.plusSeconds(1)
+                        ),
+                    recordType = records.first()::class
+                )
+            )
+        assertThat(response.records).isEmpty()
+    }
+
+    @Test
+    fun insertMultipleRecordsAndDeleteRecordIds_responseIsEmpty() = runTest {
+        val fake = FakeHealthConnectClient()
+        val records = generateRunningRecords(5)
+        fake.insertRecords(records)
+
+        val responseBeforeDeletion =
+            fake.readRecords(
+                ReadRecordsRequest(
+                    timeRangeFilter =
+                        TimeRangeFilter(
+                            startTime = records.first().startTime.minusSeconds(1),
+                            endTime = records.last().endTime.plusSeconds(1)
+                        ),
+                    recordType = records.first()::class
+                )
+            )
+
+        val recordIds = responseBeforeDeletion.records.map { it.metadata.id }
+        fake.deleteRecords(records.first()::class, recordIds, emptyList())
+
+        val response =
+            fake.readRecords(
+                ReadRecordsRequest(
+                    timeRangeFilter =
+                        TimeRangeFilter(
+                            startTime = records.first().startTime.minusSeconds(1),
+                            endTime = records.last().endTime.plusSeconds(1)
+                        ),
+                    recordType = records.first()::class
+                )
+            )
+        assertThat(response.records).isEmpty()
+    }
+
+    @Test
+    fun insertMultipleRecordsAndDeleteRecordByTimeRangeFilter_responseIsEmpty() = runTest {
+        val fake = FakeHealthConnectClient()
+        val records = generateRunningRecords(5)
+        fake.insertRecords(records)
+
+        fake.deleteRecords(
+            recordType = records.first()::class,
+            timeRangeFilter =
+                TimeRangeFilter(records.first().startTime.minusMillis(1), records.first().endTime)
+        )
+
+        val response =
+            fake.readRecords(
+                ReadRecordsRequest(
+                    timeRangeFilter =
+                        TimeRangeFilter(
+                            startTime = records.first().startTime.minusSeconds(1),
+                            endTime = records.last().endTime.plusSeconds(1)
+                        ),
+                    recordType = records.first()::class
+                )
+            )
+        // Only one record should be presend
+        assertThat(response.records).hasSize(4)
+    }
+
+    @Test
+    fun insertMultipleRecordsAndReadRecord() = runTest {
+        val fake = FakeHealthConnectClient()
+        val records = generateRunningRecords(5)
+        fake.insertRecords(records)
+
+        val recordToRead = records[1]
+        val response = fake.readRecord(recordToRead::class, recordToRead.metadata.clientRecordId!!)
+
+        assertThat(response.record.metadata.clientRecordId)
+            .isEqualTo(recordToRead.metadata.clientRecordId)
+    }
+
+    @Test
+    fun insertMultipleRecordsAndDeleteFour_responseIsOne() = runTest {
+        val fake = FakeHealthConnectClient()
+        val records = generateRunningRecords(5)
+        fake.insertRecords(records)
+
+        val clientRecordIds = records.drop(1).map { it.metadata.clientRecordId!! }
+        fake.deleteRecords(records.first()::class, emptyList(), clientRecordIds)
+
+        val response =
+            fake.readRecords(
+                ReadRecordsRequest(
+                    timeRangeFilter =
+                        TimeRangeFilter(
+                            startTime = records.first().startTime.minusSeconds(1),
+                            endTime = records.last().endTime.plusSeconds(1)
+                        ),
+                    recordType = records.first()::class
+                )
+            )
+        assertThat(response.records).hasSize(1)
+    }
+
+    @Test
+    fun insertMultipleRecords_DeleteDifferentPackageRecordIds_throws() = runTest {
+        val fake = FakeHealthConnectClient(packageName = "com.other.package")
+        val records = generateRunningRecords(5) // Uses default package name
+        fake.insertRecords(records)
+
+        // Need to fetch the records from the API to be able to read their new IDs.
+        val recordsResponse =
+            fake.readRecords(
+                ReadRecordsRequest(
+                    timeRangeFilter =
+                        TimeRangeFilter(
+                            startTime = records.first().startTime.minusSeconds(1),
+                            endTime = records.last().endTime.plusSeconds(1)
+                        ),
+                    recordType = records.first()::class
+                )
+            )
+
+        val recordIds = recordsResponse.records.map { it.metadata.id }
+
+        assertThrows(SecurityException::class.java) {
+            runBlocking {
+                fake.deleteRecords(
+                    recordType = records.first()::class,
+                    recordIdsList = recordIds,
+                    clientRecordIdsList = emptyList()
+                )
+            }
+        }
+    }
+
+    @Test
+    fun insertMultipleRecords_DeleteDifferentPackageClientRecords_throws() = runTest {
+        val fake = FakeHealthConnectClient(packageName = "com.other.package")
+        val records = generateRunningRecords(5)
+        fake.insertRecords(records)
+
+        val clientRecordIds = records.map { it.metadata.clientRecordId!! }
+
+        assertThrows(SecurityException::class.java) {
+            runBlocking { fake.deleteRecords(records.first()::class, emptyList(), clientRecordIds) }
+        }
+    }
+
+    @Test
+    fun insertMultipleRecords_UpdateDifferentPackageClientRecords_throws() = runTest {
+        val fake = FakeHealthConnectClient(packageName = "com.other.package")
+        val records = generateRunningRecords(5)
+        fake.insertRecords(records)
+
+        assertThrows(SecurityException::class.java) {
+            runBlocking { fake.updateRecords(listOf(records.first())) }
+        }
+    }
+
+    @Test
+    fun insertMultipleRecords_UpdateNonExistingClientRecords_doesNotThrow() = runTest {
+        val fake = FakeHealthConnectClient()
+        val records = generateRunningRecords(5)
+        fake.insertRecords(records)
+
+        // Try to delete a record that doesn't exist
+        fake.deleteRecords(
+            records.first()::class,
+            recordIdsList = listOf(runRecord1.metadata.clientRecordId!!),
+            emptyList()
+        )
+        // Does not throw
+    }
+
+    @Test
+    fun pagination_singlePage() = runTest {
+        val fake = FakeHealthConnectClient()
+        val numberOfRecords = 3
+        val records = generateRunningRecords(numberOfRecords)
+
+        fake.insertRecords(records)
+
+        val pagedRequest1 =
+            ReadRecordsRequest(
+                timeRangeFilter =
+                    TimeRangeFilter(
+                        startTime = records.first().startTime.minusSeconds(1),
+                        endTime = records.last().endTime.plusSeconds(1)
+                    ),
+                recordType = records.first()::class,
+                pageSize = 5,
+            )
+        val page1 = fake.readRecords(pagedRequest1)
+
+        assertThat(page1.records).hasSize(numberOfRecords)
+        assertThat(page1.pageToken).isNull()
+    }
+
+    @Test
+    fun pagination_threePages() = runTest {
+        val fake = FakeHealthConnectClient()
+        val records = generateRunningRecords(5)
+
+        fake.insertRecords(records)
+
+        val pagedRequest1 =
+            ReadRecordsRequest(
+                timeRangeFilter =
+                    TimeRangeFilter(
+                        startTime = records.first().startTime.minusSeconds(1),
+                        endTime = records.last().endTime.plusSeconds(1)
+                    ),
+                recordType = records.first()::class,
+                pageSize = 2,
+            )
+        val page1 = fake.readRecords(pagedRequest1)
+
+        val pagedRequest2 =
+            ReadRecordsRequest(
+                timeRangeFilter =
+                    TimeRangeFilter(
+                        startTime = records.first().startTime.minusSeconds(1),
+                        endTime = records.last().endTime.plusSeconds(1)
+                    ),
+                recordType = records.first()::class,
+                pageToken = page1.pageToken,
+                pageSize = 2,
+            )
+        val page2 = fake.readRecords(pagedRequest2)
+        val pagedRequest3 =
+            ReadRecordsRequest(
+                timeRangeFilter =
+                    TimeRangeFilter(
+                        startTime = records.first().startTime.minusSeconds(1),
+                        endTime = records.last().endTime.plusSeconds(1)
+                    ),
+                recordType = records.first()::class,
+                pageToken = page2.pageToken,
+                pageSize = 2,
+            )
+        val page3 = fake.readRecords(pagedRequest3)
+
+        assertThat(page1.records).hasSize(2)
+        assertThat(page2.records).hasSize(2)
+        assertThat(page3.records).hasSize(1)
+        assertThat(page3.pageToken).isNull()
+        assertThat(page2.records.first().title).isEqualTo(records[2].title)
+        assertThat(page3.records.first().title).isEqualTo(records[4].title)
+    }
+}
diff --git a/health/connect/connect-testing/src/test/java/androidx/health/connect/client/testing/FakePermissionControllerTest.kt b/health/connect/connect-testing/src/test/java/androidx/health/connect/client/testing/FakePermissionControllerTest.kt
new file mode 100644
index 0000000..5daae33
--- /dev/null
+++ b/health/connect/connect-testing/src/test/java/androidx/health/connect/client/testing/FakePermissionControllerTest.kt
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.health.connect.client.testing
+
+import androidx.health.connect.client.permission.HealthPermission
+import androidx.health.connect.client.permission.HealthPermission.Companion.PERMISSION_READ_HEALTH_DATA_IN_BACKGROUND
+import androidx.health.connect.client.permission.HealthPermission.Companion.PERMISSION_WRITE_EXERCISE_ROUTE
+import com.google.common.truth.Truth.assertThat
+import kotlin.test.Test
+import kotlinx.coroutines.test.runTest
+
+/** Unit tests for [FakePermissionController]. */
+class FakePermissionControllerTest {
+
+    @Test
+    fun grantAll_grantsWriteAndRead() = runTest {
+        val controller = FakePermissionController(grantAll = true)
+        val permissions = controller.getGrantedPermissions()
+        assertThat(permissions.size).isAtLeast(HealthPermission.ALL_PERMISSIONS.toSet().size)
+    }
+
+    @Test
+    fun grantAll_grantsExtraPermissions() = runTest {
+        val controller = FakePermissionController(grantAll = true)
+        val permissions = controller.getGrantedPermissions()
+        assertThat(permissions).contains(PERMISSION_WRITE_EXERCISE_ROUTE)
+        assertThat(permissions).contains(PERMISSION_READ_HEALTH_DATA_IN_BACKGROUND)
+    }
+
+    @Test
+    fun grantAllFalse_noPermissions() = runTest {
+        val controller = FakePermissionController(grantAll = false)
+        val permissions = controller.getGrantedPermissions()
+        assertThat(permissions).hasSize(0)
+    }
+
+    @Test
+    fun grantPermission_grantsPermission() = runTest {
+        val controller = FakePermissionController(grantAll = false)
+        controller.grantPermission(PERMISSION_WRITE_EXERCISE_ROUTE)
+        val permissions = controller.getGrantedPermissions()
+        assertThat(permissions).contains(PERMISSION_WRITE_EXERCISE_ROUTE)
+    }
+
+    @Test
+    fun revokeAllPermissions_noPermissions() = runTest {
+        val controller = FakePermissionController(grantAll = true)
+        controller.revokeAllPermissions()
+        val permissions = controller.getGrantedPermissions()
+        assertThat(permissions).hasSize(0)
+    }
+
+    @Test
+    fun grantPermissions_doesntReplace() = runTest {
+        val controller = FakePermissionController(grantAll = false)
+        controller.grantPermission("permission1")
+        controller.grantPermissions(setOf("permission2"))
+        assertThat(controller.getGrantedPermissions()).hasSize(2)
+    }
+
+    @Test
+    fun revokePermissions() = runTest {
+        val controller = FakePermissionController(grantAll = false)
+        controller.grantPermission("permission1")
+        controller.grantPermission("permission2")
+        controller.revokePermission("permission1")
+        assertThat(controller.getGrantedPermissions()).hasSize(1)
+    }
+
+    @Test
+    fun replaceGrantedPermissions() = runTest {
+        val controller = FakePermissionController(grantAll = false)
+        controller.grantPermission("permission1")
+        controller.grantPermission("permission2")
+        controller.replaceGrantedPermissions(setOf("permission1", "permission3"))
+        assertThat(controller.getGrantedPermissions())
+            .isEqualTo(setOf("permission1", "permission3"))
+    }
+}
diff --git a/health/connect/connect-testing/src/test/java/androidx/health/connect/client/testing/testdata/TestData.kt b/health/connect/connect-testing/src/test/java/androidx/health/connect/client/testing/testdata/TestData.kt
new file mode 100644
index 0000000..2446c31
--- /dev/null
+++ b/health/connect/connect-testing/src/test/java/androidx/health/connect/client/testing/testdata/TestData.kt
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.health.connect.client.testing.testdata
+
+import androidx.health.connect.client.records.ExerciseSessionRecord
+import androidx.health.connect.client.records.HydrationRecord
+import androidx.health.connect.client.records.metadata.DataOrigin
+import androidx.health.connect.client.records.metadata.Metadata
+import androidx.health.connect.client.testing.FakeHealthConnectClient
+import androidx.health.connect.client.units.Volume
+import java.time.ZonedDateTime
+
+// Arbitrary start time in the past
+private val startTime: ZonedDateTime = ZonedDateTime.now().minusHours(23)
+
+val runRecord1 =
+    ExerciseSessionRecord(
+        startTime = startTime.plusMinutes(1).toInstant(),
+        startZoneOffset = startTime.offset,
+        endTime = startTime.plusMinutes(2).toInstant(),
+        endZoneOffset = startTime.offset,
+        exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_RUNNING,
+        title = "My Run #1",
+        exerciseRoute = null,
+        metadata =
+            Metadata(
+                clientRecordId = "FakeHealthConnectData1",
+                id = "Id1",
+                dataOrigin = DataOrigin(FakeHealthConnectClient.DEFAULT_PACKAGE_NAME)
+            )
+    )
+
+val hydrationRecord1 =
+    HydrationRecord(
+        startTime = startTime.plusMinutes(3).toInstant(),
+        startZoneOffset = startTime.offset,
+        endTime = startTime.plusMinutes(4).toInstant(),
+        endZoneOffset = startTime.offset,
+        volume = Volume.liters(1.0)
+    )
+
+/** Same as [runRecord1] but updated with a new end time. */
+val runRecord1Updated =
+    ExerciseSessionRecord(
+        startTime = startTime.plusMinutes(1).toInstant(),
+        startZoneOffset = startTime.offset,
+        endTime = startTime.plusMinutes(3).toInstant(),
+        endZoneOffset = startTime.offset,
+        exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_RUNNING,
+        title = "My Run #1 - Updated",
+        exerciseRoute = null,
+        metadata =
+            Metadata(
+                clientRecordId = "FakeHealthConnectData1",
+                id = "Id1",
+                dataOrigin = DataOrigin(FakeHealthConnectClient.DEFAULT_PACKAGE_NAME)
+            )
+    )
+
+/**
+ * Generates a list of [ExerciseSessionRecord]s of type
+ * [ExerciseSessionRecord.EXERCISE_TYPE_RUNNING], one per day ending now, 1h long.
+ */
+@JvmOverloads
+fun generateRunningRecords(
+    amount: Int,
+    startTime: ZonedDateTime = ZonedDateTime.now().minusDays(amount.toLong()),
+    exerciseType: Int = ExerciseSessionRecord.EXERCISE_TYPE_RUNNING,
+    defaultPackageName: String = FakeHealthConnectClient.DEFAULT_PACKAGE_NAME
+): List<ExerciseSessionRecord> {
+    return List(amount) { index ->
+        val day = startTime.plusDays(index.toLong())
+        ExerciseSessionRecord(
+            startTime = day.minusMinutes(60).toInstant(),
+            startZoneOffset = startTime.offset,
+            endTime = day.toInstant(),
+            endZoneOffset = startTime.offset,
+            exerciseType = exerciseType,
+            title = "My Run #$index",
+            exerciseRoute = null,
+            metadata =
+                Metadata(
+                    clientRecordId = "FakeHealthConnectDataRunning$index",
+                    dataOrigin = DataOrigin(defaultPackageName)
+                )
+        )
+    }
+}
diff --git a/ink/ink-brush/build.gradle b/ink/ink-brush/build.gradle
index bb1e3f7..8083aae 100644
--- a/ink/ink-brush/build.gradle
+++ b/ink/ink-brush/build.gradle
@@ -23,15 +23,55 @@
  */
 
 import androidx.build.LibraryType
+import androidx.build.PlatformIdentifier
 
 plugins {
     id("AndroidXPlugin")
-    id("kotlin")
+    id("com.android.library")
 }
 
-dependencies {
-    api(project(":compose:ui:ui-graphics"))
-    testImplementation(libs.kotlinTest)
+androidXMultiplatform {
+  android()
+  jvm()
+
+  defaultPlatform(PlatformIdentifier.JVM)
+
+  sourceSets {
+    commonMain {
+      dependencies {
+        api(project(":compose:ui:ui-graphics"))
+      }
+    }
+
+    commonTest {
+      dependencies {
+        implementation(libs.kotlinTest)
+      }
+    }
+
+    androidMain {
+      dependsOn(commonMain)
+    }
+
+    androidInstrumentedTest {
+      dependsOn(commonTest)
+      dependencies {
+        implementation(libs.testRunner)
+      }
+    }
+
+    jvmMain {
+      dependsOn(commonMain)
+    }
+
+    jvmTest {
+      dependsOn(commonTest)
+    }
+  }
+}
+
+android {
+  namespace = "androidx.ink.brush"
 }
 
 androidx {
diff --git a/ink/ink-brush/src/main/java/androidx/ink/brush/Brush.kt b/ink/ink-brush/src/commonMain/kotlin/androidx/ink/brush/Brush.kt
similarity index 100%
rename from ink/ink-brush/src/main/java/androidx/ink/brush/Brush.kt
rename to ink/ink-brush/src/commonMain/kotlin/androidx/ink/brush/Brush.kt
diff --git a/ink/ink-brush/src/test/java/androidx/ink/brush/BrushTest.kt b/ink/ink-brush/src/commonTest/kotlin/androidx/ink/brush/BrushTest.kt
similarity index 100%
rename from ink/ink-brush/src/test/java/androidx/ink/brush/BrushTest.kt
rename to ink/ink-brush/src/commonTest/kotlin/androidx/ink/brush/BrushTest.kt
diff --git a/kruth/kruth/api/current.ignore b/kruth/kruth/api/current.ignore
index 310d98a..c12fb51 100644
--- a/kruth/kruth/api/current.ignore
+++ b/kruth/kruth/api/current.ignore
@@ -37,6 +37,10 @@
     Method androidx.kruth.TruthFailureSubject.truthFailures has changed return type from androidx.kruth.Subject.Factory<androidx.kruth.TruthFailureSubject,java.lang.AssertionError> to androidx.kruth.Subject.Factory<androidx.kruth.TruthFailureSubject<T>,T>
 
 
+InvalidNullConversion: androidx.kruth.IterableSubject#isNotIn(Iterable<?>) parameter #0:
+    Attempted to change nullability of java.lang.Object (from NONNULL to NULLABLE) in parameter iterable in androidx.kruth.IterableSubject.isNotIn(Iterable<?> iterable)
+InvalidNullConversion: androidx.kruth.StandardSubjectBuilder#that(T[]) parameter #0:
+    Attempted to change nullability of T (from NULLABLE to NONNULL) in parameter actual in androidx.kruth.StandardSubjectBuilder.that(T[] actual)
 InvalidNullConversion: androidx.kruth.StandardSubjectBuilder#withMessage(String) parameter #0:
     Attempted to change nullability of java.lang.String (from NULLABLE to NONNULL) in parameter messageToPrepend in androidx.kruth.StandardSubjectBuilder.withMessage(String messageToPrepend)
 InvalidNullConversion: androidx.kruth.StringSubject#contains(CharSequence) parameter #0:
@@ -57,6 +61,12 @@
     Attempted to change nullability of java.lang.String (from NULLABLE to NONNULL) in parameter string in androidx.kruth.StringSubject.startsWith(String string)
 InvalidNullConversion: androidx.kruth.StringSubject.CaseInsensitiveStringComparison#doesNotContain(CharSequence) parameter #0:
     Attempted to change nullability of java.lang.CharSequence (from NULLABLE to NONNULL) in parameter expected in androidx.kruth.StringSubject.CaseInsensitiveStringComparison.doesNotContain(CharSequence expected)
+InvalidNullConversion: androidx.kruth.Subject#check(String, java.lang.Object...) parameter #1:
+    Attempted to change nullability of java.lang.Object (from NULLABLE to NONNULL) in parameter args in androidx.kruth.Subject.check(String format, java.lang.Object... args)
+InvalidNullConversion: androidx.kruth.Subject#isIn(Iterable<?>) parameter #0:
+    Attempted to change nullability of java.lang.Object (from NONNULL to NULLABLE) in parameter iterable in androidx.kruth.Subject.isIn(Iterable<?> iterable)
+InvalidNullConversion: androidx.kruth.Subject#isNotIn(Iterable<?>) parameter #0:
+    Attempted to change nullability of java.lang.Object (from NONNULL to NULLABLE) in parameter iterable in androidx.kruth.Subject.isNotIn(Iterable<?> iterable)
 
 
 RemovedClass: androidx.kruth.Correspondence:
diff --git a/kruth/kruth/api/restricted_current.ignore b/kruth/kruth/api/restricted_current.ignore
index 310d98a..c12fb51 100644
--- a/kruth/kruth/api/restricted_current.ignore
+++ b/kruth/kruth/api/restricted_current.ignore
@@ -37,6 +37,10 @@
     Method androidx.kruth.TruthFailureSubject.truthFailures has changed return type from androidx.kruth.Subject.Factory<androidx.kruth.TruthFailureSubject,java.lang.AssertionError> to androidx.kruth.Subject.Factory<androidx.kruth.TruthFailureSubject<T>,T>
 
 
+InvalidNullConversion: androidx.kruth.IterableSubject#isNotIn(Iterable<?>) parameter #0:
+    Attempted to change nullability of java.lang.Object (from NONNULL to NULLABLE) in parameter iterable in androidx.kruth.IterableSubject.isNotIn(Iterable<?> iterable)
+InvalidNullConversion: androidx.kruth.StandardSubjectBuilder#that(T[]) parameter #0:
+    Attempted to change nullability of T (from NULLABLE to NONNULL) in parameter actual in androidx.kruth.StandardSubjectBuilder.that(T[] actual)
 InvalidNullConversion: androidx.kruth.StandardSubjectBuilder#withMessage(String) parameter #0:
     Attempted to change nullability of java.lang.String (from NULLABLE to NONNULL) in parameter messageToPrepend in androidx.kruth.StandardSubjectBuilder.withMessage(String messageToPrepend)
 InvalidNullConversion: androidx.kruth.StringSubject#contains(CharSequence) parameter #0:
@@ -57,6 +61,12 @@
     Attempted to change nullability of java.lang.String (from NULLABLE to NONNULL) in parameter string in androidx.kruth.StringSubject.startsWith(String string)
 InvalidNullConversion: androidx.kruth.StringSubject.CaseInsensitiveStringComparison#doesNotContain(CharSequence) parameter #0:
     Attempted to change nullability of java.lang.CharSequence (from NULLABLE to NONNULL) in parameter expected in androidx.kruth.StringSubject.CaseInsensitiveStringComparison.doesNotContain(CharSequence expected)
+InvalidNullConversion: androidx.kruth.Subject#check(String, java.lang.Object...) parameter #1:
+    Attempted to change nullability of java.lang.Object (from NULLABLE to NONNULL) in parameter args in androidx.kruth.Subject.check(String format, java.lang.Object... args)
+InvalidNullConversion: androidx.kruth.Subject#isIn(Iterable<?>) parameter #0:
+    Attempted to change nullability of java.lang.Object (from NONNULL to NULLABLE) in parameter iterable in androidx.kruth.Subject.isIn(Iterable<?> iterable)
+InvalidNullConversion: androidx.kruth.Subject#isNotIn(Iterable<?>) parameter #0:
+    Attempted to change nullability of java.lang.Object (from NONNULL to NULLABLE) in parameter iterable in androidx.kruth.Subject.isNotIn(Iterable<?> iterable)
 
 
 RemovedClass: androidx.kruth.Correspondence:
diff --git a/libraryversions.toml b/libraryversions.toml
index 11ca9a1..65e1e5b 100644
--- a/libraryversions.toml
+++ b/libraryversions.toml
@@ -2,33 +2,32 @@
 ACTIVITY = "1.10.0-alpha01"
 ANNOTATION = "1.9.0-alpha01"
 ANNOTATION_EXPERIMENTAL = "1.4.0-rc01"
-APPCOMPAT = "1.7.0-rc01"
+APPCOMPAT = "1.8.0-alpha01"
 APPSEARCH = "1.1.0-alpha04"
 ARCH_CORE = "2.3.0-alpha01"
 ASYNCLAYOUTINFLATER = "1.1.0-alpha02"
 AUTOFILL = "1.3.0-alpha02"
-BENCHMARK = "1.3.0-beta01"
+BENCHMARK = "1.3.0-beta02"
 BIOMETRIC = "1.2.0-alpha06"
 BLUETOOTH = "1.0.0-alpha02"
 BROWSER = "1.9.0-alpha01"
 BUILDSRC_TESTS = "1.0.0-alpha01"
-CAMERA = "1.4.0-beta02"
+CAMERA = "1.4.0-beta03"
 CAMERA_PIPE = "1.0.0-alpha01"
 CAMERA_TESTING = "1.0.0-alpha01"
-CAMERA_VIEWFINDER = "1.4.0-alpha07"
-CAMERA_VIEWFINDER_COMPOSE = "1.0.0-alpha02"
+CAMERA_VIEWFINDER = "1.4.0-alpha08"
+CAMERA_VIEWFINDER_COMPOSE = "1.0.0-alpha03"
 CARDVIEW = "1.1.0-alpha01"
 CAR_APP = "1.7.0-beta01"
 COLLECTION = "1.5.0-alpha01"
 COMPOSE = "1.8.0-alpha01"
-COMPOSE_COMPILER = "1.5.14"  # Update when preparing for a release
 COMPOSE_MATERIAL3 = "1.4.0-alpha01"
-COMPOSE_MATERIAL3_ADAPTIVE = "1.0.0-beta03"
+COMPOSE_MATERIAL3_ADAPTIVE = "1.1.0-alpha01"
 COMPOSE_MATERIAL3_COMMON = "1.0.0-alpha01"
 COMPOSE_RUNTIME_TRACING = "1.0.0-beta01"
-CONSTRAINTLAYOUT = "2.2.0-alpha13"
-CONSTRAINTLAYOUT_COMPOSE = "1.1.0-alpha13"
-CONSTRAINTLAYOUT_CORE = "1.1.0-alpha13"
+CONSTRAINTLAYOUT = "2.2.0-beta01"
+CONSTRAINTLAYOUT_COMPOSE = "1.1.0-beta01"
+CONSTRAINTLAYOUT_CORE = "1.1.0-beta01"
 CONTENTPAGER = "1.1.0-alpha01"
 COORDINATORLAYOUT = "1.3.0-alpha02"
 CORE = "1.14.0-alpha01"
@@ -45,7 +44,7 @@
 CORE_SPLASHSCREEN = "1.2.0-alpha01"
 CORE_TELECOM = "1.0.0-alpha08"
 CORE_UWB = "1.0.0-alpha08"
-CREDENTIALS = "1.3.0-beta02"
+CREDENTIALS = "1.3.0-rc01"
 CREDENTIALS_E2EE_QUARANTINE = "1.0.0-alpha02"
 CREDENTIALS_FIDO_QUARANTINE = "1.0.0-alpha02"
 CURSORADAPTER = "1.1.0-alpha01"
@@ -58,11 +57,11 @@
 DYNAMICANIMATION = "1.1.0-alpha04"
 DYNAMICANIMATION_KTX = "1.0.0-alpha04"
 EMOJI = "1.2.0-alpha03"
-EMOJI2 = "1.5.0-alpha01"
+EMOJI2 = "1.5.0-beta01"
 ENTERPRISE = "1.1.0-rc01"
 EXIFINTERFACE = "1.4.0-alpha01"
-FRAGMENT = "1.8.0-rc01"
-FUTURES = "1.2.0-rc01"
+FRAGMENT = "1.9.0-alpha01"
+FUTURES = "1.3.0-alpha01"
 GLANCE = "1.2.0-alpha01"
 GLANCE_TEMPLATE = "1.0.0-alpha06"
 GLANCE_WEAR_TILES = "1.0.0-alpha06"
@@ -98,7 +97,7 @@
 MEDIA = "1.7.0-rc01"
 MEDIAROUTER = "1.8.0-alpha01"
 METRICS = "1.0.0-beta02"
-NAVIGATION = "2.8.0-beta03"
+NAVIGATION = "2.8.0-beta05"
 PAGING = "3.4.0-alpha01"
 PALETTE = "1.1.0-alpha01"
 PDF = "1.0.0-alpha01"
@@ -106,7 +105,7 @@
 PREFERENCE = "1.3.0-alpha01"
 PRINT = "1.1.0-beta01"
 PRIVACYSANDBOX_ACTIVITY = "1.0.0-alpha01"
-PRIVACYSANDBOX_ADS = "1.1.0-beta08"
+PRIVACYSANDBOX_ADS = "1.1.0-beta09"
 PRIVACYSANDBOX_PLUGINS = "1.0.0-alpha03"
 PRIVACYSANDBOX_SDKRUNTIME = "1.0.0-alpha13"
 PRIVACYSANDBOX_TOOLS = "1.0.0-alpha09"
@@ -117,7 +116,7 @@
 RECYCLERVIEW_SELECTION = "1.2.0-alpha02"
 REMOTECALLBACK = "1.0.0-alpha02"
 RESOURCEINSPECTION = "1.1.0-alpha01"
-ROOM = "2.7.0-alpha04"
+ROOM = "2.7.0-alpha05"
 SAFEPARCEL = "1.0.0-alpha01"
 SAVEDSTATE = "1.3.0-alpha01"
 SECURITY = "1.1.0-alpha07"
@@ -126,14 +125,14 @@
 SECURITY_BIOMETRIC = "1.0.0-alpha01"
 SECURITY_IDENTITY_CREDENTIAL = "1.0.0-alpha04"
 SECURITY_MLS = "1.0.0-alpha01"
-SECURITY_STATE = "1.0.0-alpha02"
+SECURITY_STATE = "1.0.0-alpha03"
 SHARETARGET = "1.3.0-alpha01"
 SLICE = "1.1.0-alpha03"
 SLICE_BENCHMARK = "1.1.0-alpha03"
 SLICE_BUILDERS_KTX = "1.0.0-alpha09"
 SLICE_REMOTECALLBACK = "1.0.0-alpha01"
 SLIDINGPANELAYOUT = "1.3.0-alpha01"
-SQLITE = "2.5.0-alpha04"
+SQLITE = "2.5.0-alpha05"
 SQLITE_INSPECTOR = "2.1.0-alpha01"
 STABLE_AIDL = "1.0.0-alpha01"
 STARTUP = "1.2.0-alpha03"
@@ -147,7 +146,7 @@
 TRANSITION = "1.5.0-rc01"
 TV = "1.0.0-alpha11"
 TVPROVIDER = "1.1.0-alpha02"
-TV_MATERIAL = "1.0.0-beta01"
+TV_MATERIAL = "1.0.0-rc01"
 VECTORDRAWABLE = "1.2.0"
 VECTORDRAWABLE_ANIMATED = "1.2.0"
 VECTORDRAWABLE_SEEKABLE = "1.0.0"
@@ -162,10 +161,10 @@
 WEAR_INPUT_TESTING = "1.2.0-alpha03"
 WEAR_ONGOING = "1.1.0-alpha02"
 WEAR_PHONE_INTERACTIONS = "1.1.0-alpha04"
-WEAR_PROTOLAYOUT = "1.2.0-alpha05"
+WEAR_PROTOLAYOUT = "1.2.0-beta01"
 WEAR_PROTOLAYOUT_MATERIAL3 = "1.0.0-alpha01"
 WEAR_REMOTE_INTERACTIONS = "1.1.0-alpha02"
-WEAR_TILES = "1.4.0-alpha05"
+WEAR_TILES = "1.4.0-beta01"
 WEAR_TOOLING_PREVIEW = "1.0.0-rc01"
 WEAR_WATCHFACE = "1.3.0-alpha03"
 WEBKIT = "1.12.0-alpha02"
@@ -199,8 +198,6 @@
 CAR_APP = { group = "androidx.car.app", atomicGroupVersion = "versions.CAR_APP" }
 COLLECTION = { group = "androidx.collection", atomicGroupVersion = "versions.COLLECTION" }
 COMPOSE_ANIMATION = { group = "androidx.compose.animation", atomicGroupVersion = "versions.COMPOSE" }
-COMPOSE_COMPILER = { group = "androidx.compose.compiler", atomicGroupVersion = "versions.COMPOSE_COMPILER" }
-COMPOSE_DESKTOP = { group = "androidx.compose.desktop", atomicGroupVersion = "versions.COMPOSE" }
 COMPOSE_FOUNDATION = { group = "androidx.compose.foundation", atomicGroupVersion = "versions.COMPOSE" }
 COMPOSE_MATERIAL = { group = "androidx.compose.material" }
 COMPOSE_MATERIAL3 = { group = "androidx.compose.material3", atomicGroupVersion = "versions.COMPOSE_MATERIAL3" }
diff --git a/lifecycle/lifecycle-livedata-core-lint/src/main/java/androidx/lifecycle/lint/NonNullableMutableLiveDataDetector.kt b/lifecycle/lifecycle-livedata-core-lint/src/main/java/androidx/lifecycle/lint/NonNullableMutableLiveDataDetector.kt
index 92cceb4..4dba651 100644
--- a/lifecycle/lifecycle-livedata-core-lint/src/main/java/androidx/lifecycle/lint/NonNullableMutableLiveDataDetector.kt
+++ b/lifecycle/lifecycle-livedata-core-lint/src/main/java/androidx/lifecycle/lint/NonNullableMutableLiveDataDetector.kt
@@ -28,6 +28,7 @@
 import com.android.tools.lint.detector.api.Severity
 import com.android.tools.lint.detector.api.UastLintUtils
 import com.android.tools.lint.detector.api.isKotlin
+import com.intellij.psi.PsiAnnotationOwner
 import com.intellij.psi.PsiClassType
 import com.intellij.psi.PsiTypeParameter
 import com.intellij.psi.PsiVariable
@@ -53,8 +54,8 @@
 import org.jetbrains.uast.USimpleNameReferenceExpression
 import org.jetbrains.uast.getUastParentOfType
 import org.jetbrains.uast.isNullLiteral
-import org.jetbrains.uast.resolveToUElement
 import org.jetbrains.uast.toUElement
+import org.jetbrains.uast.toUElementOfType
 
 /**
  * Lint check for ensuring that [androidx.lifecycle.MutableLiveData] values are never null when the
@@ -320,7 +321,12 @@
         val isSuspendMethod = !context.evaluator.isSuspend(psiMethod)
         return psiMethod.hasAnnotation(NULLABLE_ANNOTATION) && isSuspendMethod
     } else if (this is UReferenceExpression) {
-        return (resolveToUElement() as? UAnnotated)?.findAnnotation(NULLABLE_ANNOTATION) != null
+        val resolved = resolve()
+        return if (resolved is PsiAnnotationOwner) {
+            resolved.findAnnotation(NULLABLE_ANNOTATION) != null
+        } else {
+            resolved.toUElementOfType<UAnnotated>()?.findAnnotation(NULLABLE_ANNOTATION) != null
+        }
     }
     return false
 }
diff --git a/lifecycle/lifecycle-livedata-core-lint/src/test/java/androidx/lifecycle/livedata/core/lint/NonNullableMutableLiveDataDetectorTest.kt b/lifecycle/lifecycle-livedata-core-lint/src/test/java/androidx/lifecycle/livedata/core/lint/NonNullableMutableLiveDataDetectorTest.kt
index 7e4c4e0..95ee2ed 100644
--- a/lifecycle/lifecycle-livedata-core-lint/src/test/java/androidx/lifecycle/livedata/core/lint/NonNullableMutableLiveDataDetectorTest.kt
+++ b/lifecycle/lifecycle-livedata-core-lint/src/test/java/androidx/lifecycle/livedata/core/lint/NonNullableMutableLiveDataDetectorTest.kt
@@ -1031,6 +1031,54 @@
             .expectClean()
     }
 
+    @Test
+    fun lambdaParameterFromMediatorLiveData() {
+        // Regression test from b/341316048
+        // https://youtrack.jetbrains.com/issue/KTIJ-30464
+        check(
+                kotlin(
+                        """
+                    package androidx.lifecycle
+
+                    fun interface Observer<T> {
+                      fun onChanged(value: T)
+                    }
+                """
+                    )
+                    .indented(),
+                java(
+                        """
+                    package androidx.lifecycle;
+
+                    public class MediatorLiveData<T> extends MutableLiveData<T> {
+                        public <S> void addSource(LiveData<S> source, Observer<? super S> onChanged) {
+                        }
+                    }
+                """
+                    )
+                    .indented(),
+                kotlin(
+                        """
+                    import androidx.lifecycle.MediatorLiveData
+
+                    class Test {
+                        val myData = MediatorLiveData<List<Boolean>>()
+
+                        init {
+                          myData.addSource(getSources()) { data ->
+                            myData.value = data
+                          }
+                        }
+
+                        private fun getSources(): MediatorLiveData<List<Boolean>> = TODO()
+                    }
+                """
+                    )
+                    .indented()
+            )
+            .expectClean()
+    }
+
     private companion object {
         val DATA_LIB: TestFile =
             bytecode(
diff --git a/lifecycle/lifecycle-viewmodel/src/desktopMain/kotlin/androidx/lifecycle/ViewModelProvider.desktop.kt b/lifecycle/lifecycle-viewmodel/src/desktopMain/kotlin/androidx/lifecycle/ViewModelProvider.desktop.kt
index 2b7ea54..f2833cc 100644
--- a/lifecycle/lifecycle-viewmodel/src/desktopMain/kotlin/androidx/lifecycle/ViewModelProvider.desktop.kt
+++ b/lifecycle/lifecycle-viewmodel/src/desktopMain/kotlin/androidx/lifecycle/ViewModelProvider.desktop.kt
@@ -19,7 +19,9 @@
 import androidx.annotation.MainThread
 import androidx.annotation.RestrictTo
 import androidx.lifecycle.viewmodel.CreationExtras
+import androidx.lifecycle.viewmodel.CreationExtras.Key
 import androidx.lifecycle.viewmodel.ViewModelProviderImpl
+import androidx.lifecycle.viewmodel.internal.JvmViewModelProviders
 import androidx.lifecycle.viewmodel.internal.ViewModelProviders
 import kotlin.reflect.KClass
 
@@ -50,6 +52,41 @@
         public actual open fun onRequery(viewModel: ViewModel) {}
     }
 
+    /** Simple factory, which calls empty constructor on the give class. */
+    public open class NewInstanceFactory
+    /**
+     * Construct a new [NewInstanceFactory] instance.
+     *
+     * Use [NewInstanceFactory.instance] to get a default instance of [NewInstanceFactory].
+     */
+    @Suppress("SingletonConstructor")
+    constructor() : Factory {
+
+        public override fun <T : ViewModel> create(
+            modelClass: KClass<T>,
+            extras: CreationExtras,
+        ): T = JvmViewModelProviders.createViewModel(modelClass.java)
+
+        public companion object {
+            private var _instance: NewInstanceFactory? = null
+
+            /**
+             * Retrieve a singleton instance of NewInstanceFactory.
+             *
+             * @return A valid [NewInstanceFactory]
+             */
+            @JvmStatic
+            public val instance: NewInstanceFactory
+                @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+                get() {
+                    if (_instance == null) {
+                        _instance = NewInstanceFactory()
+                    }
+                    return _instance!!
+                }
+        }
+    }
+
     public actual companion object {
         @JvmStatic
         public actual fun create(
diff --git a/lint-checks/build.gradle b/lint-checks/build.gradle
index 7d6fa107..aad41fa 100644
--- a/lint-checks/build.gradle
+++ b/lint-checks/build.gradle
@@ -40,12 +40,18 @@
 dependencies {
     compileOnly(libs.androidLintApi)
     compileOnly(libs.androidLintChecks)
+    compileOnly(libs.androidToolsCommon)
+    compileOnly(libs.intellijCore)
+    compileOnly(libs.intellijKotlinCompiler)
     compileOnly(libs.kotlinStdlib)
+    compileOnly(libs.lintModel)
+    compileOnly(libs.sdklib)
+    compileOnly(libs.uast)
 
-    testImplementation(libs.kotlinStdlib)
     testImplementation(libs.androidLint)
     testImplementation(libs.androidLintTests)
     testImplementation(libs.junit)
+    testImplementation(libs.guava)
 }
 
 androidx {
diff --git a/lint/lint-gradle/build.gradle b/lint/lint-gradle/build.gradle
index 0793c790..e578727 100644
--- a/lint/lint-gradle/build.gradle
+++ b/lint/lint-gradle/build.gradle
@@ -34,7 +34,6 @@
     compileOnly(libs.androidLintChecks)
     compileOnly(libs.kotlinStdlib)
 
-    testImplementation(libs.kotlinStdlib)
     testImplementation(libs.androidLint)
     testImplementation(libs.androidLintTests)
     testImplementation(libs.junit)
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRoute2Provider.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRoute2Provider.java
index 989153e..cf0b40a 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRoute2Provider.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRoute2Provider.java
@@ -194,7 +194,7 @@
         List<MediaRouteDescriptor> routeDescriptors = new ArrayList<>();
         for (MediaRoute2Info route : mRoutes) {
             MediaRouteDescriptor descriptor = MediaRouter2Utils.toMediaRouteDescriptor(route);
-            if (route != null) {
+            if (descriptor != null) {
                 routeDescriptors.add(descriptor);
             }
         }
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter2Utils.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter2Utils.java
index 234d26d..0b8ccf5 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter2Utils.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter2Utils.java
@@ -179,7 +179,6 @@
         return builder.build();
     }
 
-    @OptIn(markerClass = androidx.core.os.BuildCompat.PrereleaseSdkCheck.class)
     @Nullable
     public static MediaRouteDescriptor toMediaRouteDescriptor(
             @Nullable MediaRoute2Info fwkMediaRoute2Info) {
diff --git a/navigation/navigation-common-ktx/api/2.8.0-beta04.txt b/navigation/navigation-common-ktx/api/2.8.0-beta04.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/navigation/navigation-common-ktx/api/2.8.0-beta04.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/navigation/navigation-common-ktx/api/2.8.0-beta05.txt b/navigation/navigation-common-ktx/api/2.8.0-beta05.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/navigation/navigation-common-ktx/api/2.8.0-beta05.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/navigation/navigation-common-ktx/api/res-2.8.0-beta04.txt b/navigation/navigation-common-ktx/api/res-2.8.0-beta04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-common-ktx/api/res-2.8.0-beta04.txt
diff --git a/navigation/navigation-common-ktx/api/res-2.8.0-beta05.txt b/navigation/navigation-common-ktx/api/res-2.8.0-beta05.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-common-ktx/api/res-2.8.0-beta05.txt
diff --git a/navigation/navigation-common-ktx/api/restricted_2.8.0-beta04.txt b/navigation/navigation-common-ktx/api/restricted_2.8.0-beta04.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/navigation/navigation-common-ktx/api/restricted_2.8.0-beta04.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/navigation/navigation-common-ktx/api/restricted_2.8.0-beta05.txt b/navigation/navigation-common-ktx/api/restricted_2.8.0-beta05.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/navigation/navigation-common-ktx/api/restricted_2.8.0-beta05.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/navigation/navigation-common/api/2.8.0-beta04.txt b/navigation/navigation-common/api/2.8.0-beta04.txt
new file mode 100644
index 0000000..bb6ad19
--- /dev/null
+++ b/navigation/navigation-common/api/2.8.0-beta04.txt
@@ -0,0 +1,594 @@
+// Signature format: 4.0
+package androidx.navigation {
+
+  public final class ActionOnlyNavDirections implements androidx.navigation.NavDirections {
+    ctor public ActionOnlyNavDirections(int actionId);
+    method public int component1();
+    method public androidx.navigation.ActionOnlyNavDirections copy(int actionId);
+    method public int getActionId();
+    method public android.os.Bundle getArguments();
+    property public int actionId;
+    property public android.os.Bundle arguments;
+  }
+
+  @androidx.navigation.NavOptionsDsl public final class AnimBuilder {
+    ctor public AnimBuilder();
+    method public int getEnter();
+    method public int getExit();
+    method public int getPopEnter();
+    method public int getPopExit();
+    method public void setEnter(int);
+    method public void setExit(int);
+    method public void setPopEnter(int);
+    method public void setPopExit(int);
+    property public final int enter;
+    property public final int exit;
+    property public final int popEnter;
+    property public final int popExit;
+  }
+
+  public abstract class CollectionNavType<T> extends androidx.navigation.NavType<T> {
+    ctor public CollectionNavType(boolean isNullableAllowed);
+    method public abstract T emptyCollection();
+    method public abstract java.util.List<java.lang.String> serializeAsValues(T value);
+  }
+
+  public interface FloatingWindow {
+  }
+
+  public final class NamedNavArgument {
+    method public operator String component1();
+    method public operator androidx.navigation.NavArgument component2();
+    method public androidx.navigation.NavArgument getArgument();
+    method public String getName();
+    property public final androidx.navigation.NavArgument argument;
+    property public final String name;
+  }
+
+  public final class NamedNavArgumentKt {
+    method public static androidx.navigation.NamedNavArgument navArgument(String name, kotlin.jvm.functions.Function1<? super androidx.navigation.NavArgumentBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavAction {
+    ctor public NavAction(@IdRes int destinationId);
+    ctor public NavAction(@IdRes int destinationId, optional androidx.navigation.NavOptions? navOptions);
+    ctor public NavAction(@IdRes int destinationId, optional androidx.navigation.NavOptions? navOptions, optional android.os.Bundle? defaultArguments);
+    method public android.os.Bundle? getDefaultArguments();
+    method public int getDestinationId();
+    method public androidx.navigation.NavOptions? getNavOptions();
+    method public void setDefaultArguments(android.os.Bundle?);
+    method public void setNavOptions(androidx.navigation.NavOptions?);
+    property public final android.os.Bundle? defaultArguments;
+    property public final int destinationId;
+    property public final androidx.navigation.NavOptions? navOptions;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class NavActionBuilder {
+    ctor public NavActionBuilder();
+    method public java.util.Map<java.lang.String,java.lang.Object?> getDefaultArguments();
+    method public int getDestinationId();
+    method public void navOptions(kotlin.jvm.functions.Function1<? super androidx.navigation.NavOptionsBuilder,kotlin.Unit> optionsBuilder);
+    method public void setDestinationId(int);
+    property public final java.util.Map<java.lang.String,java.lang.Object?> defaultArguments;
+    property public final int destinationId;
+  }
+
+  public interface NavArgs {
+  }
+
+  public final class NavArgsLazy<Args extends androidx.navigation.NavArgs> implements kotlin.Lazy<Args> {
+    ctor public NavArgsLazy(kotlin.reflect.KClass<Args> navArgsClass, kotlin.jvm.functions.Function0<android.os.Bundle> argumentProducer);
+    method public Args getValue();
+    method public boolean isInitialized();
+    property public Args value;
+  }
+
+  public final class NavArgument {
+    method public Object? getDefaultValue();
+    method public androidx.navigation.NavType<java.lang.Object?> getType();
+    method public boolean isDefaultValuePresent();
+    method public boolean isNullable();
+    property public final Object? defaultValue;
+    property public final boolean isDefaultValuePresent;
+    property public final boolean isNullable;
+    property public final androidx.navigation.NavType<java.lang.Object?> type;
+  }
+
+  public static final class NavArgument.Builder {
+    ctor public NavArgument.Builder();
+    method public androidx.navigation.NavArgument build();
+    method public androidx.navigation.NavArgument.Builder setDefaultValue(Object? defaultValue);
+    method public androidx.navigation.NavArgument.Builder setIsNullable(boolean isNullable);
+    method public <T> androidx.navigation.NavArgument.Builder setType(androidx.navigation.NavType<T> type);
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class NavArgumentBuilder {
+    ctor public NavArgumentBuilder();
+    method public androidx.navigation.NavArgument build();
+    method public Object? getDefaultValue();
+    method public boolean getNullable();
+    method public androidx.navigation.NavType<? extends java.lang.Object?> getType();
+    method public void setDefaultValue(Object?);
+    method public void setNullable(boolean);
+    method public void setType(androidx.navigation.NavType<? extends java.lang.Object?>);
+    property public final Object? defaultValue;
+    property public final boolean nullable;
+    property public final androidx.navigation.NavType<? extends java.lang.Object?> type;
+  }
+
+  public final class NavBackStackEntry implements androidx.lifecycle.HasDefaultViewModelProviderFactory androidx.lifecycle.LifecycleOwner androidx.savedstate.SavedStateRegistryOwner androidx.lifecycle.ViewModelStoreOwner {
+    method public android.os.Bundle? getArguments();
+    method public androidx.lifecycle.ViewModelProvider.Factory getDefaultViewModelProviderFactory();
+    method public androidx.navigation.NavDestination getDestination();
+    method public String getId();
+    method public androidx.lifecycle.Lifecycle getLifecycle();
+    method @MainThread public androidx.lifecycle.SavedStateHandle getSavedStateHandle();
+    method public androidx.savedstate.SavedStateRegistry getSavedStateRegistry();
+    method public androidx.lifecycle.ViewModelStore getViewModelStore();
+    property public final android.os.Bundle? arguments;
+    property public androidx.lifecycle.viewmodel.CreationExtras defaultViewModelCreationExtras;
+    property public androidx.lifecycle.ViewModelProvider.Factory defaultViewModelProviderFactory;
+    property public final androidx.navigation.NavDestination destination;
+    property public final String id;
+    property public androidx.lifecycle.Lifecycle lifecycle;
+    property @MainThread public final androidx.lifecycle.SavedStateHandle savedStateHandle;
+    property public androidx.savedstate.SavedStateRegistry savedStateRegistry;
+    property public androidx.lifecycle.ViewModelStore viewModelStore;
+    field public static final androidx.navigation.NavBackStackEntry.Companion Companion;
+  }
+
+  public static final class NavBackStackEntry.Companion {
+  }
+
+  public final class NavBackStackEntryKt {
+    method public static inline <reified T> T toRoute(androidx.navigation.NavBackStackEntry);
+  }
+
+  public final class NavDeepLink {
+    method public String? getAction();
+    method public String? getMimeType();
+    method public String? getUriPattern();
+    property public final String? action;
+    property public final String? mimeType;
+    property public final String? uriPattern;
+  }
+
+  public static final class NavDeepLink.Builder {
+    method public androidx.navigation.NavDeepLink build();
+    method public static androidx.navigation.NavDeepLink.Builder fromAction(String action);
+    method public static androidx.navigation.NavDeepLink.Builder fromMimeType(String mimeType);
+    method public static androidx.navigation.NavDeepLink.Builder fromUriPattern(String uriPattern);
+    method public androidx.navigation.NavDeepLink.Builder setAction(String action);
+    method public androidx.navigation.NavDeepLink.Builder setMimeType(String mimeType);
+    method public androidx.navigation.NavDeepLink.Builder setUriPattern(String uriPattern);
+    method public inline <reified T> androidx.navigation.NavDeepLink.Builder setUriPattern(String basePath, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+  }
+
+  @kotlin.DslMarker public @interface NavDeepLinkDsl {
+  }
+
+  @androidx.navigation.NavDeepLinkDsl public final class NavDeepLinkDslBuilder {
+    ctor public NavDeepLinkDslBuilder();
+    method public String? getAction();
+    method public String? getMimeType();
+    method public String? getUriPattern();
+    method public void setAction(String?);
+    method public void setMimeType(String?);
+    method public void setUriPattern(String?);
+    property public final String? action;
+    property public final String? mimeType;
+    property public final String? uriPattern;
+  }
+
+  public final class NavDeepLinkDslBuilderKt {
+    method public static inline <reified T> androidx.navigation.NavDeepLink navDeepLink(String basePath, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, optional kotlin.jvm.functions.Function1<? super androidx.navigation.NavDeepLinkDslBuilder,kotlin.Unit> deepLinkBuilder);
+    method public static androidx.navigation.NavDeepLink navDeepLink(kotlin.jvm.functions.Function1<? super androidx.navigation.NavDeepLinkDslBuilder,kotlin.Unit> deepLinkBuilder);
+  }
+
+  public class NavDeepLinkRequest {
+    method public String? getAction();
+    method public String? getMimeType();
+    method public android.net.Uri? getUri();
+    property public String? action;
+    property public String? mimeType;
+    property public android.net.Uri? uri;
+  }
+
+  public static final class NavDeepLinkRequest.Builder {
+    method public androidx.navigation.NavDeepLinkRequest build();
+    method public static androidx.navigation.NavDeepLinkRequest.Builder fromAction(String action);
+    method public static androidx.navigation.NavDeepLinkRequest.Builder fromMimeType(String mimeType);
+    method public static androidx.navigation.NavDeepLinkRequest.Builder fromUri(android.net.Uri uri);
+    method public androidx.navigation.NavDeepLinkRequest.Builder setAction(String action);
+    method public androidx.navigation.NavDeepLinkRequest.Builder setMimeType(String mimeType);
+    method public androidx.navigation.NavDeepLinkRequest.Builder setUri(android.net.Uri uri);
+    field public static final androidx.navigation.NavDeepLinkRequest.Builder.Companion Companion;
+  }
+
+  public static final class NavDeepLinkRequest.Builder.Companion {
+    method public androidx.navigation.NavDeepLinkRequest.Builder fromAction(String action);
+    method public androidx.navigation.NavDeepLinkRequest.Builder fromMimeType(String mimeType);
+    method public androidx.navigation.NavDeepLinkRequest.Builder fromUri(android.net.Uri uri);
+  }
+
+  public class NavDestination {
+    ctor public NavDestination(androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+    ctor public NavDestination(String navigatorName);
+    method public final void addArgument(String argumentName, androidx.navigation.NavArgument argument);
+    method public final void addDeepLink(androidx.navigation.NavDeepLink navDeepLink);
+    method public final void addDeepLink(String uriPattern);
+    method public final String? fillInLabel(android.content.Context context, android.os.Bundle? bundle);
+    method public final androidx.navigation.NavAction? getAction(@IdRes int id);
+    method public final java.util.Map<java.lang.String,androidx.navigation.NavArgument> getArguments();
+    method public static final kotlin.sequences.Sequence<androidx.navigation.NavDestination> getHierarchy(androidx.navigation.NavDestination);
+    method @IdRes public final int getId();
+    method public final CharSequence? getLabel();
+    method public final String getNavigatorName();
+    method public final androidx.navigation.NavGraph? getParent();
+    method public final String? getRoute();
+    method public boolean hasDeepLink(android.net.Uri deepLink);
+    method public boolean hasDeepLink(androidx.navigation.NavDeepLinkRequest deepLinkRequest);
+    method public static final <T> boolean hasRoute(androidx.navigation.NavDestination, kotlin.reflect.KClass<T> route);
+    method @CallSuper public void onInflate(android.content.Context context, android.util.AttributeSet attrs);
+    method protected static final <C> Class<? extends C?> parseClassFromName(android.content.Context context, String name, Class<? extends C?> expectedClassType);
+    method public final void putAction(@IdRes int actionId, androidx.navigation.NavAction action);
+    method public final void putAction(@IdRes int actionId, @IdRes int destId);
+    method public final void removeAction(@IdRes int actionId);
+    method public final void removeArgument(String argumentName);
+    method public final void setId(@IdRes int);
+    method public final void setLabel(CharSequence?);
+    method public final void setRoute(String?);
+    property public final java.util.Map<java.lang.String,androidx.navigation.NavArgument> arguments;
+    property @IdRes public final int id;
+    property public final CharSequence? label;
+    property public final String navigatorName;
+    property public final androidx.navigation.NavGraph? parent;
+    property public final String? route;
+    field public static final androidx.navigation.NavDestination.Companion Companion;
+  }
+
+  @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.ANNOTATION_CLASS, kotlin.annotation.AnnotationTarget.CLASS}) public static @interface NavDestination.ClassType {
+    method public abstract Class<? extends java.lang.Object?> value();
+    property public abstract Class<? extends java.lang.Object?> value;
+  }
+
+  public static final class NavDestination.Companion {
+    method public kotlin.sequences.Sequence<androidx.navigation.NavDestination> getHierarchy(androidx.navigation.NavDestination);
+    method public inline <reified T> boolean hasRoute(androidx.navigation.NavDestination);
+    method public <T> boolean hasRoute(androidx.navigation.NavDestination, kotlin.reflect.KClass<T> route);
+    method protected <C> Class<? extends C?> parseClassFromName(android.content.Context context, String name, Class<? extends C?> expectedClassType);
+  }
+
+  @androidx.navigation.NavDestinationDsl public class NavDestinationBuilder<D extends androidx.navigation.NavDestination> {
+    ctor @Deprecated public NavDestinationBuilder(androidx.navigation.Navigator<? extends D> navigator, @IdRes int id);
+    ctor public NavDestinationBuilder(androidx.navigation.Navigator<? extends D> navigator, String? route);
+    ctor public NavDestinationBuilder(androidx.navigation.Navigator<? extends D> navigator, kotlin.reflect.KClass<? extends java.lang.Object?>? route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method @Deprecated public final void action(int actionId, kotlin.jvm.functions.Function1<? super androidx.navigation.NavActionBuilder,kotlin.Unit> actionBuilder);
+    method public final void argument(String name, androidx.navigation.NavArgument argument);
+    method public final void argument(String name, kotlin.jvm.functions.Function1<? super androidx.navigation.NavArgumentBuilder,kotlin.Unit> argumentBuilder);
+    method public D build();
+    method public final void deepLink(androidx.navigation.NavDeepLink navDeepLink);
+    method public final void deepLink(String uriPattern);
+    method public inline <reified T> void deepLink(String basePath, kotlin.jvm.functions.Function1<? super androidx.navigation.NavDeepLinkDslBuilder,kotlin.Unit> navDeepLink);
+    method public final void deepLink(kotlin.jvm.functions.Function1<? super androidx.navigation.NavDeepLinkDslBuilder,kotlin.Unit> navDeepLink);
+    method public inline <reified T> void deepLinkSafeArgs(String basePath);
+    method public final int getId();
+    method public final CharSequence? getLabel();
+    method protected final androidx.navigation.Navigator<? extends D> getNavigator();
+    method public final String? getRoute();
+    method protected D instantiateDestination();
+    method public final void setLabel(CharSequence?);
+    property public final int id;
+    property public final CharSequence? label;
+    property protected final androidx.navigation.Navigator<? extends D> navigator;
+    property public final String? route;
+  }
+
+  @kotlin.DslMarker public @interface NavDestinationDsl {
+  }
+
+  public interface NavDirections {
+    method @IdRes public int getActionId();
+    method public android.os.Bundle getArguments();
+    property @IdRes public abstract int actionId;
+    property public abstract android.os.Bundle arguments;
+  }
+
+  public class NavGraph extends androidx.navigation.NavDestination implements java.lang.Iterable<androidx.navigation.NavDestination> kotlin.jvm.internal.markers.KMappedMarker {
+    ctor public NavGraph(androidx.navigation.Navigator<? extends androidx.navigation.NavGraph> navGraphNavigator);
+    method public final void addAll(androidx.navigation.NavGraph other);
+    method public final void addDestination(androidx.navigation.NavDestination node);
+    method public final void addDestinations(androidx.navigation.NavDestination... nodes);
+    method public final void addDestinations(java.util.Collection<? extends androidx.navigation.NavDestination?> nodes);
+    method public final void clear();
+    method public inline <reified T> androidx.navigation.NavDestination? findNode();
+    method public final androidx.navigation.NavDestination? findNode(@IdRes int resId);
+    method public final androidx.navigation.NavDestination? findNode(String? route);
+    method public final <T> androidx.navigation.NavDestination? findNode(T? route);
+    method public static final androidx.navigation.NavDestination findStartDestination(androidx.navigation.NavGraph);
+    method @Deprecated @IdRes public final int getStartDestination();
+    method @IdRes public final int getStartDestinationId();
+    method public final String? getStartDestinationRoute();
+    method public final java.util.Iterator<androidx.navigation.NavDestination> iterator();
+    method public final void remove(androidx.navigation.NavDestination node);
+    method public inline <reified T> void setStartDestination();
+    method public final void setStartDestination(int startDestId);
+    method public final void setStartDestination(String startDestRoute);
+    method public final <T> void setStartDestination(T startDestRoute);
+    property @IdRes public final int startDestinationId;
+    property public final String? startDestinationRoute;
+    field public static final androidx.navigation.NavGraph.Companion Companion;
+  }
+
+  public static final class NavGraph.Companion {
+    method public androidx.navigation.NavDestination findStartDestination(androidx.navigation.NavGraph);
+  }
+
+  @androidx.navigation.NavDestinationDsl public class NavGraphBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.NavGraph> {
+    ctor @Deprecated public NavGraphBuilder(androidx.navigation.NavigatorProvider provider, @IdRes int id, @IdRes int startDestination);
+    ctor public NavGraphBuilder(androidx.navigation.NavigatorProvider provider, Object startDestination, kotlin.reflect.KClass<? extends java.lang.Object?>? route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    ctor public NavGraphBuilder(androidx.navigation.NavigatorProvider provider, String startDestination, String? route);
+    ctor public NavGraphBuilder(androidx.navigation.NavigatorProvider provider, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, kotlin.reflect.KClass<? extends java.lang.Object?>? route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public final void addDestination(androidx.navigation.NavDestination destination);
+    method public androidx.navigation.NavGraph build();
+    method public final <D extends androidx.navigation.NavDestination> void destination(androidx.navigation.NavDestinationBuilder<? extends D> navDestination);
+    method public final androidx.navigation.NavigatorProvider getProvider();
+    method public final operator void unaryPlus(androidx.navigation.NavDestination);
+    property public final androidx.navigation.NavigatorProvider provider;
+  }
+
+  public final class NavGraphBuilderKt {
+    method @Deprecated public static inline void navigation(androidx.navigation.NavGraphBuilder, @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void navigation(androidx.navigation.NavGraphBuilder, Object startDestination, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline void navigation(androidx.navigation.NavGraphBuilder, String startDestination, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void navigation(androidx.navigation.NavGraphBuilder, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, Object startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavGraphKt {
+    method public static operator boolean contains(androidx.navigation.NavGraph, @IdRes int id);
+    method public static operator boolean contains(androidx.navigation.NavGraph, String route);
+    method public static inline operator <reified T> boolean contains(androidx.navigation.NavGraph, kotlin.reflect.KClass<T> route);
+    method public static operator <T> boolean contains(androidx.navigation.NavGraph, T route);
+    method public static inline operator androidx.navigation.NavDestination get(androidx.navigation.NavGraph, @IdRes int id);
+    method public static inline operator androidx.navigation.NavDestination get(androidx.navigation.NavGraph, String route);
+    method public static inline operator <reified T> androidx.navigation.NavDestination get(androidx.navigation.NavGraph, kotlin.reflect.KClass<T> route);
+    method public static inline operator <T> androidx.navigation.NavDestination get(androidx.navigation.NavGraph, T route);
+    method public static inline operator void minusAssign(androidx.navigation.NavGraph, androidx.navigation.NavDestination node);
+    method public static inline operator void plusAssign(androidx.navigation.NavGraph, androidx.navigation.NavDestination node);
+    method public static inline operator void plusAssign(androidx.navigation.NavGraph, androidx.navigation.NavGraph other);
+  }
+
+  @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 final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getBackStack();
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> backStack;
+  }
+
+  public final class NavOptions {
+    method @AnimRes @AnimatorRes public int getEnterAnim();
+    method @AnimRes @AnimatorRes public int getExitAnim();
+    method @AnimRes @AnimatorRes public int getPopEnterAnim();
+    method @AnimRes @AnimatorRes public int getPopExitAnim();
+    method @Deprecated @IdRes public int getPopUpTo();
+    method @IdRes public int getPopUpToId();
+    method public String? getPopUpToRoute();
+    method public kotlin.reflect.KClass<? extends java.lang.Object?>? getPopUpToRouteClass();
+    method public Object? getPopUpToRouteObject();
+    method public boolean isPopUpToInclusive();
+    method public boolean shouldLaunchSingleTop();
+    method public boolean shouldPopUpToSaveState();
+    method public boolean shouldRestoreState();
+    property @AnimRes @AnimatorRes public final int enterAnim;
+    property @AnimRes @AnimatorRes public final int exitAnim;
+    property @AnimRes @AnimatorRes public final int popEnterAnim;
+    property @AnimRes @AnimatorRes public final int popExitAnim;
+    property @IdRes public final int popUpToId;
+    property public final String? popUpToRoute;
+    property public final kotlin.reflect.KClass<? extends java.lang.Object?>? popUpToRouteClass;
+    property public final Object? popUpToRouteObject;
+  }
+
+  public static final class NavOptions.Builder {
+    ctor public NavOptions.Builder();
+    method public androidx.navigation.NavOptions build();
+    method public androidx.navigation.NavOptions.Builder setEnterAnim(@AnimRes @AnimatorRes int enterAnim);
+    method public androidx.navigation.NavOptions.Builder setExitAnim(@AnimRes @AnimatorRes int exitAnim);
+    method public androidx.navigation.NavOptions.Builder setLaunchSingleTop(boolean singleTop);
+    method public androidx.navigation.NavOptions.Builder setPopEnterAnim(@AnimRes @AnimatorRes int popEnterAnim);
+    method public androidx.navigation.NavOptions.Builder setPopExitAnim(@AnimRes @AnimatorRes int popExitAnim);
+    method public inline <reified T> androidx.navigation.NavOptions.Builder setPopUpTo(boolean inclusive, optional boolean saveState);
+    method public androidx.navigation.NavOptions.Builder setPopUpTo(@IdRes int destinationId, boolean inclusive);
+    method public androidx.navigation.NavOptions.Builder setPopUpTo(@IdRes int destinationId, boolean inclusive, optional boolean saveState);
+    method public androidx.navigation.NavOptions.Builder setPopUpTo(String? route, boolean inclusive);
+    method public androidx.navigation.NavOptions.Builder setPopUpTo(String? route, boolean inclusive, optional boolean saveState);
+    method public <T> androidx.navigation.NavOptions.Builder setPopUpTo(T route, boolean inclusive);
+    method public <T> androidx.navigation.NavOptions.Builder setPopUpTo(T route, boolean inclusive, optional boolean saveState);
+    method public androidx.navigation.NavOptions.Builder setRestoreState(boolean restoreState);
+  }
+
+  @androidx.navigation.NavOptionsDsl public final class NavOptionsBuilder {
+    ctor public NavOptionsBuilder();
+    method public void anim(kotlin.jvm.functions.Function1<? super androidx.navigation.AnimBuilder,kotlin.Unit> animBuilder);
+    method public boolean getLaunchSingleTop();
+    method @Deprecated public int getPopUpTo();
+    method public int getPopUpToId();
+    method public String? getPopUpToRoute();
+    method public kotlin.reflect.KClass<? extends java.lang.Object?>? getPopUpToRouteClass();
+    method public Object? getPopUpToRouteObject();
+    method public boolean getRestoreState();
+    method public void popUpTo(@IdRes int id, optional kotlin.jvm.functions.Function1<? super androidx.navigation.PopUpToBuilder,kotlin.Unit> popUpToBuilder);
+    method public void popUpTo(String route, optional kotlin.jvm.functions.Function1<? super androidx.navigation.PopUpToBuilder,kotlin.Unit> popUpToBuilder);
+    method public inline <reified T> void popUpTo(optional kotlin.jvm.functions.Function1<? super androidx.navigation.PopUpToBuilder,kotlin.Unit> popUpToBuilder);
+    method public <T> void popUpTo(T route, optional kotlin.jvm.functions.Function1<? super androidx.navigation.PopUpToBuilder,kotlin.Unit> popUpToBuilder);
+    method public void setLaunchSingleTop(boolean);
+    method @Deprecated public void setPopUpTo(int);
+    method public void setRestoreState(boolean);
+    property public final boolean launchSingleTop;
+    property @Deprecated public final int popUpTo;
+    property public final int popUpToId;
+    property public final String? popUpToRoute;
+    property public final kotlin.reflect.KClass<? extends java.lang.Object?>? popUpToRouteClass;
+    property public final Object? popUpToRouteObject;
+    property public final boolean restoreState;
+  }
+
+  public final class NavOptionsBuilderKt {
+    method public static androidx.navigation.NavOptions navOptions(kotlin.jvm.functions.Function1<? super androidx.navigation.NavOptionsBuilder,kotlin.Unit> optionsBuilder);
+  }
+
+  @kotlin.DslMarker public @interface NavOptionsDsl {
+  }
+
+  public abstract class NavType<T> {
+    ctor public NavType(boolean isNullableAllowed);
+    method public static androidx.navigation.NavType<? extends java.lang.Object?> fromArgType(String? type, String? packageName);
+    method public abstract operator T? get(android.os.Bundle bundle, String key);
+    method public String getName();
+    method public boolean isNullableAllowed();
+    method public abstract T parseValue(String value);
+    method public T parseValue(String value, T previousValue);
+    method public abstract void put(android.os.Bundle bundle, String key, T value);
+    method public String serializeAsValue(T value);
+    method public boolean valueEquals(T value, T other);
+    property public boolean isNullableAllowed;
+    property public String name;
+    field public static final androidx.navigation.NavType<boolean[]?> BoolArrayType;
+    field public static final androidx.navigation.NavType<java.util.List<java.lang.Boolean>?> BoolListType;
+    field public static final androidx.navigation.NavType<java.lang.Boolean> BoolType;
+    field public static final androidx.navigation.NavType.Companion Companion;
+    field public static final androidx.navigation.NavType<float[]?> FloatArrayType;
+    field public static final androidx.navigation.NavType<java.util.List<java.lang.Float>?> FloatListType;
+    field public static final androidx.navigation.NavType<java.lang.Float> FloatType;
+    field public static final androidx.navigation.NavType<int[]?> IntArrayType;
+    field public static final androidx.navigation.NavType<java.util.List<java.lang.Integer>?> IntListType;
+    field public static final androidx.navigation.NavType<java.lang.Integer> IntType;
+    field public static final androidx.navigation.NavType<long[]?> LongArrayType;
+    field public static final androidx.navigation.NavType<java.util.List<java.lang.Long>?> LongListType;
+    field public static final androidx.navigation.NavType<java.lang.Long> LongType;
+    field public static final androidx.navigation.NavType<java.lang.Integer> ReferenceType;
+    field public static final androidx.navigation.NavType<java.lang.String[]?> StringArrayType;
+    field public static final androidx.navigation.NavType<java.util.List<java.lang.String>?> StringListType;
+    field public static final androidx.navigation.NavType<java.lang.String?> StringType;
+  }
+
+  public static final class NavType.Companion {
+    method public androidx.navigation.NavType<? extends java.lang.Object?> fromArgType(String? type, String? packageName);
+  }
+
+  public static final class NavType.EnumType<D extends java.lang.Enum<?>> extends androidx.navigation.NavType.SerializableType<D> {
+    ctor public NavType.EnumType(Class<D> type);
+    property public String name;
+  }
+
+  public static final class NavType.ParcelableArrayType<D extends android.os.Parcelable> extends androidx.navigation.NavType<D[]?> {
+    ctor public NavType.ParcelableArrayType(Class<D> type);
+    method public D[]? get(android.os.Bundle bundle, String key);
+    method public D[] parseValue(String value);
+    method public void put(android.os.Bundle bundle, String key, D[]? value);
+    method public boolean valueEquals(D[]? value, D[]? other);
+    property public String name;
+  }
+
+  public static final class NavType.ParcelableType<D> extends androidx.navigation.NavType<D> {
+    ctor public NavType.ParcelableType(Class<D> type);
+    method public D? get(android.os.Bundle bundle, String key);
+    method public D parseValue(String value);
+    method public void put(android.os.Bundle bundle, String key, D value);
+    property public String name;
+  }
+
+  public static final class NavType.SerializableArrayType<D extends java.io.Serializable> extends androidx.navigation.NavType<D[]?> {
+    ctor public NavType.SerializableArrayType(Class<D> type);
+    method public D[]? get(android.os.Bundle bundle, String key);
+    method public D[] parseValue(String value);
+    method public void put(android.os.Bundle bundle, String key, D[]? value);
+    method public boolean valueEquals(D[]? value, D[]? other);
+    property public String name;
+  }
+
+  public static class NavType.SerializableType<D extends java.io.Serializable> extends androidx.navigation.NavType<D> {
+    ctor public NavType.SerializableType(Class<D> type);
+    method public D? get(android.os.Bundle bundle, String key);
+    method public D parseValue(String value);
+    method public void put(android.os.Bundle bundle, String key, D value);
+    property public String name;
+  }
+
+  public abstract class Navigator<D extends androidx.navigation.NavDestination> {
+    ctor public Navigator();
+    method public abstract D createDestination();
+    method protected final androidx.navigation.NavigatorState getState();
+    method public final boolean isAttached();
+    method public androidx.navigation.NavDestination? navigate(D destination, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method public void navigate(java.util.List<androidx.navigation.NavBackStackEntry> entries, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @CallSuper public void onAttach(androidx.navigation.NavigatorState state);
+    method public void onLaunchSingleTop(androidx.navigation.NavBackStackEntry backStackEntry);
+    method public void onRestoreState(android.os.Bundle savedState);
+    method public android.os.Bundle? onSaveState();
+    method public boolean popBackStack();
+    method public void popBackStack(androidx.navigation.NavBackStackEntry popUpTo, boolean savedState);
+    property public final boolean isAttached;
+    property protected final androidx.navigation.NavigatorState state;
+  }
+
+  public static interface Navigator.Extras {
+  }
+
+  @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.RUNTIME) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.ANNOTATION_CLASS, kotlin.annotation.AnnotationTarget.CLASS}) public static @interface Navigator.Name {
+    method public abstract String value();
+    property public abstract String value;
+  }
+
+  public class NavigatorProvider {
+    ctor public NavigatorProvider();
+    method public final androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>? addNavigator(androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+    method @CallSuper public androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>? addNavigator(String name, androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+    method public final <T extends androidx.navigation.Navigator<?>> T getNavigator(Class<T> navigatorClass);
+    method @CallSuper public <T extends androidx.navigation.Navigator<?>> T getNavigator(String name);
+  }
+
+  public final class NavigatorProviderKt {
+    method public static inline operator <T extends androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>> T get(androidx.navigation.NavigatorProvider, String name);
+    method public static inline operator <T extends androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>> T get(androidx.navigation.NavigatorProvider, kotlin.reflect.KClass<T> clazz);
+    method public static inline operator void plusAssign(androidx.navigation.NavigatorProvider, androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+    method public static inline operator androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>? set(androidx.navigation.NavigatorProvider, String name, androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+  }
+
+  public abstract class NavigatorState {
+    ctor public NavigatorState();
+    method public abstract androidx.navigation.NavBackStackEntry createBackStackEntry(androidx.navigation.NavDestination destination, android.os.Bundle? arguments);
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getBackStack();
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.Set<androidx.navigation.NavBackStackEntry>> getTransitionsInProgress();
+    method public void markTransitionComplete(androidx.navigation.NavBackStackEntry entry);
+    method @CallSuper public void onLaunchSingleTop(androidx.navigation.NavBackStackEntry backStackEntry);
+    method @CallSuper public void onLaunchSingleTopWithTransition(androidx.navigation.NavBackStackEntry backStackEntry);
+    method public void pop(androidx.navigation.NavBackStackEntry popUpTo, boolean saveState);
+    method public void popWithTransition(androidx.navigation.NavBackStackEntry popUpTo, boolean saveState);
+    method @CallSuper public void prepareForTransition(androidx.navigation.NavBackStackEntry entry);
+    method public void push(androidx.navigation.NavBackStackEntry backStackEntry);
+    method public void pushWithTransition(androidx.navigation.NavBackStackEntry backStackEntry);
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> backStack;
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.Set<androidx.navigation.NavBackStackEntry>> transitionsInProgress;
+  }
+
+  @androidx.navigation.NavOptionsDsl public final class PopUpToBuilder {
+    ctor public PopUpToBuilder();
+    method public boolean getInclusive();
+    method public boolean getSaveState();
+    method public void setInclusive(boolean);
+    method public void setSaveState(boolean);
+    property public final boolean inclusive;
+    property public final boolean saveState;
+  }
+
+  public final class SavedStateHandleKt {
+    method public static inline <reified T> T toRoute(androidx.lifecycle.SavedStateHandle, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+  }
+
+}
+
diff --git a/navigation/navigation-common/api/2.8.0-beta05.txt b/navigation/navigation-common/api/2.8.0-beta05.txt
new file mode 100644
index 0000000..bb6ad19
--- /dev/null
+++ b/navigation/navigation-common/api/2.8.0-beta05.txt
@@ -0,0 +1,594 @@
+// Signature format: 4.0
+package androidx.navigation {
+
+  public final class ActionOnlyNavDirections implements androidx.navigation.NavDirections {
+    ctor public ActionOnlyNavDirections(int actionId);
+    method public int component1();
+    method public androidx.navigation.ActionOnlyNavDirections copy(int actionId);
+    method public int getActionId();
+    method public android.os.Bundle getArguments();
+    property public int actionId;
+    property public android.os.Bundle arguments;
+  }
+
+  @androidx.navigation.NavOptionsDsl public final class AnimBuilder {
+    ctor public AnimBuilder();
+    method public int getEnter();
+    method public int getExit();
+    method public int getPopEnter();
+    method public int getPopExit();
+    method public void setEnter(int);
+    method public void setExit(int);
+    method public void setPopEnter(int);
+    method public void setPopExit(int);
+    property public final int enter;
+    property public final int exit;
+    property public final int popEnter;
+    property public final int popExit;
+  }
+
+  public abstract class CollectionNavType<T> extends androidx.navigation.NavType<T> {
+    ctor public CollectionNavType(boolean isNullableAllowed);
+    method public abstract T emptyCollection();
+    method public abstract java.util.List<java.lang.String> serializeAsValues(T value);
+  }
+
+  public interface FloatingWindow {
+  }
+
+  public final class NamedNavArgument {
+    method public operator String component1();
+    method public operator androidx.navigation.NavArgument component2();
+    method public androidx.navigation.NavArgument getArgument();
+    method public String getName();
+    property public final androidx.navigation.NavArgument argument;
+    property public final String name;
+  }
+
+  public final class NamedNavArgumentKt {
+    method public static androidx.navigation.NamedNavArgument navArgument(String name, kotlin.jvm.functions.Function1<? super androidx.navigation.NavArgumentBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavAction {
+    ctor public NavAction(@IdRes int destinationId);
+    ctor public NavAction(@IdRes int destinationId, optional androidx.navigation.NavOptions? navOptions);
+    ctor public NavAction(@IdRes int destinationId, optional androidx.navigation.NavOptions? navOptions, optional android.os.Bundle? defaultArguments);
+    method public android.os.Bundle? getDefaultArguments();
+    method public int getDestinationId();
+    method public androidx.navigation.NavOptions? getNavOptions();
+    method public void setDefaultArguments(android.os.Bundle?);
+    method public void setNavOptions(androidx.navigation.NavOptions?);
+    property public final android.os.Bundle? defaultArguments;
+    property public final int destinationId;
+    property public final androidx.navigation.NavOptions? navOptions;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class NavActionBuilder {
+    ctor public NavActionBuilder();
+    method public java.util.Map<java.lang.String,java.lang.Object?> getDefaultArguments();
+    method public int getDestinationId();
+    method public void navOptions(kotlin.jvm.functions.Function1<? super androidx.navigation.NavOptionsBuilder,kotlin.Unit> optionsBuilder);
+    method public void setDestinationId(int);
+    property public final java.util.Map<java.lang.String,java.lang.Object?> defaultArguments;
+    property public final int destinationId;
+  }
+
+  public interface NavArgs {
+  }
+
+  public final class NavArgsLazy<Args extends androidx.navigation.NavArgs> implements kotlin.Lazy<Args> {
+    ctor public NavArgsLazy(kotlin.reflect.KClass<Args> navArgsClass, kotlin.jvm.functions.Function0<android.os.Bundle> argumentProducer);
+    method public Args getValue();
+    method public boolean isInitialized();
+    property public Args value;
+  }
+
+  public final class NavArgument {
+    method public Object? getDefaultValue();
+    method public androidx.navigation.NavType<java.lang.Object?> getType();
+    method public boolean isDefaultValuePresent();
+    method public boolean isNullable();
+    property public final Object? defaultValue;
+    property public final boolean isDefaultValuePresent;
+    property public final boolean isNullable;
+    property public final androidx.navigation.NavType<java.lang.Object?> type;
+  }
+
+  public static final class NavArgument.Builder {
+    ctor public NavArgument.Builder();
+    method public androidx.navigation.NavArgument build();
+    method public androidx.navigation.NavArgument.Builder setDefaultValue(Object? defaultValue);
+    method public androidx.navigation.NavArgument.Builder setIsNullable(boolean isNullable);
+    method public <T> androidx.navigation.NavArgument.Builder setType(androidx.navigation.NavType<T> type);
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class NavArgumentBuilder {
+    ctor public NavArgumentBuilder();
+    method public androidx.navigation.NavArgument build();
+    method public Object? getDefaultValue();
+    method public boolean getNullable();
+    method public androidx.navigation.NavType<? extends java.lang.Object?> getType();
+    method public void setDefaultValue(Object?);
+    method public void setNullable(boolean);
+    method public void setType(androidx.navigation.NavType<? extends java.lang.Object?>);
+    property public final Object? defaultValue;
+    property public final boolean nullable;
+    property public final androidx.navigation.NavType<? extends java.lang.Object?> type;
+  }
+
+  public final class NavBackStackEntry implements androidx.lifecycle.HasDefaultViewModelProviderFactory androidx.lifecycle.LifecycleOwner androidx.savedstate.SavedStateRegistryOwner androidx.lifecycle.ViewModelStoreOwner {
+    method public android.os.Bundle? getArguments();
+    method public androidx.lifecycle.ViewModelProvider.Factory getDefaultViewModelProviderFactory();
+    method public androidx.navigation.NavDestination getDestination();
+    method public String getId();
+    method public androidx.lifecycle.Lifecycle getLifecycle();
+    method @MainThread public androidx.lifecycle.SavedStateHandle getSavedStateHandle();
+    method public androidx.savedstate.SavedStateRegistry getSavedStateRegistry();
+    method public androidx.lifecycle.ViewModelStore getViewModelStore();
+    property public final android.os.Bundle? arguments;
+    property public androidx.lifecycle.viewmodel.CreationExtras defaultViewModelCreationExtras;
+    property public androidx.lifecycle.ViewModelProvider.Factory defaultViewModelProviderFactory;
+    property public final androidx.navigation.NavDestination destination;
+    property public final String id;
+    property public androidx.lifecycle.Lifecycle lifecycle;
+    property @MainThread public final androidx.lifecycle.SavedStateHandle savedStateHandle;
+    property public androidx.savedstate.SavedStateRegistry savedStateRegistry;
+    property public androidx.lifecycle.ViewModelStore viewModelStore;
+    field public static final androidx.navigation.NavBackStackEntry.Companion Companion;
+  }
+
+  public static final class NavBackStackEntry.Companion {
+  }
+
+  public final class NavBackStackEntryKt {
+    method public static inline <reified T> T toRoute(androidx.navigation.NavBackStackEntry);
+  }
+
+  public final class NavDeepLink {
+    method public String? getAction();
+    method public String? getMimeType();
+    method public String? getUriPattern();
+    property public final String? action;
+    property public final String? mimeType;
+    property public final String? uriPattern;
+  }
+
+  public static final class NavDeepLink.Builder {
+    method public androidx.navigation.NavDeepLink build();
+    method public static androidx.navigation.NavDeepLink.Builder fromAction(String action);
+    method public static androidx.navigation.NavDeepLink.Builder fromMimeType(String mimeType);
+    method public static androidx.navigation.NavDeepLink.Builder fromUriPattern(String uriPattern);
+    method public androidx.navigation.NavDeepLink.Builder setAction(String action);
+    method public androidx.navigation.NavDeepLink.Builder setMimeType(String mimeType);
+    method public androidx.navigation.NavDeepLink.Builder setUriPattern(String uriPattern);
+    method public inline <reified T> androidx.navigation.NavDeepLink.Builder setUriPattern(String basePath, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+  }
+
+  @kotlin.DslMarker public @interface NavDeepLinkDsl {
+  }
+
+  @androidx.navigation.NavDeepLinkDsl public final class NavDeepLinkDslBuilder {
+    ctor public NavDeepLinkDslBuilder();
+    method public String? getAction();
+    method public String? getMimeType();
+    method public String? getUriPattern();
+    method public void setAction(String?);
+    method public void setMimeType(String?);
+    method public void setUriPattern(String?);
+    property public final String? action;
+    property public final String? mimeType;
+    property public final String? uriPattern;
+  }
+
+  public final class NavDeepLinkDslBuilderKt {
+    method public static inline <reified T> androidx.navigation.NavDeepLink navDeepLink(String basePath, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, optional kotlin.jvm.functions.Function1<? super androidx.navigation.NavDeepLinkDslBuilder,kotlin.Unit> deepLinkBuilder);
+    method public static androidx.navigation.NavDeepLink navDeepLink(kotlin.jvm.functions.Function1<? super androidx.navigation.NavDeepLinkDslBuilder,kotlin.Unit> deepLinkBuilder);
+  }
+
+  public class NavDeepLinkRequest {
+    method public String? getAction();
+    method public String? getMimeType();
+    method public android.net.Uri? getUri();
+    property public String? action;
+    property public String? mimeType;
+    property public android.net.Uri? uri;
+  }
+
+  public static final class NavDeepLinkRequest.Builder {
+    method public androidx.navigation.NavDeepLinkRequest build();
+    method public static androidx.navigation.NavDeepLinkRequest.Builder fromAction(String action);
+    method public static androidx.navigation.NavDeepLinkRequest.Builder fromMimeType(String mimeType);
+    method public static androidx.navigation.NavDeepLinkRequest.Builder fromUri(android.net.Uri uri);
+    method public androidx.navigation.NavDeepLinkRequest.Builder setAction(String action);
+    method public androidx.navigation.NavDeepLinkRequest.Builder setMimeType(String mimeType);
+    method public androidx.navigation.NavDeepLinkRequest.Builder setUri(android.net.Uri uri);
+    field public static final androidx.navigation.NavDeepLinkRequest.Builder.Companion Companion;
+  }
+
+  public static final class NavDeepLinkRequest.Builder.Companion {
+    method public androidx.navigation.NavDeepLinkRequest.Builder fromAction(String action);
+    method public androidx.navigation.NavDeepLinkRequest.Builder fromMimeType(String mimeType);
+    method public androidx.navigation.NavDeepLinkRequest.Builder fromUri(android.net.Uri uri);
+  }
+
+  public class NavDestination {
+    ctor public NavDestination(androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+    ctor public NavDestination(String navigatorName);
+    method public final void addArgument(String argumentName, androidx.navigation.NavArgument argument);
+    method public final void addDeepLink(androidx.navigation.NavDeepLink navDeepLink);
+    method public final void addDeepLink(String uriPattern);
+    method public final String? fillInLabel(android.content.Context context, android.os.Bundle? bundle);
+    method public final androidx.navigation.NavAction? getAction(@IdRes int id);
+    method public final java.util.Map<java.lang.String,androidx.navigation.NavArgument> getArguments();
+    method public static final kotlin.sequences.Sequence<androidx.navigation.NavDestination> getHierarchy(androidx.navigation.NavDestination);
+    method @IdRes public final int getId();
+    method public final CharSequence? getLabel();
+    method public final String getNavigatorName();
+    method public final androidx.navigation.NavGraph? getParent();
+    method public final String? getRoute();
+    method public boolean hasDeepLink(android.net.Uri deepLink);
+    method public boolean hasDeepLink(androidx.navigation.NavDeepLinkRequest deepLinkRequest);
+    method public static final <T> boolean hasRoute(androidx.navigation.NavDestination, kotlin.reflect.KClass<T> route);
+    method @CallSuper public void onInflate(android.content.Context context, android.util.AttributeSet attrs);
+    method protected static final <C> Class<? extends C?> parseClassFromName(android.content.Context context, String name, Class<? extends C?> expectedClassType);
+    method public final void putAction(@IdRes int actionId, androidx.navigation.NavAction action);
+    method public final void putAction(@IdRes int actionId, @IdRes int destId);
+    method public final void removeAction(@IdRes int actionId);
+    method public final void removeArgument(String argumentName);
+    method public final void setId(@IdRes int);
+    method public final void setLabel(CharSequence?);
+    method public final void setRoute(String?);
+    property public final java.util.Map<java.lang.String,androidx.navigation.NavArgument> arguments;
+    property @IdRes public final int id;
+    property public final CharSequence? label;
+    property public final String navigatorName;
+    property public final androidx.navigation.NavGraph? parent;
+    property public final String? route;
+    field public static final androidx.navigation.NavDestination.Companion Companion;
+  }
+
+  @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.ANNOTATION_CLASS, kotlin.annotation.AnnotationTarget.CLASS}) public static @interface NavDestination.ClassType {
+    method public abstract Class<? extends java.lang.Object?> value();
+    property public abstract Class<? extends java.lang.Object?> value;
+  }
+
+  public static final class NavDestination.Companion {
+    method public kotlin.sequences.Sequence<androidx.navigation.NavDestination> getHierarchy(androidx.navigation.NavDestination);
+    method public inline <reified T> boolean hasRoute(androidx.navigation.NavDestination);
+    method public <T> boolean hasRoute(androidx.navigation.NavDestination, kotlin.reflect.KClass<T> route);
+    method protected <C> Class<? extends C?> parseClassFromName(android.content.Context context, String name, Class<? extends C?> expectedClassType);
+  }
+
+  @androidx.navigation.NavDestinationDsl public class NavDestinationBuilder<D extends androidx.navigation.NavDestination> {
+    ctor @Deprecated public NavDestinationBuilder(androidx.navigation.Navigator<? extends D> navigator, @IdRes int id);
+    ctor public NavDestinationBuilder(androidx.navigation.Navigator<? extends D> navigator, String? route);
+    ctor public NavDestinationBuilder(androidx.navigation.Navigator<? extends D> navigator, kotlin.reflect.KClass<? extends java.lang.Object?>? route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method @Deprecated public final void action(int actionId, kotlin.jvm.functions.Function1<? super androidx.navigation.NavActionBuilder,kotlin.Unit> actionBuilder);
+    method public final void argument(String name, androidx.navigation.NavArgument argument);
+    method public final void argument(String name, kotlin.jvm.functions.Function1<? super androidx.navigation.NavArgumentBuilder,kotlin.Unit> argumentBuilder);
+    method public D build();
+    method public final void deepLink(androidx.navigation.NavDeepLink navDeepLink);
+    method public final void deepLink(String uriPattern);
+    method public inline <reified T> void deepLink(String basePath, kotlin.jvm.functions.Function1<? super androidx.navigation.NavDeepLinkDslBuilder,kotlin.Unit> navDeepLink);
+    method public final void deepLink(kotlin.jvm.functions.Function1<? super androidx.navigation.NavDeepLinkDslBuilder,kotlin.Unit> navDeepLink);
+    method public inline <reified T> void deepLinkSafeArgs(String basePath);
+    method public final int getId();
+    method public final CharSequence? getLabel();
+    method protected final androidx.navigation.Navigator<? extends D> getNavigator();
+    method public final String? getRoute();
+    method protected D instantiateDestination();
+    method public final void setLabel(CharSequence?);
+    property public final int id;
+    property public final CharSequence? label;
+    property protected final androidx.navigation.Navigator<? extends D> navigator;
+    property public final String? route;
+  }
+
+  @kotlin.DslMarker public @interface NavDestinationDsl {
+  }
+
+  public interface NavDirections {
+    method @IdRes public int getActionId();
+    method public android.os.Bundle getArguments();
+    property @IdRes public abstract int actionId;
+    property public abstract android.os.Bundle arguments;
+  }
+
+  public class NavGraph extends androidx.navigation.NavDestination implements java.lang.Iterable<androidx.navigation.NavDestination> kotlin.jvm.internal.markers.KMappedMarker {
+    ctor public NavGraph(androidx.navigation.Navigator<? extends androidx.navigation.NavGraph> navGraphNavigator);
+    method public final void addAll(androidx.navigation.NavGraph other);
+    method public final void addDestination(androidx.navigation.NavDestination node);
+    method public final void addDestinations(androidx.navigation.NavDestination... nodes);
+    method public final void addDestinations(java.util.Collection<? extends androidx.navigation.NavDestination?> nodes);
+    method public final void clear();
+    method public inline <reified T> androidx.navigation.NavDestination? findNode();
+    method public final androidx.navigation.NavDestination? findNode(@IdRes int resId);
+    method public final androidx.navigation.NavDestination? findNode(String? route);
+    method public final <T> androidx.navigation.NavDestination? findNode(T? route);
+    method public static final androidx.navigation.NavDestination findStartDestination(androidx.navigation.NavGraph);
+    method @Deprecated @IdRes public final int getStartDestination();
+    method @IdRes public final int getStartDestinationId();
+    method public final String? getStartDestinationRoute();
+    method public final java.util.Iterator<androidx.navigation.NavDestination> iterator();
+    method public final void remove(androidx.navigation.NavDestination node);
+    method public inline <reified T> void setStartDestination();
+    method public final void setStartDestination(int startDestId);
+    method public final void setStartDestination(String startDestRoute);
+    method public final <T> void setStartDestination(T startDestRoute);
+    property @IdRes public final int startDestinationId;
+    property public final String? startDestinationRoute;
+    field public static final androidx.navigation.NavGraph.Companion Companion;
+  }
+
+  public static final class NavGraph.Companion {
+    method public androidx.navigation.NavDestination findStartDestination(androidx.navigation.NavGraph);
+  }
+
+  @androidx.navigation.NavDestinationDsl public class NavGraphBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.NavGraph> {
+    ctor @Deprecated public NavGraphBuilder(androidx.navigation.NavigatorProvider provider, @IdRes int id, @IdRes int startDestination);
+    ctor public NavGraphBuilder(androidx.navigation.NavigatorProvider provider, Object startDestination, kotlin.reflect.KClass<? extends java.lang.Object?>? route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    ctor public NavGraphBuilder(androidx.navigation.NavigatorProvider provider, String startDestination, String? route);
+    ctor public NavGraphBuilder(androidx.navigation.NavigatorProvider provider, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, kotlin.reflect.KClass<? extends java.lang.Object?>? route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public final void addDestination(androidx.navigation.NavDestination destination);
+    method public androidx.navigation.NavGraph build();
+    method public final <D extends androidx.navigation.NavDestination> void destination(androidx.navigation.NavDestinationBuilder<? extends D> navDestination);
+    method public final androidx.navigation.NavigatorProvider getProvider();
+    method public final operator void unaryPlus(androidx.navigation.NavDestination);
+    property public final androidx.navigation.NavigatorProvider provider;
+  }
+
+  public final class NavGraphBuilderKt {
+    method @Deprecated public static inline void navigation(androidx.navigation.NavGraphBuilder, @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void navigation(androidx.navigation.NavGraphBuilder, Object startDestination, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline void navigation(androidx.navigation.NavGraphBuilder, String startDestination, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void navigation(androidx.navigation.NavGraphBuilder, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, Object startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavGraphKt {
+    method public static operator boolean contains(androidx.navigation.NavGraph, @IdRes int id);
+    method public static operator boolean contains(androidx.navigation.NavGraph, String route);
+    method public static inline operator <reified T> boolean contains(androidx.navigation.NavGraph, kotlin.reflect.KClass<T> route);
+    method public static operator <T> boolean contains(androidx.navigation.NavGraph, T route);
+    method public static inline operator androidx.navigation.NavDestination get(androidx.navigation.NavGraph, @IdRes int id);
+    method public static inline operator androidx.navigation.NavDestination get(androidx.navigation.NavGraph, String route);
+    method public static inline operator <reified T> androidx.navigation.NavDestination get(androidx.navigation.NavGraph, kotlin.reflect.KClass<T> route);
+    method public static inline operator <T> androidx.navigation.NavDestination get(androidx.navigation.NavGraph, T route);
+    method public static inline operator void minusAssign(androidx.navigation.NavGraph, androidx.navigation.NavDestination node);
+    method public static inline operator void plusAssign(androidx.navigation.NavGraph, androidx.navigation.NavDestination node);
+    method public static inline operator void plusAssign(androidx.navigation.NavGraph, androidx.navigation.NavGraph other);
+  }
+
+  @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 final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getBackStack();
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> backStack;
+  }
+
+  public final class NavOptions {
+    method @AnimRes @AnimatorRes public int getEnterAnim();
+    method @AnimRes @AnimatorRes public int getExitAnim();
+    method @AnimRes @AnimatorRes public int getPopEnterAnim();
+    method @AnimRes @AnimatorRes public int getPopExitAnim();
+    method @Deprecated @IdRes public int getPopUpTo();
+    method @IdRes public int getPopUpToId();
+    method public String? getPopUpToRoute();
+    method public kotlin.reflect.KClass<? extends java.lang.Object?>? getPopUpToRouteClass();
+    method public Object? getPopUpToRouteObject();
+    method public boolean isPopUpToInclusive();
+    method public boolean shouldLaunchSingleTop();
+    method public boolean shouldPopUpToSaveState();
+    method public boolean shouldRestoreState();
+    property @AnimRes @AnimatorRes public final int enterAnim;
+    property @AnimRes @AnimatorRes public final int exitAnim;
+    property @AnimRes @AnimatorRes public final int popEnterAnim;
+    property @AnimRes @AnimatorRes public final int popExitAnim;
+    property @IdRes public final int popUpToId;
+    property public final String? popUpToRoute;
+    property public final kotlin.reflect.KClass<? extends java.lang.Object?>? popUpToRouteClass;
+    property public final Object? popUpToRouteObject;
+  }
+
+  public static final class NavOptions.Builder {
+    ctor public NavOptions.Builder();
+    method public androidx.navigation.NavOptions build();
+    method public androidx.navigation.NavOptions.Builder setEnterAnim(@AnimRes @AnimatorRes int enterAnim);
+    method public androidx.navigation.NavOptions.Builder setExitAnim(@AnimRes @AnimatorRes int exitAnim);
+    method public androidx.navigation.NavOptions.Builder setLaunchSingleTop(boolean singleTop);
+    method public androidx.navigation.NavOptions.Builder setPopEnterAnim(@AnimRes @AnimatorRes int popEnterAnim);
+    method public androidx.navigation.NavOptions.Builder setPopExitAnim(@AnimRes @AnimatorRes int popExitAnim);
+    method public inline <reified T> androidx.navigation.NavOptions.Builder setPopUpTo(boolean inclusive, optional boolean saveState);
+    method public androidx.navigation.NavOptions.Builder setPopUpTo(@IdRes int destinationId, boolean inclusive);
+    method public androidx.navigation.NavOptions.Builder setPopUpTo(@IdRes int destinationId, boolean inclusive, optional boolean saveState);
+    method public androidx.navigation.NavOptions.Builder setPopUpTo(String? route, boolean inclusive);
+    method public androidx.navigation.NavOptions.Builder setPopUpTo(String? route, boolean inclusive, optional boolean saveState);
+    method public <T> androidx.navigation.NavOptions.Builder setPopUpTo(T route, boolean inclusive);
+    method public <T> androidx.navigation.NavOptions.Builder setPopUpTo(T route, boolean inclusive, optional boolean saveState);
+    method public androidx.navigation.NavOptions.Builder setRestoreState(boolean restoreState);
+  }
+
+  @androidx.navigation.NavOptionsDsl public final class NavOptionsBuilder {
+    ctor public NavOptionsBuilder();
+    method public void anim(kotlin.jvm.functions.Function1<? super androidx.navigation.AnimBuilder,kotlin.Unit> animBuilder);
+    method public boolean getLaunchSingleTop();
+    method @Deprecated public int getPopUpTo();
+    method public int getPopUpToId();
+    method public String? getPopUpToRoute();
+    method public kotlin.reflect.KClass<? extends java.lang.Object?>? getPopUpToRouteClass();
+    method public Object? getPopUpToRouteObject();
+    method public boolean getRestoreState();
+    method public void popUpTo(@IdRes int id, optional kotlin.jvm.functions.Function1<? super androidx.navigation.PopUpToBuilder,kotlin.Unit> popUpToBuilder);
+    method public void popUpTo(String route, optional kotlin.jvm.functions.Function1<? super androidx.navigation.PopUpToBuilder,kotlin.Unit> popUpToBuilder);
+    method public inline <reified T> void popUpTo(optional kotlin.jvm.functions.Function1<? super androidx.navigation.PopUpToBuilder,kotlin.Unit> popUpToBuilder);
+    method public <T> void popUpTo(T route, optional kotlin.jvm.functions.Function1<? super androidx.navigation.PopUpToBuilder,kotlin.Unit> popUpToBuilder);
+    method public void setLaunchSingleTop(boolean);
+    method @Deprecated public void setPopUpTo(int);
+    method public void setRestoreState(boolean);
+    property public final boolean launchSingleTop;
+    property @Deprecated public final int popUpTo;
+    property public final int popUpToId;
+    property public final String? popUpToRoute;
+    property public final kotlin.reflect.KClass<? extends java.lang.Object?>? popUpToRouteClass;
+    property public final Object? popUpToRouteObject;
+    property public final boolean restoreState;
+  }
+
+  public final class NavOptionsBuilderKt {
+    method public static androidx.navigation.NavOptions navOptions(kotlin.jvm.functions.Function1<? super androidx.navigation.NavOptionsBuilder,kotlin.Unit> optionsBuilder);
+  }
+
+  @kotlin.DslMarker public @interface NavOptionsDsl {
+  }
+
+  public abstract class NavType<T> {
+    ctor public NavType(boolean isNullableAllowed);
+    method public static androidx.navigation.NavType<? extends java.lang.Object?> fromArgType(String? type, String? packageName);
+    method public abstract operator T? get(android.os.Bundle bundle, String key);
+    method public String getName();
+    method public boolean isNullableAllowed();
+    method public abstract T parseValue(String value);
+    method public T parseValue(String value, T previousValue);
+    method public abstract void put(android.os.Bundle bundle, String key, T value);
+    method public String serializeAsValue(T value);
+    method public boolean valueEquals(T value, T other);
+    property public boolean isNullableAllowed;
+    property public String name;
+    field public static final androidx.navigation.NavType<boolean[]?> BoolArrayType;
+    field public static final androidx.navigation.NavType<java.util.List<java.lang.Boolean>?> BoolListType;
+    field public static final androidx.navigation.NavType<java.lang.Boolean> BoolType;
+    field public static final androidx.navigation.NavType.Companion Companion;
+    field public static final androidx.navigation.NavType<float[]?> FloatArrayType;
+    field public static final androidx.navigation.NavType<java.util.List<java.lang.Float>?> FloatListType;
+    field public static final androidx.navigation.NavType<java.lang.Float> FloatType;
+    field public static final androidx.navigation.NavType<int[]?> IntArrayType;
+    field public static final androidx.navigation.NavType<java.util.List<java.lang.Integer>?> IntListType;
+    field public static final androidx.navigation.NavType<java.lang.Integer> IntType;
+    field public static final androidx.navigation.NavType<long[]?> LongArrayType;
+    field public static final androidx.navigation.NavType<java.util.List<java.lang.Long>?> LongListType;
+    field public static final androidx.navigation.NavType<java.lang.Long> LongType;
+    field public static final androidx.navigation.NavType<java.lang.Integer> ReferenceType;
+    field public static final androidx.navigation.NavType<java.lang.String[]?> StringArrayType;
+    field public static final androidx.navigation.NavType<java.util.List<java.lang.String>?> StringListType;
+    field public static final androidx.navigation.NavType<java.lang.String?> StringType;
+  }
+
+  public static final class NavType.Companion {
+    method public androidx.navigation.NavType<? extends java.lang.Object?> fromArgType(String? type, String? packageName);
+  }
+
+  public static final class NavType.EnumType<D extends java.lang.Enum<?>> extends androidx.navigation.NavType.SerializableType<D> {
+    ctor public NavType.EnumType(Class<D> type);
+    property public String name;
+  }
+
+  public static final class NavType.ParcelableArrayType<D extends android.os.Parcelable> extends androidx.navigation.NavType<D[]?> {
+    ctor public NavType.ParcelableArrayType(Class<D> type);
+    method public D[]? get(android.os.Bundle bundle, String key);
+    method public D[] parseValue(String value);
+    method public void put(android.os.Bundle bundle, String key, D[]? value);
+    method public boolean valueEquals(D[]? value, D[]? other);
+    property public String name;
+  }
+
+  public static final class NavType.ParcelableType<D> extends androidx.navigation.NavType<D> {
+    ctor public NavType.ParcelableType(Class<D> type);
+    method public D? get(android.os.Bundle bundle, String key);
+    method public D parseValue(String value);
+    method public void put(android.os.Bundle bundle, String key, D value);
+    property public String name;
+  }
+
+  public static final class NavType.SerializableArrayType<D extends java.io.Serializable> extends androidx.navigation.NavType<D[]?> {
+    ctor public NavType.SerializableArrayType(Class<D> type);
+    method public D[]? get(android.os.Bundle bundle, String key);
+    method public D[] parseValue(String value);
+    method public void put(android.os.Bundle bundle, String key, D[]? value);
+    method public boolean valueEquals(D[]? value, D[]? other);
+    property public String name;
+  }
+
+  public static class NavType.SerializableType<D extends java.io.Serializable> extends androidx.navigation.NavType<D> {
+    ctor public NavType.SerializableType(Class<D> type);
+    method public D? get(android.os.Bundle bundle, String key);
+    method public D parseValue(String value);
+    method public void put(android.os.Bundle bundle, String key, D value);
+    property public String name;
+  }
+
+  public abstract class Navigator<D extends androidx.navigation.NavDestination> {
+    ctor public Navigator();
+    method public abstract D createDestination();
+    method protected final androidx.navigation.NavigatorState getState();
+    method public final boolean isAttached();
+    method public androidx.navigation.NavDestination? navigate(D destination, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method public void navigate(java.util.List<androidx.navigation.NavBackStackEntry> entries, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @CallSuper public void onAttach(androidx.navigation.NavigatorState state);
+    method public void onLaunchSingleTop(androidx.navigation.NavBackStackEntry backStackEntry);
+    method public void onRestoreState(android.os.Bundle savedState);
+    method public android.os.Bundle? onSaveState();
+    method public boolean popBackStack();
+    method public void popBackStack(androidx.navigation.NavBackStackEntry popUpTo, boolean savedState);
+    property public final boolean isAttached;
+    property protected final androidx.navigation.NavigatorState state;
+  }
+
+  public static interface Navigator.Extras {
+  }
+
+  @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.RUNTIME) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.ANNOTATION_CLASS, kotlin.annotation.AnnotationTarget.CLASS}) public static @interface Navigator.Name {
+    method public abstract String value();
+    property public abstract String value;
+  }
+
+  public class NavigatorProvider {
+    ctor public NavigatorProvider();
+    method public final androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>? addNavigator(androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+    method @CallSuper public androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>? addNavigator(String name, androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+    method public final <T extends androidx.navigation.Navigator<?>> T getNavigator(Class<T> navigatorClass);
+    method @CallSuper public <T extends androidx.navigation.Navigator<?>> T getNavigator(String name);
+  }
+
+  public final class NavigatorProviderKt {
+    method public static inline operator <T extends androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>> T get(androidx.navigation.NavigatorProvider, String name);
+    method public static inline operator <T extends androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>> T get(androidx.navigation.NavigatorProvider, kotlin.reflect.KClass<T> clazz);
+    method public static inline operator void plusAssign(androidx.navigation.NavigatorProvider, androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+    method public static inline operator androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>? set(androidx.navigation.NavigatorProvider, String name, androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+  }
+
+  public abstract class NavigatorState {
+    ctor public NavigatorState();
+    method public abstract androidx.navigation.NavBackStackEntry createBackStackEntry(androidx.navigation.NavDestination destination, android.os.Bundle? arguments);
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getBackStack();
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.Set<androidx.navigation.NavBackStackEntry>> getTransitionsInProgress();
+    method public void markTransitionComplete(androidx.navigation.NavBackStackEntry entry);
+    method @CallSuper public void onLaunchSingleTop(androidx.navigation.NavBackStackEntry backStackEntry);
+    method @CallSuper public void onLaunchSingleTopWithTransition(androidx.navigation.NavBackStackEntry backStackEntry);
+    method public void pop(androidx.navigation.NavBackStackEntry popUpTo, boolean saveState);
+    method public void popWithTransition(androidx.navigation.NavBackStackEntry popUpTo, boolean saveState);
+    method @CallSuper public void prepareForTransition(androidx.navigation.NavBackStackEntry entry);
+    method public void push(androidx.navigation.NavBackStackEntry backStackEntry);
+    method public void pushWithTransition(androidx.navigation.NavBackStackEntry backStackEntry);
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> backStack;
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.Set<androidx.navigation.NavBackStackEntry>> transitionsInProgress;
+  }
+
+  @androidx.navigation.NavOptionsDsl public final class PopUpToBuilder {
+    ctor public PopUpToBuilder();
+    method public boolean getInclusive();
+    method public boolean getSaveState();
+    method public void setInclusive(boolean);
+    method public void setSaveState(boolean);
+    property public final boolean inclusive;
+    property public final boolean saveState;
+  }
+
+  public final class SavedStateHandleKt {
+    method public static inline <reified T> T toRoute(androidx.lifecycle.SavedStateHandle, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+  }
+
+}
+
diff --git a/navigation/navigation-common/api/res-2.8.0-beta04.txt b/navigation/navigation-common/api/res-2.8.0-beta04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-common/api/res-2.8.0-beta04.txt
diff --git a/navigation/navigation-common/api/res-2.8.0-beta05.txt b/navigation/navigation-common/api/res-2.8.0-beta05.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-common/api/res-2.8.0-beta05.txt
diff --git a/navigation/navigation-common/api/restricted_2.8.0-beta04.txt b/navigation/navigation-common/api/restricted_2.8.0-beta04.txt
new file mode 100644
index 0000000..bb6ad19
--- /dev/null
+++ b/navigation/navigation-common/api/restricted_2.8.0-beta04.txt
@@ -0,0 +1,594 @@
+// Signature format: 4.0
+package androidx.navigation {
+
+  public final class ActionOnlyNavDirections implements androidx.navigation.NavDirections {
+    ctor public ActionOnlyNavDirections(int actionId);
+    method public int component1();
+    method public androidx.navigation.ActionOnlyNavDirections copy(int actionId);
+    method public int getActionId();
+    method public android.os.Bundle getArguments();
+    property public int actionId;
+    property public android.os.Bundle arguments;
+  }
+
+  @androidx.navigation.NavOptionsDsl public final class AnimBuilder {
+    ctor public AnimBuilder();
+    method public int getEnter();
+    method public int getExit();
+    method public int getPopEnter();
+    method public int getPopExit();
+    method public void setEnter(int);
+    method public void setExit(int);
+    method public void setPopEnter(int);
+    method public void setPopExit(int);
+    property public final int enter;
+    property public final int exit;
+    property public final int popEnter;
+    property public final int popExit;
+  }
+
+  public abstract class CollectionNavType<T> extends androidx.navigation.NavType<T> {
+    ctor public CollectionNavType(boolean isNullableAllowed);
+    method public abstract T emptyCollection();
+    method public abstract java.util.List<java.lang.String> serializeAsValues(T value);
+  }
+
+  public interface FloatingWindow {
+  }
+
+  public final class NamedNavArgument {
+    method public operator String component1();
+    method public operator androidx.navigation.NavArgument component2();
+    method public androidx.navigation.NavArgument getArgument();
+    method public String getName();
+    property public final androidx.navigation.NavArgument argument;
+    property public final String name;
+  }
+
+  public final class NamedNavArgumentKt {
+    method public static androidx.navigation.NamedNavArgument navArgument(String name, kotlin.jvm.functions.Function1<? super androidx.navigation.NavArgumentBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavAction {
+    ctor public NavAction(@IdRes int destinationId);
+    ctor public NavAction(@IdRes int destinationId, optional androidx.navigation.NavOptions? navOptions);
+    ctor public NavAction(@IdRes int destinationId, optional androidx.navigation.NavOptions? navOptions, optional android.os.Bundle? defaultArguments);
+    method public android.os.Bundle? getDefaultArguments();
+    method public int getDestinationId();
+    method public androidx.navigation.NavOptions? getNavOptions();
+    method public void setDefaultArguments(android.os.Bundle?);
+    method public void setNavOptions(androidx.navigation.NavOptions?);
+    property public final android.os.Bundle? defaultArguments;
+    property public final int destinationId;
+    property public final androidx.navigation.NavOptions? navOptions;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class NavActionBuilder {
+    ctor public NavActionBuilder();
+    method public java.util.Map<java.lang.String,java.lang.Object?> getDefaultArguments();
+    method public int getDestinationId();
+    method public void navOptions(kotlin.jvm.functions.Function1<? super androidx.navigation.NavOptionsBuilder,kotlin.Unit> optionsBuilder);
+    method public void setDestinationId(int);
+    property public final java.util.Map<java.lang.String,java.lang.Object?> defaultArguments;
+    property public final int destinationId;
+  }
+
+  public interface NavArgs {
+  }
+
+  public final class NavArgsLazy<Args extends androidx.navigation.NavArgs> implements kotlin.Lazy<Args> {
+    ctor public NavArgsLazy(kotlin.reflect.KClass<Args> navArgsClass, kotlin.jvm.functions.Function0<android.os.Bundle> argumentProducer);
+    method public Args getValue();
+    method public boolean isInitialized();
+    property public Args value;
+  }
+
+  public final class NavArgument {
+    method public Object? getDefaultValue();
+    method public androidx.navigation.NavType<java.lang.Object?> getType();
+    method public boolean isDefaultValuePresent();
+    method public boolean isNullable();
+    property public final Object? defaultValue;
+    property public final boolean isDefaultValuePresent;
+    property public final boolean isNullable;
+    property public final androidx.navigation.NavType<java.lang.Object?> type;
+  }
+
+  public static final class NavArgument.Builder {
+    ctor public NavArgument.Builder();
+    method public androidx.navigation.NavArgument build();
+    method public androidx.navigation.NavArgument.Builder setDefaultValue(Object? defaultValue);
+    method public androidx.navigation.NavArgument.Builder setIsNullable(boolean isNullable);
+    method public <T> androidx.navigation.NavArgument.Builder setType(androidx.navigation.NavType<T> type);
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class NavArgumentBuilder {
+    ctor public NavArgumentBuilder();
+    method public androidx.navigation.NavArgument build();
+    method public Object? getDefaultValue();
+    method public boolean getNullable();
+    method public androidx.navigation.NavType<? extends java.lang.Object?> getType();
+    method public void setDefaultValue(Object?);
+    method public void setNullable(boolean);
+    method public void setType(androidx.navigation.NavType<? extends java.lang.Object?>);
+    property public final Object? defaultValue;
+    property public final boolean nullable;
+    property public final androidx.navigation.NavType<? extends java.lang.Object?> type;
+  }
+
+  public final class NavBackStackEntry implements androidx.lifecycle.HasDefaultViewModelProviderFactory androidx.lifecycle.LifecycleOwner androidx.savedstate.SavedStateRegistryOwner androidx.lifecycle.ViewModelStoreOwner {
+    method public android.os.Bundle? getArguments();
+    method public androidx.lifecycle.ViewModelProvider.Factory getDefaultViewModelProviderFactory();
+    method public androidx.navigation.NavDestination getDestination();
+    method public String getId();
+    method public androidx.lifecycle.Lifecycle getLifecycle();
+    method @MainThread public androidx.lifecycle.SavedStateHandle getSavedStateHandle();
+    method public androidx.savedstate.SavedStateRegistry getSavedStateRegistry();
+    method public androidx.lifecycle.ViewModelStore getViewModelStore();
+    property public final android.os.Bundle? arguments;
+    property public androidx.lifecycle.viewmodel.CreationExtras defaultViewModelCreationExtras;
+    property public androidx.lifecycle.ViewModelProvider.Factory defaultViewModelProviderFactory;
+    property public final androidx.navigation.NavDestination destination;
+    property public final String id;
+    property public androidx.lifecycle.Lifecycle lifecycle;
+    property @MainThread public final androidx.lifecycle.SavedStateHandle savedStateHandle;
+    property public androidx.savedstate.SavedStateRegistry savedStateRegistry;
+    property public androidx.lifecycle.ViewModelStore viewModelStore;
+    field public static final androidx.navigation.NavBackStackEntry.Companion Companion;
+  }
+
+  public static final class NavBackStackEntry.Companion {
+  }
+
+  public final class NavBackStackEntryKt {
+    method public static inline <reified T> T toRoute(androidx.navigation.NavBackStackEntry);
+  }
+
+  public final class NavDeepLink {
+    method public String? getAction();
+    method public String? getMimeType();
+    method public String? getUriPattern();
+    property public final String? action;
+    property public final String? mimeType;
+    property public final String? uriPattern;
+  }
+
+  public static final class NavDeepLink.Builder {
+    method public androidx.navigation.NavDeepLink build();
+    method public static androidx.navigation.NavDeepLink.Builder fromAction(String action);
+    method public static androidx.navigation.NavDeepLink.Builder fromMimeType(String mimeType);
+    method public static androidx.navigation.NavDeepLink.Builder fromUriPattern(String uriPattern);
+    method public androidx.navigation.NavDeepLink.Builder setAction(String action);
+    method public androidx.navigation.NavDeepLink.Builder setMimeType(String mimeType);
+    method public androidx.navigation.NavDeepLink.Builder setUriPattern(String uriPattern);
+    method public inline <reified T> androidx.navigation.NavDeepLink.Builder setUriPattern(String basePath, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+  }
+
+  @kotlin.DslMarker public @interface NavDeepLinkDsl {
+  }
+
+  @androidx.navigation.NavDeepLinkDsl public final class NavDeepLinkDslBuilder {
+    ctor public NavDeepLinkDslBuilder();
+    method public String? getAction();
+    method public String? getMimeType();
+    method public String? getUriPattern();
+    method public void setAction(String?);
+    method public void setMimeType(String?);
+    method public void setUriPattern(String?);
+    property public final String? action;
+    property public final String? mimeType;
+    property public final String? uriPattern;
+  }
+
+  public final class NavDeepLinkDslBuilderKt {
+    method public static inline <reified T> androidx.navigation.NavDeepLink navDeepLink(String basePath, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, optional kotlin.jvm.functions.Function1<? super androidx.navigation.NavDeepLinkDslBuilder,kotlin.Unit> deepLinkBuilder);
+    method public static androidx.navigation.NavDeepLink navDeepLink(kotlin.jvm.functions.Function1<? super androidx.navigation.NavDeepLinkDslBuilder,kotlin.Unit> deepLinkBuilder);
+  }
+
+  public class NavDeepLinkRequest {
+    method public String? getAction();
+    method public String? getMimeType();
+    method public android.net.Uri? getUri();
+    property public String? action;
+    property public String? mimeType;
+    property public android.net.Uri? uri;
+  }
+
+  public static final class NavDeepLinkRequest.Builder {
+    method public androidx.navigation.NavDeepLinkRequest build();
+    method public static androidx.navigation.NavDeepLinkRequest.Builder fromAction(String action);
+    method public static androidx.navigation.NavDeepLinkRequest.Builder fromMimeType(String mimeType);
+    method public static androidx.navigation.NavDeepLinkRequest.Builder fromUri(android.net.Uri uri);
+    method public androidx.navigation.NavDeepLinkRequest.Builder setAction(String action);
+    method public androidx.navigation.NavDeepLinkRequest.Builder setMimeType(String mimeType);
+    method public androidx.navigation.NavDeepLinkRequest.Builder setUri(android.net.Uri uri);
+    field public static final androidx.navigation.NavDeepLinkRequest.Builder.Companion Companion;
+  }
+
+  public static final class NavDeepLinkRequest.Builder.Companion {
+    method public androidx.navigation.NavDeepLinkRequest.Builder fromAction(String action);
+    method public androidx.navigation.NavDeepLinkRequest.Builder fromMimeType(String mimeType);
+    method public androidx.navigation.NavDeepLinkRequest.Builder fromUri(android.net.Uri uri);
+  }
+
+  public class NavDestination {
+    ctor public NavDestination(androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+    ctor public NavDestination(String navigatorName);
+    method public final void addArgument(String argumentName, androidx.navigation.NavArgument argument);
+    method public final void addDeepLink(androidx.navigation.NavDeepLink navDeepLink);
+    method public final void addDeepLink(String uriPattern);
+    method public final String? fillInLabel(android.content.Context context, android.os.Bundle? bundle);
+    method public final androidx.navigation.NavAction? getAction(@IdRes int id);
+    method public final java.util.Map<java.lang.String,androidx.navigation.NavArgument> getArguments();
+    method public static final kotlin.sequences.Sequence<androidx.navigation.NavDestination> getHierarchy(androidx.navigation.NavDestination);
+    method @IdRes public final int getId();
+    method public final CharSequence? getLabel();
+    method public final String getNavigatorName();
+    method public final androidx.navigation.NavGraph? getParent();
+    method public final String? getRoute();
+    method public boolean hasDeepLink(android.net.Uri deepLink);
+    method public boolean hasDeepLink(androidx.navigation.NavDeepLinkRequest deepLinkRequest);
+    method public static final <T> boolean hasRoute(androidx.navigation.NavDestination, kotlin.reflect.KClass<T> route);
+    method @CallSuper public void onInflate(android.content.Context context, android.util.AttributeSet attrs);
+    method protected static final <C> Class<? extends C?> parseClassFromName(android.content.Context context, String name, Class<? extends C?> expectedClassType);
+    method public final void putAction(@IdRes int actionId, androidx.navigation.NavAction action);
+    method public final void putAction(@IdRes int actionId, @IdRes int destId);
+    method public final void removeAction(@IdRes int actionId);
+    method public final void removeArgument(String argumentName);
+    method public final void setId(@IdRes int);
+    method public final void setLabel(CharSequence?);
+    method public final void setRoute(String?);
+    property public final java.util.Map<java.lang.String,androidx.navigation.NavArgument> arguments;
+    property @IdRes public final int id;
+    property public final CharSequence? label;
+    property public final String navigatorName;
+    property public final androidx.navigation.NavGraph? parent;
+    property public final String? route;
+    field public static final androidx.navigation.NavDestination.Companion Companion;
+  }
+
+  @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.ANNOTATION_CLASS, kotlin.annotation.AnnotationTarget.CLASS}) public static @interface NavDestination.ClassType {
+    method public abstract Class<? extends java.lang.Object?> value();
+    property public abstract Class<? extends java.lang.Object?> value;
+  }
+
+  public static final class NavDestination.Companion {
+    method public kotlin.sequences.Sequence<androidx.navigation.NavDestination> getHierarchy(androidx.navigation.NavDestination);
+    method public inline <reified T> boolean hasRoute(androidx.navigation.NavDestination);
+    method public <T> boolean hasRoute(androidx.navigation.NavDestination, kotlin.reflect.KClass<T> route);
+    method protected <C> Class<? extends C?> parseClassFromName(android.content.Context context, String name, Class<? extends C?> expectedClassType);
+  }
+
+  @androidx.navigation.NavDestinationDsl public class NavDestinationBuilder<D extends androidx.navigation.NavDestination> {
+    ctor @Deprecated public NavDestinationBuilder(androidx.navigation.Navigator<? extends D> navigator, @IdRes int id);
+    ctor public NavDestinationBuilder(androidx.navigation.Navigator<? extends D> navigator, String? route);
+    ctor public NavDestinationBuilder(androidx.navigation.Navigator<? extends D> navigator, kotlin.reflect.KClass<? extends java.lang.Object?>? route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method @Deprecated public final void action(int actionId, kotlin.jvm.functions.Function1<? super androidx.navigation.NavActionBuilder,kotlin.Unit> actionBuilder);
+    method public final void argument(String name, androidx.navigation.NavArgument argument);
+    method public final void argument(String name, kotlin.jvm.functions.Function1<? super androidx.navigation.NavArgumentBuilder,kotlin.Unit> argumentBuilder);
+    method public D build();
+    method public final void deepLink(androidx.navigation.NavDeepLink navDeepLink);
+    method public final void deepLink(String uriPattern);
+    method public inline <reified T> void deepLink(String basePath, kotlin.jvm.functions.Function1<? super androidx.navigation.NavDeepLinkDslBuilder,kotlin.Unit> navDeepLink);
+    method public final void deepLink(kotlin.jvm.functions.Function1<? super androidx.navigation.NavDeepLinkDslBuilder,kotlin.Unit> navDeepLink);
+    method public inline <reified T> void deepLinkSafeArgs(String basePath);
+    method public final int getId();
+    method public final CharSequence? getLabel();
+    method protected final androidx.navigation.Navigator<? extends D> getNavigator();
+    method public final String? getRoute();
+    method protected D instantiateDestination();
+    method public final void setLabel(CharSequence?);
+    property public final int id;
+    property public final CharSequence? label;
+    property protected final androidx.navigation.Navigator<? extends D> navigator;
+    property public final String? route;
+  }
+
+  @kotlin.DslMarker public @interface NavDestinationDsl {
+  }
+
+  public interface NavDirections {
+    method @IdRes public int getActionId();
+    method public android.os.Bundle getArguments();
+    property @IdRes public abstract int actionId;
+    property public abstract android.os.Bundle arguments;
+  }
+
+  public class NavGraph extends androidx.navigation.NavDestination implements java.lang.Iterable<androidx.navigation.NavDestination> kotlin.jvm.internal.markers.KMappedMarker {
+    ctor public NavGraph(androidx.navigation.Navigator<? extends androidx.navigation.NavGraph> navGraphNavigator);
+    method public final void addAll(androidx.navigation.NavGraph other);
+    method public final void addDestination(androidx.navigation.NavDestination node);
+    method public final void addDestinations(androidx.navigation.NavDestination... nodes);
+    method public final void addDestinations(java.util.Collection<? extends androidx.navigation.NavDestination?> nodes);
+    method public final void clear();
+    method public inline <reified T> androidx.navigation.NavDestination? findNode();
+    method public final androidx.navigation.NavDestination? findNode(@IdRes int resId);
+    method public final androidx.navigation.NavDestination? findNode(String? route);
+    method public final <T> androidx.navigation.NavDestination? findNode(T? route);
+    method public static final androidx.navigation.NavDestination findStartDestination(androidx.navigation.NavGraph);
+    method @Deprecated @IdRes public final int getStartDestination();
+    method @IdRes public final int getStartDestinationId();
+    method public final String? getStartDestinationRoute();
+    method public final java.util.Iterator<androidx.navigation.NavDestination> iterator();
+    method public final void remove(androidx.navigation.NavDestination node);
+    method public inline <reified T> void setStartDestination();
+    method public final void setStartDestination(int startDestId);
+    method public final void setStartDestination(String startDestRoute);
+    method public final <T> void setStartDestination(T startDestRoute);
+    property @IdRes public final int startDestinationId;
+    property public final String? startDestinationRoute;
+    field public static final androidx.navigation.NavGraph.Companion Companion;
+  }
+
+  public static final class NavGraph.Companion {
+    method public androidx.navigation.NavDestination findStartDestination(androidx.navigation.NavGraph);
+  }
+
+  @androidx.navigation.NavDestinationDsl public class NavGraphBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.NavGraph> {
+    ctor @Deprecated public NavGraphBuilder(androidx.navigation.NavigatorProvider provider, @IdRes int id, @IdRes int startDestination);
+    ctor public NavGraphBuilder(androidx.navigation.NavigatorProvider provider, Object startDestination, kotlin.reflect.KClass<? extends java.lang.Object?>? route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    ctor public NavGraphBuilder(androidx.navigation.NavigatorProvider provider, String startDestination, String? route);
+    ctor public NavGraphBuilder(androidx.navigation.NavigatorProvider provider, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, kotlin.reflect.KClass<? extends java.lang.Object?>? route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public final void addDestination(androidx.navigation.NavDestination destination);
+    method public androidx.navigation.NavGraph build();
+    method public final <D extends androidx.navigation.NavDestination> void destination(androidx.navigation.NavDestinationBuilder<? extends D> navDestination);
+    method public final androidx.navigation.NavigatorProvider getProvider();
+    method public final operator void unaryPlus(androidx.navigation.NavDestination);
+    property public final androidx.navigation.NavigatorProvider provider;
+  }
+
+  public final class NavGraphBuilderKt {
+    method @Deprecated public static inline void navigation(androidx.navigation.NavGraphBuilder, @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void navigation(androidx.navigation.NavGraphBuilder, Object startDestination, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline void navigation(androidx.navigation.NavGraphBuilder, String startDestination, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void navigation(androidx.navigation.NavGraphBuilder, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, Object startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavGraphKt {
+    method public static operator boolean contains(androidx.navigation.NavGraph, @IdRes int id);
+    method public static operator boolean contains(androidx.navigation.NavGraph, String route);
+    method public static inline operator <reified T> boolean contains(androidx.navigation.NavGraph, kotlin.reflect.KClass<T> route);
+    method public static operator <T> boolean contains(androidx.navigation.NavGraph, T route);
+    method public static inline operator androidx.navigation.NavDestination get(androidx.navigation.NavGraph, @IdRes int id);
+    method public static inline operator androidx.navigation.NavDestination get(androidx.navigation.NavGraph, String route);
+    method public static inline operator <reified T> androidx.navigation.NavDestination get(androidx.navigation.NavGraph, kotlin.reflect.KClass<T> route);
+    method public static inline operator <T> androidx.navigation.NavDestination get(androidx.navigation.NavGraph, T route);
+    method public static inline operator void minusAssign(androidx.navigation.NavGraph, androidx.navigation.NavDestination node);
+    method public static inline operator void plusAssign(androidx.navigation.NavGraph, androidx.navigation.NavDestination node);
+    method public static inline operator void plusAssign(androidx.navigation.NavGraph, androidx.navigation.NavGraph other);
+  }
+
+  @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 final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getBackStack();
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> backStack;
+  }
+
+  public final class NavOptions {
+    method @AnimRes @AnimatorRes public int getEnterAnim();
+    method @AnimRes @AnimatorRes public int getExitAnim();
+    method @AnimRes @AnimatorRes public int getPopEnterAnim();
+    method @AnimRes @AnimatorRes public int getPopExitAnim();
+    method @Deprecated @IdRes public int getPopUpTo();
+    method @IdRes public int getPopUpToId();
+    method public String? getPopUpToRoute();
+    method public kotlin.reflect.KClass<? extends java.lang.Object?>? getPopUpToRouteClass();
+    method public Object? getPopUpToRouteObject();
+    method public boolean isPopUpToInclusive();
+    method public boolean shouldLaunchSingleTop();
+    method public boolean shouldPopUpToSaveState();
+    method public boolean shouldRestoreState();
+    property @AnimRes @AnimatorRes public final int enterAnim;
+    property @AnimRes @AnimatorRes public final int exitAnim;
+    property @AnimRes @AnimatorRes public final int popEnterAnim;
+    property @AnimRes @AnimatorRes public final int popExitAnim;
+    property @IdRes public final int popUpToId;
+    property public final String? popUpToRoute;
+    property public final kotlin.reflect.KClass<? extends java.lang.Object?>? popUpToRouteClass;
+    property public final Object? popUpToRouteObject;
+  }
+
+  public static final class NavOptions.Builder {
+    ctor public NavOptions.Builder();
+    method public androidx.navigation.NavOptions build();
+    method public androidx.navigation.NavOptions.Builder setEnterAnim(@AnimRes @AnimatorRes int enterAnim);
+    method public androidx.navigation.NavOptions.Builder setExitAnim(@AnimRes @AnimatorRes int exitAnim);
+    method public androidx.navigation.NavOptions.Builder setLaunchSingleTop(boolean singleTop);
+    method public androidx.navigation.NavOptions.Builder setPopEnterAnim(@AnimRes @AnimatorRes int popEnterAnim);
+    method public androidx.navigation.NavOptions.Builder setPopExitAnim(@AnimRes @AnimatorRes int popExitAnim);
+    method public inline <reified T> androidx.navigation.NavOptions.Builder setPopUpTo(boolean inclusive, optional boolean saveState);
+    method public androidx.navigation.NavOptions.Builder setPopUpTo(@IdRes int destinationId, boolean inclusive);
+    method public androidx.navigation.NavOptions.Builder setPopUpTo(@IdRes int destinationId, boolean inclusive, optional boolean saveState);
+    method public androidx.navigation.NavOptions.Builder setPopUpTo(String? route, boolean inclusive);
+    method public androidx.navigation.NavOptions.Builder setPopUpTo(String? route, boolean inclusive, optional boolean saveState);
+    method public <T> androidx.navigation.NavOptions.Builder setPopUpTo(T route, boolean inclusive);
+    method public <T> androidx.navigation.NavOptions.Builder setPopUpTo(T route, boolean inclusive, optional boolean saveState);
+    method public androidx.navigation.NavOptions.Builder setRestoreState(boolean restoreState);
+  }
+
+  @androidx.navigation.NavOptionsDsl public final class NavOptionsBuilder {
+    ctor public NavOptionsBuilder();
+    method public void anim(kotlin.jvm.functions.Function1<? super androidx.navigation.AnimBuilder,kotlin.Unit> animBuilder);
+    method public boolean getLaunchSingleTop();
+    method @Deprecated public int getPopUpTo();
+    method public int getPopUpToId();
+    method public String? getPopUpToRoute();
+    method public kotlin.reflect.KClass<? extends java.lang.Object?>? getPopUpToRouteClass();
+    method public Object? getPopUpToRouteObject();
+    method public boolean getRestoreState();
+    method public void popUpTo(@IdRes int id, optional kotlin.jvm.functions.Function1<? super androidx.navigation.PopUpToBuilder,kotlin.Unit> popUpToBuilder);
+    method public void popUpTo(String route, optional kotlin.jvm.functions.Function1<? super androidx.navigation.PopUpToBuilder,kotlin.Unit> popUpToBuilder);
+    method public inline <reified T> void popUpTo(optional kotlin.jvm.functions.Function1<? super androidx.navigation.PopUpToBuilder,kotlin.Unit> popUpToBuilder);
+    method public <T> void popUpTo(T route, optional kotlin.jvm.functions.Function1<? super androidx.navigation.PopUpToBuilder,kotlin.Unit> popUpToBuilder);
+    method public void setLaunchSingleTop(boolean);
+    method @Deprecated public void setPopUpTo(int);
+    method public void setRestoreState(boolean);
+    property public final boolean launchSingleTop;
+    property @Deprecated public final int popUpTo;
+    property public final int popUpToId;
+    property public final String? popUpToRoute;
+    property public final kotlin.reflect.KClass<? extends java.lang.Object?>? popUpToRouteClass;
+    property public final Object? popUpToRouteObject;
+    property public final boolean restoreState;
+  }
+
+  public final class NavOptionsBuilderKt {
+    method public static androidx.navigation.NavOptions navOptions(kotlin.jvm.functions.Function1<? super androidx.navigation.NavOptionsBuilder,kotlin.Unit> optionsBuilder);
+  }
+
+  @kotlin.DslMarker public @interface NavOptionsDsl {
+  }
+
+  public abstract class NavType<T> {
+    ctor public NavType(boolean isNullableAllowed);
+    method public static androidx.navigation.NavType<? extends java.lang.Object?> fromArgType(String? type, String? packageName);
+    method public abstract operator T? get(android.os.Bundle bundle, String key);
+    method public String getName();
+    method public boolean isNullableAllowed();
+    method public abstract T parseValue(String value);
+    method public T parseValue(String value, T previousValue);
+    method public abstract void put(android.os.Bundle bundle, String key, T value);
+    method public String serializeAsValue(T value);
+    method public boolean valueEquals(T value, T other);
+    property public boolean isNullableAllowed;
+    property public String name;
+    field public static final androidx.navigation.NavType<boolean[]?> BoolArrayType;
+    field public static final androidx.navigation.NavType<java.util.List<java.lang.Boolean>?> BoolListType;
+    field public static final androidx.navigation.NavType<java.lang.Boolean> BoolType;
+    field public static final androidx.navigation.NavType.Companion Companion;
+    field public static final androidx.navigation.NavType<float[]?> FloatArrayType;
+    field public static final androidx.navigation.NavType<java.util.List<java.lang.Float>?> FloatListType;
+    field public static final androidx.navigation.NavType<java.lang.Float> FloatType;
+    field public static final androidx.navigation.NavType<int[]?> IntArrayType;
+    field public static final androidx.navigation.NavType<java.util.List<java.lang.Integer>?> IntListType;
+    field public static final androidx.navigation.NavType<java.lang.Integer> IntType;
+    field public static final androidx.navigation.NavType<long[]?> LongArrayType;
+    field public static final androidx.navigation.NavType<java.util.List<java.lang.Long>?> LongListType;
+    field public static final androidx.navigation.NavType<java.lang.Long> LongType;
+    field public static final androidx.navigation.NavType<java.lang.Integer> ReferenceType;
+    field public static final androidx.navigation.NavType<java.lang.String[]?> StringArrayType;
+    field public static final androidx.navigation.NavType<java.util.List<java.lang.String>?> StringListType;
+    field public static final androidx.navigation.NavType<java.lang.String?> StringType;
+  }
+
+  public static final class NavType.Companion {
+    method public androidx.navigation.NavType<? extends java.lang.Object?> fromArgType(String? type, String? packageName);
+  }
+
+  public static final class NavType.EnumType<D extends java.lang.Enum<?>> extends androidx.navigation.NavType.SerializableType<D> {
+    ctor public NavType.EnumType(Class<D> type);
+    property public String name;
+  }
+
+  public static final class NavType.ParcelableArrayType<D extends android.os.Parcelable> extends androidx.navigation.NavType<D[]?> {
+    ctor public NavType.ParcelableArrayType(Class<D> type);
+    method public D[]? get(android.os.Bundle bundle, String key);
+    method public D[] parseValue(String value);
+    method public void put(android.os.Bundle bundle, String key, D[]? value);
+    method public boolean valueEquals(D[]? value, D[]? other);
+    property public String name;
+  }
+
+  public static final class NavType.ParcelableType<D> extends androidx.navigation.NavType<D> {
+    ctor public NavType.ParcelableType(Class<D> type);
+    method public D? get(android.os.Bundle bundle, String key);
+    method public D parseValue(String value);
+    method public void put(android.os.Bundle bundle, String key, D value);
+    property public String name;
+  }
+
+  public static final class NavType.SerializableArrayType<D extends java.io.Serializable> extends androidx.navigation.NavType<D[]?> {
+    ctor public NavType.SerializableArrayType(Class<D> type);
+    method public D[]? get(android.os.Bundle bundle, String key);
+    method public D[] parseValue(String value);
+    method public void put(android.os.Bundle bundle, String key, D[]? value);
+    method public boolean valueEquals(D[]? value, D[]? other);
+    property public String name;
+  }
+
+  public static class NavType.SerializableType<D extends java.io.Serializable> extends androidx.navigation.NavType<D> {
+    ctor public NavType.SerializableType(Class<D> type);
+    method public D? get(android.os.Bundle bundle, String key);
+    method public D parseValue(String value);
+    method public void put(android.os.Bundle bundle, String key, D value);
+    property public String name;
+  }
+
+  public abstract class Navigator<D extends androidx.navigation.NavDestination> {
+    ctor public Navigator();
+    method public abstract D createDestination();
+    method protected final androidx.navigation.NavigatorState getState();
+    method public final boolean isAttached();
+    method public androidx.navigation.NavDestination? navigate(D destination, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method public void navigate(java.util.List<androidx.navigation.NavBackStackEntry> entries, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @CallSuper public void onAttach(androidx.navigation.NavigatorState state);
+    method public void onLaunchSingleTop(androidx.navigation.NavBackStackEntry backStackEntry);
+    method public void onRestoreState(android.os.Bundle savedState);
+    method public android.os.Bundle? onSaveState();
+    method public boolean popBackStack();
+    method public void popBackStack(androidx.navigation.NavBackStackEntry popUpTo, boolean savedState);
+    property public final boolean isAttached;
+    property protected final androidx.navigation.NavigatorState state;
+  }
+
+  public static interface Navigator.Extras {
+  }
+
+  @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.RUNTIME) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.ANNOTATION_CLASS, kotlin.annotation.AnnotationTarget.CLASS}) public static @interface Navigator.Name {
+    method public abstract String value();
+    property public abstract String value;
+  }
+
+  public class NavigatorProvider {
+    ctor public NavigatorProvider();
+    method public final androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>? addNavigator(androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+    method @CallSuper public androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>? addNavigator(String name, androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+    method public final <T extends androidx.navigation.Navigator<?>> T getNavigator(Class<T> navigatorClass);
+    method @CallSuper public <T extends androidx.navigation.Navigator<?>> T getNavigator(String name);
+  }
+
+  public final class NavigatorProviderKt {
+    method public static inline operator <T extends androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>> T get(androidx.navigation.NavigatorProvider, String name);
+    method public static inline operator <T extends androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>> T get(androidx.navigation.NavigatorProvider, kotlin.reflect.KClass<T> clazz);
+    method public static inline operator void plusAssign(androidx.navigation.NavigatorProvider, androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+    method public static inline operator androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>? set(androidx.navigation.NavigatorProvider, String name, androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+  }
+
+  public abstract class NavigatorState {
+    ctor public NavigatorState();
+    method public abstract androidx.navigation.NavBackStackEntry createBackStackEntry(androidx.navigation.NavDestination destination, android.os.Bundle? arguments);
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getBackStack();
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.Set<androidx.navigation.NavBackStackEntry>> getTransitionsInProgress();
+    method public void markTransitionComplete(androidx.navigation.NavBackStackEntry entry);
+    method @CallSuper public void onLaunchSingleTop(androidx.navigation.NavBackStackEntry backStackEntry);
+    method @CallSuper public void onLaunchSingleTopWithTransition(androidx.navigation.NavBackStackEntry backStackEntry);
+    method public void pop(androidx.navigation.NavBackStackEntry popUpTo, boolean saveState);
+    method public void popWithTransition(androidx.navigation.NavBackStackEntry popUpTo, boolean saveState);
+    method @CallSuper public void prepareForTransition(androidx.navigation.NavBackStackEntry entry);
+    method public void push(androidx.navigation.NavBackStackEntry backStackEntry);
+    method public void pushWithTransition(androidx.navigation.NavBackStackEntry backStackEntry);
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> backStack;
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.Set<androidx.navigation.NavBackStackEntry>> transitionsInProgress;
+  }
+
+  @androidx.navigation.NavOptionsDsl public final class PopUpToBuilder {
+    ctor public PopUpToBuilder();
+    method public boolean getInclusive();
+    method public boolean getSaveState();
+    method public void setInclusive(boolean);
+    method public void setSaveState(boolean);
+    property public final boolean inclusive;
+    property public final boolean saveState;
+  }
+
+  public final class SavedStateHandleKt {
+    method public static inline <reified T> T toRoute(androidx.lifecycle.SavedStateHandle, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+  }
+
+}
+
diff --git a/navigation/navigation-common/api/restricted_2.8.0-beta05.txt b/navigation/navigation-common/api/restricted_2.8.0-beta05.txt
new file mode 100644
index 0000000..bb6ad19
--- /dev/null
+++ b/navigation/navigation-common/api/restricted_2.8.0-beta05.txt
@@ -0,0 +1,594 @@
+// Signature format: 4.0
+package androidx.navigation {
+
+  public final class ActionOnlyNavDirections implements androidx.navigation.NavDirections {
+    ctor public ActionOnlyNavDirections(int actionId);
+    method public int component1();
+    method public androidx.navigation.ActionOnlyNavDirections copy(int actionId);
+    method public int getActionId();
+    method public android.os.Bundle getArguments();
+    property public int actionId;
+    property public android.os.Bundle arguments;
+  }
+
+  @androidx.navigation.NavOptionsDsl public final class AnimBuilder {
+    ctor public AnimBuilder();
+    method public int getEnter();
+    method public int getExit();
+    method public int getPopEnter();
+    method public int getPopExit();
+    method public void setEnter(int);
+    method public void setExit(int);
+    method public void setPopEnter(int);
+    method public void setPopExit(int);
+    property public final int enter;
+    property public final int exit;
+    property public final int popEnter;
+    property public final int popExit;
+  }
+
+  public abstract class CollectionNavType<T> extends androidx.navigation.NavType<T> {
+    ctor public CollectionNavType(boolean isNullableAllowed);
+    method public abstract T emptyCollection();
+    method public abstract java.util.List<java.lang.String> serializeAsValues(T value);
+  }
+
+  public interface FloatingWindow {
+  }
+
+  public final class NamedNavArgument {
+    method public operator String component1();
+    method public operator androidx.navigation.NavArgument component2();
+    method public androidx.navigation.NavArgument getArgument();
+    method public String getName();
+    property public final androidx.navigation.NavArgument argument;
+    property public final String name;
+  }
+
+  public final class NamedNavArgumentKt {
+    method public static androidx.navigation.NamedNavArgument navArgument(String name, kotlin.jvm.functions.Function1<? super androidx.navigation.NavArgumentBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavAction {
+    ctor public NavAction(@IdRes int destinationId);
+    ctor public NavAction(@IdRes int destinationId, optional androidx.navigation.NavOptions? navOptions);
+    ctor public NavAction(@IdRes int destinationId, optional androidx.navigation.NavOptions? navOptions, optional android.os.Bundle? defaultArguments);
+    method public android.os.Bundle? getDefaultArguments();
+    method public int getDestinationId();
+    method public androidx.navigation.NavOptions? getNavOptions();
+    method public void setDefaultArguments(android.os.Bundle?);
+    method public void setNavOptions(androidx.navigation.NavOptions?);
+    property public final android.os.Bundle? defaultArguments;
+    property public final int destinationId;
+    property public final androidx.navigation.NavOptions? navOptions;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class NavActionBuilder {
+    ctor public NavActionBuilder();
+    method public java.util.Map<java.lang.String,java.lang.Object?> getDefaultArguments();
+    method public int getDestinationId();
+    method public void navOptions(kotlin.jvm.functions.Function1<? super androidx.navigation.NavOptionsBuilder,kotlin.Unit> optionsBuilder);
+    method public void setDestinationId(int);
+    property public final java.util.Map<java.lang.String,java.lang.Object?> defaultArguments;
+    property public final int destinationId;
+  }
+
+  public interface NavArgs {
+  }
+
+  public final class NavArgsLazy<Args extends androidx.navigation.NavArgs> implements kotlin.Lazy<Args> {
+    ctor public NavArgsLazy(kotlin.reflect.KClass<Args> navArgsClass, kotlin.jvm.functions.Function0<android.os.Bundle> argumentProducer);
+    method public Args getValue();
+    method public boolean isInitialized();
+    property public Args value;
+  }
+
+  public final class NavArgument {
+    method public Object? getDefaultValue();
+    method public androidx.navigation.NavType<java.lang.Object?> getType();
+    method public boolean isDefaultValuePresent();
+    method public boolean isNullable();
+    property public final Object? defaultValue;
+    property public final boolean isDefaultValuePresent;
+    property public final boolean isNullable;
+    property public final androidx.navigation.NavType<java.lang.Object?> type;
+  }
+
+  public static final class NavArgument.Builder {
+    ctor public NavArgument.Builder();
+    method public androidx.navigation.NavArgument build();
+    method public androidx.navigation.NavArgument.Builder setDefaultValue(Object? defaultValue);
+    method public androidx.navigation.NavArgument.Builder setIsNullable(boolean isNullable);
+    method public <T> androidx.navigation.NavArgument.Builder setType(androidx.navigation.NavType<T> type);
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class NavArgumentBuilder {
+    ctor public NavArgumentBuilder();
+    method public androidx.navigation.NavArgument build();
+    method public Object? getDefaultValue();
+    method public boolean getNullable();
+    method public androidx.navigation.NavType<? extends java.lang.Object?> getType();
+    method public void setDefaultValue(Object?);
+    method public void setNullable(boolean);
+    method public void setType(androidx.navigation.NavType<? extends java.lang.Object?>);
+    property public final Object? defaultValue;
+    property public final boolean nullable;
+    property public final androidx.navigation.NavType<? extends java.lang.Object?> type;
+  }
+
+  public final class NavBackStackEntry implements androidx.lifecycle.HasDefaultViewModelProviderFactory androidx.lifecycle.LifecycleOwner androidx.savedstate.SavedStateRegistryOwner androidx.lifecycle.ViewModelStoreOwner {
+    method public android.os.Bundle? getArguments();
+    method public androidx.lifecycle.ViewModelProvider.Factory getDefaultViewModelProviderFactory();
+    method public androidx.navigation.NavDestination getDestination();
+    method public String getId();
+    method public androidx.lifecycle.Lifecycle getLifecycle();
+    method @MainThread public androidx.lifecycle.SavedStateHandle getSavedStateHandle();
+    method public androidx.savedstate.SavedStateRegistry getSavedStateRegistry();
+    method public androidx.lifecycle.ViewModelStore getViewModelStore();
+    property public final android.os.Bundle? arguments;
+    property public androidx.lifecycle.viewmodel.CreationExtras defaultViewModelCreationExtras;
+    property public androidx.lifecycle.ViewModelProvider.Factory defaultViewModelProviderFactory;
+    property public final androidx.navigation.NavDestination destination;
+    property public final String id;
+    property public androidx.lifecycle.Lifecycle lifecycle;
+    property @MainThread public final androidx.lifecycle.SavedStateHandle savedStateHandle;
+    property public androidx.savedstate.SavedStateRegistry savedStateRegistry;
+    property public androidx.lifecycle.ViewModelStore viewModelStore;
+    field public static final androidx.navigation.NavBackStackEntry.Companion Companion;
+  }
+
+  public static final class NavBackStackEntry.Companion {
+  }
+
+  public final class NavBackStackEntryKt {
+    method public static inline <reified T> T toRoute(androidx.navigation.NavBackStackEntry);
+  }
+
+  public final class NavDeepLink {
+    method public String? getAction();
+    method public String? getMimeType();
+    method public String? getUriPattern();
+    property public final String? action;
+    property public final String? mimeType;
+    property public final String? uriPattern;
+  }
+
+  public static final class NavDeepLink.Builder {
+    method public androidx.navigation.NavDeepLink build();
+    method public static androidx.navigation.NavDeepLink.Builder fromAction(String action);
+    method public static androidx.navigation.NavDeepLink.Builder fromMimeType(String mimeType);
+    method public static androidx.navigation.NavDeepLink.Builder fromUriPattern(String uriPattern);
+    method public androidx.navigation.NavDeepLink.Builder setAction(String action);
+    method public androidx.navigation.NavDeepLink.Builder setMimeType(String mimeType);
+    method public androidx.navigation.NavDeepLink.Builder setUriPattern(String uriPattern);
+    method public inline <reified T> androidx.navigation.NavDeepLink.Builder setUriPattern(String basePath, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+  }
+
+  @kotlin.DslMarker public @interface NavDeepLinkDsl {
+  }
+
+  @androidx.navigation.NavDeepLinkDsl public final class NavDeepLinkDslBuilder {
+    ctor public NavDeepLinkDslBuilder();
+    method public String? getAction();
+    method public String? getMimeType();
+    method public String? getUriPattern();
+    method public void setAction(String?);
+    method public void setMimeType(String?);
+    method public void setUriPattern(String?);
+    property public final String? action;
+    property public final String? mimeType;
+    property public final String? uriPattern;
+  }
+
+  public final class NavDeepLinkDslBuilderKt {
+    method public static inline <reified T> androidx.navigation.NavDeepLink navDeepLink(String basePath, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, optional kotlin.jvm.functions.Function1<? super androidx.navigation.NavDeepLinkDslBuilder,kotlin.Unit> deepLinkBuilder);
+    method public static androidx.navigation.NavDeepLink navDeepLink(kotlin.jvm.functions.Function1<? super androidx.navigation.NavDeepLinkDslBuilder,kotlin.Unit> deepLinkBuilder);
+  }
+
+  public class NavDeepLinkRequest {
+    method public String? getAction();
+    method public String? getMimeType();
+    method public android.net.Uri? getUri();
+    property public String? action;
+    property public String? mimeType;
+    property public android.net.Uri? uri;
+  }
+
+  public static final class NavDeepLinkRequest.Builder {
+    method public androidx.navigation.NavDeepLinkRequest build();
+    method public static androidx.navigation.NavDeepLinkRequest.Builder fromAction(String action);
+    method public static androidx.navigation.NavDeepLinkRequest.Builder fromMimeType(String mimeType);
+    method public static androidx.navigation.NavDeepLinkRequest.Builder fromUri(android.net.Uri uri);
+    method public androidx.navigation.NavDeepLinkRequest.Builder setAction(String action);
+    method public androidx.navigation.NavDeepLinkRequest.Builder setMimeType(String mimeType);
+    method public androidx.navigation.NavDeepLinkRequest.Builder setUri(android.net.Uri uri);
+    field public static final androidx.navigation.NavDeepLinkRequest.Builder.Companion Companion;
+  }
+
+  public static final class NavDeepLinkRequest.Builder.Companion {
+    method public androidx.navigation.NavDeepLinkRequest.Builder fromAction(String action);
+    method public androidx.navigation.NavDeepLinkRequest.Builder fromMimeType(String mimeType);
+    method public androidx.navigation.NavDeepLinkRequest.Builder fromUri(android.net.Uri uri);
+  }
+
+  public class NavDestination {
+    ctor public NavDestination(androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+    ctor public NavDestination(String navigatorName);
+    method public final void addArgument(String argumentName, androidx.navigation.NavArgument argument);
+    method public final void addDeepLink(androidx.navigation.NavDeepLink navDeepLink);
+    method public final void addDeepLink(String uriPattern);
+    method public final String? fillInLabel(android.content.Context context, android.os.Bundle? bundle);
+    method public final androidx.navigation.NavAction? getAction(@IdRes int id);
+    method public final java.util.Map<java.lang.String,androidx.navigation.NavArgument> getArguments();
+    method public static final kotlin.sequences.Sequence<androidx.navigation.NavDestination> getHierarchy(androidx.navigation.NavDestination);
+    method @IdRes public final int getId();
+    method public final CharSequence? getLabel();
+    method public final String getNavigatorName();
+    method public final androidx.navigation.NavGraph? getParent();
+    method public final String? getRoute();
+    method public boolean hasDeepLink(android.net.Uri deepLink);
+    method public boolean hasDeepLink(androidx.navigation.NavDeepLinkRequest deepLinkRequest);
+    method public static final <T> boolean hasRoute(androidx.navigation.NavDestination, kotlin.reflect.KClass<T> route);
+    method @CallSuper public void onInflate(android.content.Context context, android.util.AttributeSet attrs);
+    method protected static final <C> Class<? extends C?> parseClassFromName(android.content.Context context, String name, Class<? extends C?> expectedClassType);
+    method public final void putAction(@IdRes int actionId, androidx.navigation.NavAction action);
+    method public final void putAction(@IdRes int actionId, @IdRes int destId);
+    method public final void removeAction(@IdRes int actionId);
+    method public final void removeArgument(String argumentName);
+    method public final void setId(@IdRes int);
+    method public final void setLabel(CharSequence?);
+    method public final void setRoute(String?);
+    property public final java.util.Map<java.lang.String,androidx.navigation.NavArgument> arguments;
+    property @IdRes public final int id;
+    property public final CharSequence? label;
+    property public final String navigatorName;
+    property public final androidx.navigation.NavGraph? parent;
+    property public final String? route;
+    field public static final androidx.navigation.NavDestination.Companion Companion;
+  }
+
+  @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.ANNOTATION_CLASS, kotlin.annotation.AnnotationTarget.CLASS}) public static @interface NavDestination.ClassType {
+    method public abstract Class<? extends java.lang.Object?> value();
+    property public abstract Class<? extends java.lang.Object?> value;
+  }
+
+  public static final class NavDestination.Companion {
+    method public kotlin.sequences.Sequence<androidx.navigation.NavDestination> getHierarchy(androidx.navigation.NavDestination);
+    method public inline <reified T> boolean hasRoute(androidx.navigation.NavDestination);
+    method public <T> boolean hasRoute(androidx.navigation.NavDestination, kotlin.reflect.KClass<T> route);
+    method protected <C> Class<? extends C?> parseClassFromName(android.content.Context context, String name, Class<? extends C?> expectedClassType);
+  }
+
+  @androidx.navigation.NavDestinationDsl public class NavDestinationBuilder<D extends androidx.navigation.NavDestination> {
+    ctor @Deprecated public NavDestinationBuilder(androidx.navigation.Navigator<? extends D> navigator, @IdRes int id);
+    ctor public NavDestinationBuilder(androidx.navigation.Navigator<? extends D> navigator, String? route);
+    ctor public NavDestinationBuilder(androidx.navigation.Navigator<? extends D> navigator, kotlin.reflect.KClass<? extends java.lang.Object?>? route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method @Deprecated public final void action(int actionId, kotlin.jvm.functions.Function1<? super androidx.navigation.NavActionBuilder,kotlin.Unit> actionBuilder);
+    method public final void argument(String name, androidx.navigation.NavArgument argument);
+    method public final void argument(String name, kotlin.jvm.functions.Function1<? super androidx.navigation.NavArgumentBuilder,kotlin.Unit> argumentBuilder);
+    method public D build();
+    method public final void deepLink(androidx.navigation.NavDeepLink navDeepLink);
+    method public final void deepLink(String uriPattern);
+    method public inline <reified T> void deepLink(String basePath, kotlin.jvm.functions.Function1<? super androidx.navigation.NavDeepLinkDslBuilder,kotlin.Unit> navDeepLink);
+    method public final void deepLink(kotlin.jvm.functions.Function1<? super androidx.navigation.NavDeepLinkDslBuilder,kotlin.Unit> navDeepLink);
+    method public inline <reified T> void deepLinkSafeArgs(String basePath);
+    method public final int getId();
+    method public final CharSequence? getLabel();
+    method protected final androidx.navigation.Navigator<? extends D> getNavigator();
+    method public final String? getRoute();
+    method protected D instantiateDestination();
+    method public final void setLabel(CharSequence?);
+    property public final int id;
+    property public final CharSequence? label;
+    property protected final androidx.navigation.Navigator<? extends D> navigator;
+    property public final String? route;
+  }
+
+  @kotlin.DslMarker public @interface NavDestinationDsl {
+  }
+
+  public interface NavDirections {
+    method @IdRes public int getActionId();
+    method public android.os.Bundle getArguments();
+    property @IdRes public abstract int actionId;
+    property public abstract android.os.Bundle arguments;
+  }
+
+  public class NavGraph extends androidx.navigation.NavDestination implements java.lang.Iterable<androidx.navigation.NavDestination> kotlin.jvm.internal.markers.KMappedMarker {
+    ctor public NavGraph(androidx.navigation.Navigator<? extends androidx.navigation.NavGraph> navGraphNavigator);
+    method public final void addAll(androidx.navigation.NavGraph other);
+    method public final void addDestination(androidx.navigation.NavDestination node);
+    method public final void addDestinations(androidx.navigation.NavDestination... nodes);
+    method public final void addDestinations(java.util.Collection<? extends androidx.navigation.NavDestination?> nodes);
+    method public final void clear();
+    method public inline <reified T> androidx.navigation.NavDestination? findNode();
+    method public final androidx.navigation.NavDestination? findNode(@IdRes int resId);
+    method public final androidx.navigation.NavDestination? findNode(String? route);
+    method public final <T> androidx.navigation.NavDestination? findNode(T? route);
+    method public static final androidx.navigation.NavDestination findStartDestination(androidx.navigation.NavGraph);
+    method @Deprecated @IdRes public final int getStartDestination();
+    method @IdRes public final int getStartDestinationId();
+    method public final String? getStartDestinationRoute();
+    method public final java.util.Iterator<androidx.navigation.NavDestination> iterator();
+    method public final void remove(androidx.navigation.NavDestination node);
+    method public inline <reified T> void setStartDestination();
+    method public final void setStartDestination(int startDestId);
+    method public final void setStartDestination(String startDestRoute);
+    method public final <T> void setStartDestination(T startDestRoute);
+    property @IdRes public final int startDestinationId;
+    property public final String? startDestinationRoute;
+    field public static final androidx.navigation.NavGraph.Companion Companion;
+  }
+
+  public static final class NavGraph.Companion {
+    method public androidx.navigation.NavDestination findStartDestination(androidx.navigation.NavGraph);
+  }
+
+  @androidx.navigation.NavDestinationDsl public class NavGraphBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.NavGraph> {
+    ctor @Deprecated public NavGraphBuilder(androidx.navigation.NavigatorProvider provider, @IdRes int id, @IdRes int startDestination);
+    ctor public NavGraphBuilder(androidx.navigation.NavigatorProvider provider, Object startDestination, kotlin.reflect.KClass<? extends java.lang.Object?>? route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    ctor public NavGraphBuilder(androidx.navigation.NavigatorProvider provider, String startDestination, String? route);
+    ctor public NavGraphBuilder(androidx.navigation.NavigatorProvider provider, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, kotlin.reflect.KClass<? extends java.lang.Object?>? route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public final void addDestination(androidx.navigation.NavDestination destination);
+    method public androidx.navigation.NavGraph build();
+    method public final <D extends androidx.navigation.NavDestination> void destination(androidx.navigation.NavDestinationBuilder<? extends D> navDestination);
+    method public final androidx.navigation.NavigatorProvider getProvider();
+    method public final operator void unaryPlus(androidx.navigation.NavDestination);
+    property public final androidx.navigation.NavigatorProvider provider;
+  }
+
+  public final class NavGraphBuilderKt {
+    method @Deprecated public static inline void navigation(androidx.navigation.NavGraphBuilder, @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void navigation(androidx.navigation.NavGraphBuilder, Object startDestination, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline void navigation(androidx.navigation.NavGraphBuilder, String startDestination, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void navigation(androidx.navigation.NavGraphBuilder, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, Object startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavGraphKt {
+    method public static operator boolean contains(androidx.navigation.NavGraph, @IdRes int id);
+    method public static operator boolean contains(androidx.navigation.NavGraph, String route);
+    method public static inline operator <reified T> boolean contains(androidx.navigation.NavGraph, kotlin.reflect.KClass<T> route);
+    method public static operator <T> boolean contains(androidx.navigation.NavGraph, T route);
+    method public static inline operator androidx.navigation.NavDestination get(androidx.navigation.NavGraph, @IdRes int id);
+    method public static inline operator androidx.navigation.NavDestination get(androidx.navigation.NavGraph, String route);
+    method public static inline operator <reified T> androidx.navigation.NavDestination get(androidx.navigation.NavGraph, kotlin.reflect.KClass<T> route);
+    method public static inline operator <T> androidx.navigation.NavDestination get(androidx.navigation.NavGraph, T route);
+    method public static inline operator void minusAssign(androidx.navigation.NavGraph, androidx.navigation.NavDestination node);
+    method public static inline operator void plusAssign(androidx.navigation.NavGraph, androidx.navigation.NavDestination node);
+    method public static inline operator void plusAssign(androidx.navigation.NavGraph, androidx.navigation.NavGraph other);
+  }
+
+  @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 final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getBackStack();
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> backStack;
+  }
+
+  public final class NavOptions {
+    method @AnimRes @AnimatorRes public int getEnterAnim();
+    method @AnimRes @AnimatorRes public int getExitAnim();
+    method @AnimRes @AnimatorRes public int getPopEnterAnim();
+    method @AnimRes @AnimatorRes public int getPopExitAnim();
+    method @Deprecated @IdRes public int getPopUpTo();
+    method @IdRes public int getPopUpToId();
+    method public String? getPopUpToRoute();
+    method public kotlin.reflect.KClass<? extends java.lang.Object?>? getPopUpToRouteClass();
+    method public Object? getPopUpToRouteObject();
+    method public boolean isPopUpToInclusive();
+    method public boolean shouldLaunchSingleTop();
+    method public boolean shouldPopUpToSaveState();
+    method public boolean shouldRestoreState();
+    property @AnimRes @AnimatorRes public final int enterAnim;
+    property @AnimRes @AnimatorRes public final int exitAnim;
+    property @AnimRes @AnimatorRes public final int popEnterAnim;
+    property @AnimRes @AnimatorRes public final int popExitAnim;
+    property @IdRes public final int popUpToId;
+    property public final String? popUpToRoute;
+    property public final kotlin.reflect.KClass<? extends java.lang.Object?>? popUpToRouteClass;
+    property public final Object? popUpToRouteObject;
+  }
+
+  public static final class NavOptions.Builder {
+    ctor public NavOptions.Builder();
+    method public androidx.navigation.NavOptions build();
+    method public androidx.navigation.NavOptions.Builder setEnterAnim(@AnimRes @AnimatorRes int enterAnim);
+    method public androidx.navigation.NavOptions.Builder setExitAnim(@AnimRes @AnimatorRes int exitAnim);
+    method public androidx.navigation.NavOptions.Builder setLaunchSingleTop(boolean singleTop);
+    method public androidx.navigation.NavOptions.Builder setPopEnterAnim(@AnimRes @AnimatorRes int popEnterAnim);
+    method public androidx.navigation.NavOptions.Builder setPopExitAnim(@AnimRes @AnimatorRes int popExitAnim);
+    method public inline <reified T> androidx.navigation.NavOptions.Builder setPopUpTo(boolean inclusive, optional boolean saveState);
+    method public androidx.navigation.NavOptions.Builder setPopUpTo(@IdRes int destinationId, boolean inclusive);
+    method public androidx.navigation.NavOptions.Builder setPopUpTo(@IdRes int destinationId, boolean inclusive, optional boolean saveState);
+    method public androidx.navigation.NavOptions.Builder setPopUpTo(String? route, boolean inclusive);
+    method public androidx.navigation.NavOptions.Builder setPopUpTo(String? route, boolean inclusive, optional boolean saveState);
+    method public <T> androidx.navigation.NavOptions.Builder setPopUpTo(T route, boolean inclusive);
+    method public <T> androidx.navigation.NavOptions.Builder setPopUpTo(T route, boolean inclusive, optional boolean saveState);
+    method public androidx.navigation.NavOptions.Builder setRestoreState(boolean restoreState);
+  }
+
+  @androidx.navigation.NavOptionsDsl public final class NavOptionsBuilder {
+    ctor public NavOptionsBuilder();
+    method public void anim(kotlin.jvm.functions.Function1<? super androidx.navigation.AnimBuilder,kotlin.Unit> animBuilder);
+    method public boolean getLaunchSingleTop();
+    method @Deprecated public int getPopUpTo();
+    method public int getPopUpToId();
+    method public String? getPopUpToRoute();
+    method public kotlin.reflect.KClass<? extends java.lang.Object?>? getPopUpToRouteClass();
+    method public Object? getPopUpToRouteObject();
+    method public boolean getRestoreState();
+    method public void popUpTo(@IdRes int id, optional kotlin.jvm.functions.Function1<? super androidx.navigation.PopUpToBuilder,kotlin.Unit> popUpToBuilder);
+    method public void popUpTo(String route, optional kotlin.jvm.functions.Function1<? super androidx.navigation.PopUpToBuilder,kotlin.Unit> popUpToBuilder);
+    method public inline <reified T> void popUpTo(optional kotlin.jvm.functions.Function1<? super androidx.navigation.PopUpToBuilder,kotlin.Unit> popUpToBuilder);
+    method public <T> void popUpTo(T route, optional kotlin.jvm.functions.Function1<? super androidx.navigation.PopUpToBuilder,kotlin.Unit> popUpToBuilder);
+    method public void setLaunchSingleTop(boolean);
+    method @Deprecated public void setPopUpTo(int);
+    method public void setRestoreState(boolean);
+    property public final boolean launchSingleTop;
+    property @Deprecated public final int popUpTo;
+    property public final int popUpToId;
+    property public final String? popUpToRoute;
+    property public final kotlin.reflect.KClass<? extends java.lang.Object?>? popUpToRouteClass;
+    property public final Object? popUpToRouteObject;
+    property public final boolean restoreState;
+  }
+
+  public final class NavOptionsBuilderKt {
+    method public static androidx.navigation.NavOptions navOptions(kotlin.jvm.functions.Function1<? super androidx.navigation.NavOptionsBuilder,kotlin.Unit> optionsBuilder);
+  }
+
+  @kotlin.DslMarker public @interface NavOptionsDsl {
+  }
+
+  public abstract class NavType<T> {
+    ctor public NavType(boolean isNullableAllowed);
+    method public static androidx.navigation.NavType<? extends java.lang.Object?> fromArgType(String? type, String? packageName);
+    method public abstract operator T? get(android.os.Bundle bundle, String key);
+    method public String getName();
+    method public boolean isNullableAllowed();
+    method public abstract T parseValue(String value);
+    method public T parseValue(String value, T previousValue);
+    method public abstract void put(android.os.Bundle bundle, String key, T value);
+    method public String serializeAsValue(T value);
+    method public boolean valueEquals(T value, T other);
+    property public boolean isNullableAllowed;
+    property public String name;
+    field public static final androidx.navigation.NavType<boolean[]?> BoolArrayType;
+    field public static final androidx.navigation.NavType<java.util.List<java.lang.Boolean>?> BoolListType;
+    field public static final androidx.navigation.NavType<java.lang.Boolean> BoolType;
+    field public static final androidx.navigation.NavType.Companion Companion;
+    field public static final androidx.navigation.NavType<float[]?> FloatArrayType;
+    field public static final androidx.navigation.NavType<java.util.List<java.lang.Float>?> FloatListType;
+    field public static final androidx.navigation.NavType<java.lang.Float> FloatType;
+    field public static final androidx.navigation.NavType<int[]?> IntArrayType;
+    field public static final androidx.navigation.NavType<java.util.List<java.lang.Integer>?> IntListType;
+    field public static final androidx.navigation.NavType<java.lang.Integer> IntType;
+    field public static final androidx.navigation.NavType<long[]?> LongArrayType;
+    field public static final androidx.navigation.NavType<java.util.List<java.lang.Long>?> LongListType;
+    field public static final androidx.navigation.NavType<java.lang.Long> LongType;
+    field public static final androidx.navigation.NavType<java.lang.Integer> ReferenceType;
+    field public static final androidx.navigation.NavType<java.lang.String[]?> StringArrayType;
+    field public static final androidx.navigation.NavType<java.util.List<java.lang.String>?> StringListType;
+    field public static final androidx.navigation.NavType<java.lang.String?> StringType;
+  }
+
+  public static final class NavType.Companion {
+    method public androidx.navigation.NavType<? extends java.lang.Object?> fromArgType(String? type, String? packageName);
+  }
+
+  public static final class NavType.EnumType<D extends java.lang.Enum<?>> extends androidx.navigation.NavType.SerializableType<D> {
+    ctor public NavType.EnumType(Class<D> type);
+    property public String name;
+  }
+
+  public static final class NavType.ParcelableArrayType<D extends android.os.Parcelable> extends androidx.navigation.NavType<D[]?> {
+    ctor public NavType.ParcelableArrayType(Class<D> type);
+    method public D[]? get(android.os.Bundle bundle, String key);
+    method public D[] parseValue(String value);
+    method public void put(android.os.Bundle bundle, String key, D[]? value);
+    method public boolean valueEquals(D[]? value, D[]? other);
+    property public String name;
+  }
+
+  public static final class NavType.ParcelableType<D> extends androidx.navigation.NavType<D> {
+    ctor public NavType.ParcelableType(Class<D> type);
+    method public D? get(android.os.Bundle bundle, String key);
+    method public D parseValue(String value);
+    method public void put(android.os.Bundle bundle, String key, D value);
+    property public String name;
+  }
+
+  public static final class NavType.SerializableArrayType<D extends java.io.Serializable> extends androidx.navigation.NavType<D[]?> {
+    ctor public NavType.SerializableArrayType(Class<D> type);
+    method public D[]? get(android.os.Bundle bundle, String key);
+    method public D[] parseValue(String value);
+    method public void put(android.os.Bundle bundle, String key, D[]? value);
+    method public boolean valueEquals(D[]? value, D[]? other);
+    property public String name;
+  }
+
+  public static class NavType.SerializableType<D extends java.io.Serializable> extends androidx.navigation.NavType<D> {
+    ctor public NavType.SerializableType(Class<D> type);
+    method public D? get(android.os.Bundle bundle, String key);
+    method public D parseValue(String value);
+    method public void put(android.os.Bundle bundle, String key, D value);
+    property public String name;
+  }
+
+  public abstract class Navigator<D extends androidx.navigation.NavDestination> {
+    ctor public Navigator();
+    method public abstract D createDestination();
+    method protected final androidx.navigation.NavigatorState getState();
+    method public final boolean isAttached();
+    method public androidx.navigation.NavDestination? navigate(D destination, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method public void navigate(java.util.List<androidx.navigation.NavBackStackEntry> entries, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @CallSuper public void onAttach(androidx.navigation.NavigatorState state);
+    method public void onLaunchSingleTop(androidx.navigation.NavBackStackEntry backStackEntry);
+    method public void onRestoreState(android.os.Bundle savedState);
+    method public android.os.Bundle? onSaveState();
+    method public boolean popBackStack();
+    method public void popBackStack(androidx.navigation.NavBackStackEntry popUpTo, boolean savedState);
+    property public final boolean isAttached;
+    property protected final androidx.navigation.NavigatorState state;
+  }
+
+  public static interface Navigator.Extras {
+  }
+
+  @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.RUNTIME) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.ANNOTATION_CLASS, kotlin.annotation.AnnotationTarget.CLASS}) public static @interface Navigator.Name {
+    method public abstract String value();
+    property public abstract String value;
+  }
+
+  public class NavigatorProvider {
+    ctor public NavigatorProvider();
+    method public final androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>? addNavigator(androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+    method @CallSuper public androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>? addNavigator(String name, androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+    method public final <T extends androidx.navigation.Navigator<?>> T getNavigator(Class<T> navigatorClass);
+    method @CallSuper public <T extends androidx.navigation.Navigator<?>> T getNavigator(String name);
+  }
+
+  public final class NavigatorProviderKt {
+    method public static inline operator <T extends androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>> T get(androidx.navigation.NavigatorProvider, String name);
+    method public static inline operator <T extends androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>> T get(androidx.navigation.NavigatorProvider, kotlin.reflect.KClass<T> clazz);
+    method public static inline operator void plusAssign(androidx.navigation.NavigatorProvider, androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+    method public static inline operator androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>? set(androidx.navigation.NavigatorProvider, String name, androidx.navigation.Navigator<? extends androidx.navigation.NavDestination> navigator);
+  }
+
+  public abstract class NavigatorState {
+    ctor public NavigatorState();
+    method public abstract androidx.navigation.NavBackStackEntry createBackStackEntry(androidx.navigation.NavDestination destination, android.os.Bundle? arguments);
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getBackStack();
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.Set<androidx.navigation.NavBackStackEntry>> getTransitionsInProgress();
+    method public void markTransitionComplete(androidx.navigation.NavBackStackEntry entry);
+    method @CallSuper public void onLaunchSingleTop(androidx.navigation.NavBackStackEntry backStackEntry);
+    method @CallSuper public void onLaunchSingleTopWithTransition(androidx.navigation.NavBackStackEntry backStackEntry);
+    method public void pop(androidx.navigation.NavBackStackEntry popUpTo, boolean saveState);
+    method public void popWithTransition(androidx.navigation.NavBackStackEntry popUpTo, boolean saveState);
+    method @CallSuper public void prepareForTransition(androidx.navigation.NavBackStackEntry entry);
+    method public void push(androidx.navigation.NavBackStackEntry backStackEntry);
+    method public void pushWithTransition(androidx.navigation.NavBackStackEntry backStackEntry);
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> backStack;
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.Set<androidx.navigation.NavBackStackEntry>> transitionsInProgress;
+  }
+
+  @androidx.navigation.NavOptionsDsl public final class PopUpToBuilder {
+    ctor public PopUpToBuilder();
+    method public boolean getInclusive();
+    method public boolean getSaveState();
+    method public void setInclusive(boolean);
+    method public void setSaveState(boolean);
+    property public final boolean inclusive;
+    property public final boolean saveState;
+  }
+
+  public final class SavedStateHandleKt {
+    method public static inline <reified T> T toRoute(androidx.lifecycle.SavedStateHandle, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+  }
+
+}
+
diff --git a/navigation/navigation-common/src/main/java/androidx/navigation/NavGraph.kt b/navigation/navigation-common/src/main/java/androidx/navigation/NavGraph.kt
index efc157f..4e19649 100644
--- a/navigation/navigation-common/src/main/java/androidx/navigation/NavGraph.kt
+++ b/navigation/navigation-common/src/main/java/androidx/navigation/NavGraph.kt
@@ -493,15 +493,17 @@
          * @return the actual startDestination of the given graph.
          */
         @JvmStatic
-        public fun NavGraph.findStartDestination(): NavDestination =
-            generateSequence(findNode(startDestinationId)) {
-                    if (it is NavGraph) {
-                        it.findNode(it.startDestinationId)
-                    } else {
-                        null
-                    }
+        public fun NavGraph.findStartDestination(): NavDestination = childHierarchy().last()
+
+        @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+        public fun NavGraph.childHierarchy(): Sequence<NavDestination> =
+            generateSequence(this as NavDestination) {
+                if (it is NavGraph) {
+                    it.findNode(it.startDestinationId)
+                } else {
+                    null
                 }
-                .last()
+            }
     }
 }
 
diff --git a/navigation/navigation-compose/api/2.8.0-beta04.txt b/navigation/navigation-compose/api/2.8.0-beta04.txt
new file mode 100644
index 0000000..f4411f7
--- /dev/null
+++ b/navigation/navigation-compose/api/2.8.0-beta04.txt
@@ -0,0 +1,94 @@
+// Signature format: 4.0
+package androidx.navigation.compose {
+
+  @androidx.navigation.Navigator.Name("composable") public final class ComposeNavigator extends androidx.navigation.Navigator<androidx.navigation.compose.ComposeNavigator.Destination> {
+    ctor public ComposeNavigator();
+    method public androidx.navigation.compose.ComposeNavigator.Destination createDestination();
+    method public kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getBackStack();
+    method public void onTransitionComplete(androidx.navigation.NavBackStackEntry entry);
+    method public void prepareForTransition(androidx.navigation.NavBackStackEntry entry);
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> backStack;
+  }
+
+  @androidx.navigation.NavDestination.ClassType(Composable::class) public static final class ComposeNavigator.Destination extends androidx.navigation.NavDestination {
+    ctor @Deprecated public ComposeNavigator.Destination(androidx.navigation.compose.ComposeNavigator navigator, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    ctor public ComposeNavigator.Destination(androidx.navigation.compose.ComposeNavigator navigator, kotlin.jvm.functions.Function2<? super androidx.compose.animation.AnimatedContentScope,androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class ComposeNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.compose.ComposeNavigator.Destination> {
+    ctor public ComposeNavigatorDestinationBuilder(androidx.navigation.compose.ComposeNavigator navigator, String route, kotlin.jvm.functions.Function2<? super androidx.compose.animation.AnimatedContentScope,? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    ctor public ComposeNavigatorDestinationBuilder(androidx.navigation.compose.ComposeNavigator navigator, kotlin.reflect.KClass<? extends java.lang.Object?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function2<? super androidx.compose.animation.AnimatedContentScope,? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public androidx.navigation.compose.ComposeNavigator.Destination build();
+    method public kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? getEnterTransition();
+    method public kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? getExitTransition();
+    method public kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? getPopEnterTransition();
+    method public kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? getPopExitTransition();
+    method public kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? getSizeTransform();
+    method protected androidx.navigation.compose.ComposeNavigator.Destination instantiateDestination();
+    method public void setEnterTransition(kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>?);
+    method public void setExitTransition(kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>?);
+    method public void setPopEnterTransition(kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>?);
+    method public void setPopExitTransition(kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>?);
+    method public void setSizeTransform(kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>?);
+    property public final kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? enterTransition;
+    property public final kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? exitTransition;
+    property public final kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? popEnterTransition;
+    property public final kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? popExitTransition;
+    property public final kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform;
+  }
+
+  public final class DialogHostKt {
+    method @androidx.compose.runtime.Composable public static void DialogHost(androidx.navigation.compose.DialogNavigator dialogNavigator);
+  }
+
+  @androidx.navigation.Navigator.Name("dialog") public final class DialogNavigator extends androidx.navigation.Navigator<androidx.navigation.compose.DialogNavigator.Destination> {
+    ctor public DialogNavigator();
+    method public androidx.navigation.compose.DialogNavigator.Destination createDestination();
+  }
+
+  @androidx.navigation.NavDestination.ClassType(Composable::class) public static final class DialogNavigator.Destination extends androidx.navigation.NavDestination implements androidx.navigation.FloatingWindow {
+    ctor public DialogNavigator.Destination(androidx.navigation.compose.DialogNavigator navigator, optional androidx.compose.ui.window.DialogProperties dialogProperties, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DialogNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.compose.DialogNavigator.Destination> {
+    ctor public DialogNavigatorDestinationBuilder(androidx.navigation.compose.DialogNavigator navigator, String route, androidx.compose.ui.window.DialogProperties dialogProperties, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    ctor public DialogNavigatorDestinationBuilder(androidx.navigation.compose.DialogNavigator navigator, kotlin.reflect.KClass<? extends java.lang.Object?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, androidx.compose.ui.window.DialogProperties dialogProperties, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method protected androidx.navigation.compose.DialogNavigator.Destination instantiateDestination();
+  }
+
+  public final class NavBackStackEntryProviderKt {
+    method @androidx.compose.runtime.Composable public static void LocalOwnersProvider(androidx.navigation.NavBackStackEntry, androidx.compose.runtime.saveable.SaveableStateHolder saveableStateHolder, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+  }
+
+  public final class NavGraphBuilderKt {
+    method @Deprecated public static void composable(androidx.navigation.NavGraphBuilder, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public static void composable(androidx.navigation.NavGraphBuilder, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? enterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? exitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? popEnterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? popExitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function2<? super androidx.compose.animation.AnimatedContentScope,? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method @Deprecated public static void composable(androidx.navigation.NavGraphBuilder, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? enterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? exitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? popEnterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? popExitTransition, kotlin.jvm.functions.Function2<? super androidx.compose.animation.AnimatedContentScope,? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public static inline <reified T> void composable(androidx.navigation.NavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? enterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? exitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? popEnterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? popExitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function2<? super androidx.compose.animation.AnimatedContentScope,? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public static void dialog(androidx.navigation.NavGraphBuilder, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional androidx.compose.ui.window.DialogProperties dialogProperties, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public static inline <reified T> void dialog(androidx.navigation.NavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional androidx.compose.ui.window.DialogProperties dialogProperties, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public static inline <reified T> void navigation(androidx.navigation.NavGraphBuilder, Object startDestination, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? enterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? exitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? popEnterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? popExitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated public static void navigation(androidx.navigation.NavGraphBuilder, String startDestination, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.EnterTransition?>? enterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.ExitTransition?>? exitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.EnterTransition?>? popEnterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.ExitTransition?>? popExitTransition, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated public static void navigation(androidx.navigation.NavGraphBuilder, String startDestination, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static void navigation(androidx.navigation.NavGraphBuilder, String startDestination, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? enterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? exitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? popEnterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? popExitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void navigation(androidx.navigation.NavGraphBuilder, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? enterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? exitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? popEnterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? popExitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavHostControllerKt {
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.navigation.NavBackStackEntry?> currentBackStackEntryAsState(androidx.navigation.NavController);
+    method @androidx.compose.runtime.Composable public static androidx.navigation.NavHostController rememberNavController(androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>... navigators);
+  }
+
+  public final class NavHostKt {
+    method @Deprecated @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, androidx.navigation.NavGraph graph, optional androidx.compose.ui.Modifier modifier);
+    method @Deprecated @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, androidx.navigation.NavGraph graph, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment contentAlignment, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.EnterTransition> enterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.ExitTransition> exitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.EnterTransition> popEnterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.ExitTransition> popExitTransition);
+    method @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, androidx.navigation.NavGraph graph, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment contentAlignment, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> enterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> exitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> popEnterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> popExitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform);
+    method @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, Object startDestination, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment contentAlignment, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> enterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> exitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> popEnterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> popExitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, String startDestination, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment contentAlignment, optional String? route, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.EnterTransition> enterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.ExitTransition> exitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.EnterTransition> popEnterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.ExitTransition> popExitTransition, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, String startDestination, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment contentAlignment, optional String? route, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> enterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> exitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> popEnterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> popExitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, String startDestination, optional androidx.compose.ui.Modifier modifier, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment contentAlignment, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> enterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> exitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> popEnterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> popExitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+}
+
diff --git a/navigation/navigation-compose/api/2.8.0-beta05.txt b/navigation/navigation-compose/api/2.8.0-beta05.txt
new file mode 100644
index 0000000..f4411f7
--- /dev/null
+++ b/navigation/navigation-compose/api/2.8.0-beta05.txt
@@ -0,0 +1,94 @@
+// Signature format: 4.0
+package androidx.navigation.compose {
+
+  @androidx.navigation.Navigator.Name("composable") public final class ComposeNavigator extends androidx.navigation.Navigator<androidx.navigation.compose.ComposeNavigator.Destination> {
+    ctor public ComposeNavigator();
+    method public androidx.navigation.compose.ComposeNavigator.Destination createDestination();
+    method public kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getBackStack();
+    method public void onTransitionComplete(androidx.navigation.NavBackStackEntry entry);
+    method public void prepareForTransition(androidx.navigation.NavBackStackEntry entry);
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> backStack;
+  }
+
+  @androidx.navigation.NavDestination.ClassType(Composable::class) public static final class ComposeNavigator.Destination extends androidx.navigation.NavDestination {
+    ctor @Deprecated public ComposeNavigator.Destination(androidx.navigation.compose.ComposeNavigator navigator, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    ctor public ComposeNavigator.Destination(androidx.navigation.compose.ComposeNavigator navigator, kotlin.jvm.functions.Function2<? super androidx.compose.animation.AnimatedContentScope,androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class ComposeNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.compose.ComposeNavigator.Destination> {
+    ctor public ComposeNavigatorDestinationBuilder(androidx.navigation.compose.ComposeNavigator navigator, String route, kotlin.jvm.functions.Function2<? super androidx.compose.animation.AnimatedContentScope,? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    ctor public ComposeNavigatorDestinationBuilder(androidx.navigation.compose.ComposeNavigator navigator, kotlin.reflect.KClass<? extends java.lang.Object?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function2<? super androidx.compose.animation.AnimatedContentScope,? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public androidx.navigation.compose.ComposeNavigator.Destination build();
+    method public kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? getEnterTransition();
+    method public kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? getExitTransition();
+    method public kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? getPopEnterTransition();
+    method public kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? getPopExitTransition();
+    method public kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? getSizeTransform();
+    method protected androidx.navigation.compose.ComposeNavigator.Destination instantiateDestination();
+    method public void setEnterTransition(kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>?);
+    method public void setExitTransition(kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>?);
+    method public void setPopEnterTransition(kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>?);
+    method public void setPopExitTransition(kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>?);
+    method public void setSizeTransform(kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>?);
+    property public final kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? enterTransition;
+    property public final kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? exitTransition;
+    property public final kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? popEnterTransition;
+    property public final kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? popExitTransition;
+    property public final kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform;
+  }
+
+  public final class DialogHostKt {
+    method @androidx.compose.runtime.Composable public static void DialogHost(androidx.navigation.compose.DialogNavigator dialogNavigator);
+  }
+
+  @androidx.navigation.Navigator.Name("dialog") public final class DialogNavigator extends androidx.navigation.Navigator<androidx.navigation.compose.DialogNavigator.Destination> {
+    ctor public DialogNavigator();
+    method public androidx.navigation.compose.DialogNavigator.Destination createDestination();
+  }
+
+  @androidx.navigation.NavDestination.ClassType(Composable::class) public static final class DialogNavigator.Destination extends androidx.navigation.NavDestination implements androidx.navigation.FloatingWindow {
+    ctor public DialogNavigator.Destination(androidx.navigation.compose.DialogNavigator navigator, optional androidx.compose.ui.window.DialogProperties dialogProperties, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DialogNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.compose.DialogNavigator.Destination> {
+    ctor public DialogNavigatorDestinationBuilder(androidx.navigation.compose.DialogNavigator navigator, String route, androidx.compose.ui.window.DialogProperties dialogProperties, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    ctor public DialogNavigatorDestinationBuilder(androidx.navigation.compose.DialogNavigator navigator, kotlin.reflect.KClass<? extends java.lang.Object?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, androidx.compose.ui.window.DialogProperties dialogProperties, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method protected androidx.navigation.compose.DialogNavigator.Destination instantiateDestination();
+  }
+
+  public final class NavBackStackEntryProviderKt {
+    method @androidx.compose.runtime.Composable public static void LocalOwnersProvider(androidx.navigation.NavBackStackEntry, androidx.compose.runtime.saveable.SaveableStateHolder saveableStateHolder, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+  }
+
+  public final class NavGraphBuilderKt {
+    method @Deprecated public static void composable(androidx.navigation.NavGraphBuilder, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public static void composable(androidx.navigation.NavGraphBuilder, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? enterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? exitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? popEnterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? popExitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function2<? super androidx.compose.animation.AnimatedContentScope,? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method @Deprecated public static void composable(androidx.navigation.NavGraphBuilder, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? enterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? exitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? popEnterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? popExitTransition, kotlin.jvm.functions.Function2<? super androidx.compose.animation.AnimatedContentScope,? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public static inline <reified T> void composable(androidx.navigation.NavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? enterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? exitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? popEnterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? popExitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function2<? super androidx.compose.animation.AnimatedContentScope,? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public static void dialog(androidx.navigation.NavGraphBuilder, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional androidx.compose.ui.window.DialogProperties dialogProperties, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public static inline <reified T> void dialog(androidx.navigation.NavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional androidx.compose.ui.window.DialogProperties dialogProperties, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public static inline <reified T> void navigation(androidx.navigation.NavGraphBuilder, Object startDestination, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? enterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? exitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? popEnterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? popExitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated public static void navigation(androidx.navigation.NavGraphBuilder, String startDestination, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.EnterTransition?>? enterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.ExitTransition?>? exitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.EnterTransition?>? popEnterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.ExitTransition?>? popExitTransition, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated public static void navigation(androidx.navigation.NavGraphBuilder, String startDestination, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static void navigation(androidx.navigation.NavGraphBuilder, String startDestination, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? enterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? exitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? popEnterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? popExitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void navigation(androidx.navigation.NavGraphBuilder, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? enterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? exitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? popEnterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? popExitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavHostControllerKt {
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.navigation.NavBackStackEntry?> currentBackStackEntryAsState(androidx.navigation.NavController);
+    method @androidx.compose.runtime.Composable public static androidx.navigation.NavHostController rememberNavController(androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>... navigators);
+  }
+
+  public final class NavHostKt {
+    method @Deprecated @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, androidx.navigation.NavGraph graph, optional androidx.compose.ui.Modifier modifier);
+    method @Deprecated @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, androidx.navigation.NavGraph graph, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment contentAlignment, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.EnterTransition> enterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.ExitTransition> exitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.EnterTransition> popEnterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.ExitTransition> popExitTransition);
+    method @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, androidx.navigation.NavGraph graph, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment contentAlignment, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> enterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> exitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> popEnterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> popExitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform);
+    method @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, Object startDestination, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment contentAlignment, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> enterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> exitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> popEnterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> popExitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, String startDestination, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment contentAlignment, optional String? route, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.EnterTransition> enterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.ExitTransition> exitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.EnterTransition> popEnterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.ExitTransition> popExitTransition, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, String startDestination, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment contentAlignment, optional String? route, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> enterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> exitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> popEnterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> popExitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, String startDestination, optional androidx.compose.ui.Modifier modifier, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment contentAlignment, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> enterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> exitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> popEnterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> popExitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+}
+
diff --git a/navigation/navigation-compose/api/res-2.8.0-beta04.txt b/navigation/navigation-compose/api/res-2.8.0-beta04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-compose/api/res-2.8.0-beta04.txt
diff --git a/navigation/navigation-compose/api/res-2.8.0-beta05.txt b/navigation/navigation-compose/api/res-2.8.0-beta05.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-compose/api/res-2.8.0-beta05.txt
diff --git a/navigation/navigation-compose/api/restricted_2.8.0-beta04.txt b/navigation/navigation-compose/api/restricted_2.8.0-beta04.txt
new file mode 100644
index 0000000..f4411f7
--- /dev/null
+++ b/navigation/navigation-compose/api/restricted_2.8.0-beta04.txt
@@ -0,0 +1,94 @@
+// Signature format: 4.0
+package androidx.navigation.compose {
+
+  @androidx.navigation.Navigator.Name("composable") public final class ComposeNavigator extends androidx.navigation.Navigator<androidx.navigation.compose.ComposeNavigator.Destination> {
+    ctor public ComposeNavigator();
+    method public androidx.navigation.compose.ComposeNavigator.Destination createDestination();
+    method public kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getBackStack();
+    method public void onTransitionComplete(androidx.navigation.NavBackStackEntry entry);
+    method public void prepareForTransition(androidx.navigation.NavBackStackEntry entry);
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> backStack;
+  }
+
+  @androidx.navigation.NavDestination.ClassType(Composable::class) public static final class ComposeNavigator.Destination extends androidx.navigation.NavDestination {
+    ctor @Deprecated public ComposeNavigator.Destination(androidx.navigation.compose.ComposeNavigator navigator, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    ctor public ComposeNavigator.Destination(androidx.navigation.compose.ComposeNavigator navigator, kotlin.jvm.functions.Function2<? super androidx.compose.animation.AnimatedContentScope,androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class ComposeNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.compose.ComposeNavigator.Destination> {
+    ctor public ComposeNavigatorDestinationBuilder(androidx.navigation.compose.ComposeNavigator navigator, String route, kotlin.jvm.functions.Function2<? super androidx.compose.animation.AnimatedContentScope,? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    ctor public ComposeNavigatorDestinationBuilder(androidx.navigation.compose.ComposeNavigator navigator, kotlin.reflect.KClass<? extends java.lang.Object?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function2<? super androidx.compose.animation.AnimatedContentScope,? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public androidx.navigation.compose.ComposeNavigator.Destination build();
+    method public kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? getEnterTransition();
+    method public kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? getExitTransition();
+    method public kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? getPopEnterTransition();
+    method public kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? getPopExitTransition();
+    method public kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? getSizeTransform();
+    method protected androidx.navigation.compose.ComposeNavigator.Destination instantiateDestination();
+    method public void setEnterTransition(kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>?);
+    method public void setExitTransition(kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>?);
+    method public void setPopEnterTransition(kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>?);
+    method public void setPopExitTransition(kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>?);
+    method public void setSizeTransform(kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>?);
+    property public final kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? enterTransition;
+    property public final kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? exitTransition;
+    property public final kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? popEnterTransition;
+    property public final kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? popExitTransition;
+    property public final kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform;
+  }
+
+  public final class DialogHostKt {
+    method @androidx.compose.runtime.Composable public static void DialogHost(androidx.navigation.compose.DialogNavigator dialogNavigator);
+  }
+
+  @androidx.navigation.Navigator.Name("dialog") public final class DialogNavigator extends androidx.navigation.Navigator<androidx.navigation.compose.DialogNavigator.Destination> {
+    ctor public DialogNavigator();
+    method public androidx.navigation.compose.DialogNavigator.Destination createDestination();
+  }
+
+  @androidx.navigation.NavDestination.ClassType(Composable::class) public static final class DialogNavigator.Destination extends androidx.navigation.NavDestination implements androidx.navigation.FloatingWindow {
+    ctor public DialogNavigator.Destination(androidx.navigation.compose.DialogNavigator navigator, optional androidx.compose.ui.window.DialogProperties dialogProperties, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DialogNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.compose.DialogNavigator.Destination> {
+    ctor public DialogNavigatorDestinationBuilder(androidx.navigation.compose.DialogNavigator navigator, String route, androidx.compose.ui.window.DialogProperties dialogProperties, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    ctor public DialogNavigatorDestinationBuilder(androidx.navigation.compose.DialogNavigator navigator, kotlin.reflect.KClass<? extends java.lang.Object?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, androidx.compose.ui.window.DialogProperties dialogProperties, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method protected androidx.navigation.compose.DialogNavigator.Destination instantiateDestination();
+  }
+
+  public final class NavBackStackEntryProviderKt {
+    method @androidx.compose.runtime.Composable public static void LocalOwnersProvider(androidx.navigation.NavBackStackEntry, androidx.compose.runtime.saveable.SaveableStateHolder saveableStateHolder, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+  }
+
+  public final class NavGraphBuilderKt {
+    method @Deprecated public static void composable(androidx.navigation.NavGraphBuilder, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public static void composable(androidx.navigation.NavGraphBuilder, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? enterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? exitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? popEnterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? popExitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function2<? super androidx.compose.animation.AnimatedContentScope,? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method @Deprecated public static void composable(androidx.navigation.NavGraphBuilder, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? enterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? exitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? popEnterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? popExitTransition, kotlin.jvm.functions.Function2<? super androidx.compose.animation.AnimatedContentScope,? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public static inline <reified T> void composable(androidx.navigation.NavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? enterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? exitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? popEnterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? popExitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function2<? super androidx.compose.animation.AnimatedContentScope,? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public static void dialog(androidx.navigation.NavGraphBuilder, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional androidx.compose.ui.window.DialogProperties dialogProperties, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public static inline <reified T> void dialog(androidx.navigation.NavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional androidx.compose.ui.window.DialogProperties dialogProperties, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public static inline <reified T> void navigation(androidx.navigation.NavGraphBuilder, Object startDestination, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? enterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? exitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? popEnterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? popExitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated public static void navigation(androidx.navigation.NavGraphBuilder, String startDestination, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.EnterTransition?>? enterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.ExitTransition?>? exitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.EnterTransition?>? popEnterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.ExitTransition?>? popExitTransition, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated public static void navigation(androidx.navigation.NavGraphBuilder, String startDestination, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static void navigation(androidx.navigation.NavGraphBuilder, String startDestination, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? enterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? exitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? popEnterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? popExitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void navigation(androidx.navigation.NavGraphBuilder, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? enterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? exitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? popEnterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? popExitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavHostControllerKt {
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.navigation.NavBackStackEntry?> currentBackStackEntryAsState(androidx.navigation.NavController);
+    method @androidx.compose.runtime.Composable public static androidx.navigation.NavHostController rememberNavController(androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>... navigators);
+  }
+
+  public final class NavHostKt {
+    method @Deprecated @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, androidx.navigation.NavGraph graph, optional androidx.compose.ui.Modifier modifier);
+    method @Deprecated @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, androidx.navigation.NavGraph graph, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment contentAlignment, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.EnterTransition> enterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.ExitTransition> exitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.EnterTransition> popEnterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.ExitTransition> popExitTransition);
+    method @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, androidx.navigation.NavGraph graph, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment contentAlignment, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> enterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> exitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> popEnterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> popExitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform);
+    method @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, Object startDestination, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment contentAlignment, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> enterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> exitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> popEnterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> popExitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, String startDestination, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment contentAlignment, optional String? route, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.EnterTransition> enterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.ExitTransition> exitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.EnterTransition> popEnterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.ExitTransition> popExitTransition, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, String startDestination, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment contentAlignment, optional String? route, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> enterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> exitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> popEnterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> popExitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, String startDestination, optional androidx.compose.ui.Modifier modifier, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment contentAlignment, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> enterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> exitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> popEnterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> popExitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+}
+
diff --git a/navigation/navigation-compose/api/restricted_2.8.0-beta05.txt b/navigation/navigation-compose/api/restricted_2.8.0-beta05.txt
new file mode 100644
index 0000000..f4411f7
--- /dev/null
+++ b/navigation/navigation-compose/api/restricted_2.8.0-beta05.txt
@@ -0,0 +1,94 @@
+// Signature format: 4.0
+package androidx.navigation.compose {
+
+  @androidx.navigation.Navigator.Name("composable") public final class ComposeNavigator extends androidx.navigation.Navigator<androidx.navigation.compose.ComposeNavigator.Destination> {
+    ctor public ComposeNavigator();
+    method public androidx.navigation.compose.ComposeNavigator.Destination createDestination();
+    method public kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getBackStack();
+    method public void onTransitionComplete(androidx.navigation.NavBackStackEntry entry);
+    method public void prepareForTransition(androidx.navigation.NavBackStackEntry entry);
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> backStack;
+  }
+
+  @androidx.navigation.NavDestination.ClassType(Composable::class) public static final class ComposeNavigator.Destination extends androidx.navigation.NavDestination {
+    ctor @Deprecated public ComposeNavigator.Destination(androidx.navigation.compose.ComposeNavigator navigator, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    ctor public ComposeNavigator.Destination(androidx.navigation.compose.ComposeNavigator navigator, kotlin.jvm.functions.Function2<? super androidx.compose.animation.AnimatedContentScope,androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class ComposeNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.compose.ComposeNavigator.Destination> {
+    ctor public ComposeNavigatorDestinationBuilder(androidx.navigation.compose.ComposeNavigator navigator, String route, kotlin.jvm.functions.Function2<? super androidx.compose.animation.AnimatedContentScope,? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    ctor public ComposeNavigatorDestinationBuilder(androidx.navigation.compose.ComposeNavigator navigator, kotlin.reflect.KClass<? extends java.lang.Object?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function2<? super androidx.compose.animation.AnimatedContentScope,? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public androidx.navigation.compose.ComposeNavigator.Destination build();
+    method public kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? getEnterTransition();
+    method public kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? getExitTransition();
+    method public kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? getPopEnterTransition();
+    method public kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? getPopExitTransition();
+    method public kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? getSizeTransform();
+    method protected androidx.navigation.compose.ComposeNavigator.Destination instantiateDestination();
+    method public void setEnterTransition(kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>?);
+    method public void setExitTransition(kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>?);
+    method public void setPopEnterTransition(kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>?);
+    method public void setPopExitTransition(kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>?);
+    method public void setSizeTransform(kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>?);
+    property public final kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? enterTransition;
+    property public final kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? exitTransition;
+    property public final kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? popEnterTransition;
+    property public final kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? popExitTransition;
+    property public final kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform;
+  }
+
+  public final class DialogHostKt {
+    method @androidx.compose.runtime.Composable public static void DialogHost(androidx.navigation.compose.DialogNavigator dialogNavigator);
+  }
+
+  @androidx.navigation.Navigator.Name("dialog") public final class DialogNavigator extends androidx.navigation.Navigator<androidx.navigation.compose.DialogNavigator.Destination> {
+    ctor public DialogNavigator();
+    method public androidx.navigation.compose.DialogNavigator.Destination createDestination();
+  }
+
+  @androidx.navigation.NavDestination.ClassType(Composable::class) public static final class DialogNavigator.Destination extends androidx.navigation.NavDestination implements androidx.navigation.FloatingWindow {
+    ctor public DialogNavigator.Destination(androidx.navigation.compose.DialogNavigator navigator, optional androidx.compose.ui.window.DialogProperties dialogProperties, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DialogNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.compose.DialogNavigator.Destination> {
+    ctor public DialogNavigatorDestinationBuilder(androidx.navigation.compose.DialogNavigator navigator, String route, androidx.compose.ui.window.DialogProperties dialogProperties, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    ctor public DialogNavigatorDestinationBuilder(androidx.navigation.compose.DialogNavigator navigator, kotlin.reflect.KClass<? extends java.lang.Object?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, androidx.compose.ui.window.DialogProperties dialogProperties, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method protected androidx.navigation.compose.DialogNavigator.Destination instantiateDestination();
+  }
+
+  public final class NavBackStackEntryProviderKt {
+    method @androidx.compose.runtime.Composable public static void LocalOwnersProvider(androidx.navigation.NavBackStackEntry, androidx.compose.runtime.saveable.SaveableStateHolder saveableStateHolder, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+  }
+
+  public final class NavGraphBuilderKt {
+    method @Deprecated public static void composable(androidx.navigation.NavGraphBuilder, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public static void composable(androidx.navigation.NavGraphBuilder, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? enterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? exitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? popEnterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? popExitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function2<? super androidx.compose.animation.AnimatedContentScope,? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method @Deprecated public static void composable(androidx.navigation.NavGraphBuilder, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? enterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? exitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? popEnterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? popExitTransition, kotlin.jvm.functions.Function2<? super androidx.compose.animation.AnimatedContentScope,? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public static inline <reified T> void composable(androidx.navigation.NavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? enterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? exitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? popEnterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? popExitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function2<? super androidx.compose.animation.AnimatedContentScope,? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public static void dialog(androidx.navigation.NavGraphBuilder, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional androidx.compose.ui.window.DialogProperties dialogProperties, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public static inline <reified T> void dialog(androidx.navigation.NavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional androidx.compose.ui.window.DialogProperties dialogProperties, kotlin.jvm.functions.Function1<? super androidx.navigation.NavBackStackEntry,kotlin.Unit> content);
+    method public static inline <reified T> void navigation(androidx.navigation.NavGraphBuilder, Object startDestination, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? enterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? exitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? popEnterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? popExitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated public static void navigation(androidx.navigation.NavGraphBuilder, String startDestination, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.EnterTransition?>? enterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.ExitTransition?>? exitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.EnterTransition?>? popEnterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.ExitTransition?>? popExitTransition, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated public static void navigation(androidx.navigation.NavGraphBuilder, String startDestination, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static void navigation(androidx.navigation.NavGraphBuilder, String startDestination, String route, optional java.util.List<androidx.navigation.NamedNavArgument> arguments, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? enterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? exitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? popEnterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? popExitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void navigation(androidx.navigation.NavGraphBuilder, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, optional java.util.List<androidx.navigation.NavDeepLink> deepLinks, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? enterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? exitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition?>? popEnterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition?>? popExitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavHostControllerKt {
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.navigation.NavBackStackEntry?> currentBackStackEntryAsState(androidx.navigation.NavController);
+    method @androidx.compose.runtime.Composable public static androidx.navigation.NavHostController rememberNavController(androidx.navigation.Navigator<? extends androidx.navigation.NavDestination>... navigators);
+  }
+
+  public final class NavHostKt {
+    method @Deprecated @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, androidx.navigation.NavGraph graph, optional androidx.compose.ui.Modifier modifier);
+    method @Deprecated @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, androidx.navigation.NavGraph graph, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment contentAlignment, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.EnterTransition> enterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.ExitTransition> exitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.EnterTransition> popEnterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.ExitTransition> popExitTransition);
+    method @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, androidx.navigation.NavGraph graph, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment contentAlignment, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> enterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> exitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> popEnterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> popExitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform);
+    method @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, Object startDestination, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment contentAlignment, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> enterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> exitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> popEnterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> popExitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, String startDestination, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment contentAlignment, optional String? route, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.EnterTransition> enterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.ExitTransition> exitTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.EnterTransition> popEnterTransition, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,? extends androidx.compose.animation.ExitTransition> popExitTransition, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, String startDestination, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment contentAlignment, optional String? route, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> enterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> exitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> popEnterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> popExitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, String startDestination, optional androidx.compose.ui.Modifier modifier, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method @androidx.compose.runtime.Composable public static void NavHost(androidx.navigation.NavHostController navController, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment contentAlignment, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> enterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> exitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.EnterTransition> popEnterTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.ExitTransition> popExitTransition, optional kotlin.jvm.functions.Function1<androidx.compose.animation.AnimatedContentTransitionScope<androidx.navigation.NavBackStackEntry>,androidx.compose.animation.SizeTransform?>? sizeTransform, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+}
+
diff --git a/navigation/navigation-compose/build.gradle b/navigation/navigation-compose/build.gradle
index 9c597aa..2e7e9c4 100644
--- a/navigation/navigation-compose/build.gradle
+++ b/navigation/navigation-compose/build.gradle
@@ -28,11 +28,11 @@
 
     implementation(libs.kotlinStdlib)
     api("androidx.activity:activity-compose:1.8.0")
-    api("androidx.compose.animation:animation:1.7.0-beta03")
-    implementation("androidx.compose.foundation:foundation-layout:1.7.0-beta03")
-    api("androidx.compose.runtime:runtime:1.7.0-beta03")
-    api("androidx.compose.runtime:runtime-saveable:1.7.0-beta03")
-    api("androidx.compose.ui:ui:1.7.0-beta03")
+    api("androidx.compose.animation:animation:1.7.0-beta04")
+    implementation("androidx.compose.foundation:foundation-layout:1.7.0-beta04")
+    api("androidx.compose.runtime:runtime:1.7.0-beta04")
+    api("androidx.compose.runtime:runtime-saveable:1.7.0-beta04")
+    api("androidx.compose.ui:ui:1.7.0-beta04")
     api("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2")
     api(projectOrArtifact(":navigation:navigation-runtime-ktx"))
     implementation(libs.kotlinSerializationCore)
diff --git a/navigation/navigation-compose/src/androidTest/java/androidx/navigation/compose/NavHostPredictiveBackTest.kt b/navigation/navigation-compose/src/androidTest/java/androidx/navigation/compose/NavHostPredictiveBackTest.kt
new file mode 100644
index 0000000..b20b318
--- /dev/null
+++ b/navigation/navigation-compose/src/androidTest/java/androidx/navigation/compose/NavHostPredictiveBackTest.kt
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.navigation.compose
+
+import android.window.BackEvent
+import androidx.activity.BackEventCompat
+import androidx.activity.OnBackPressedDispatcher
+import androidx.activity.compose.LocalOnBackPressedDispatcherOwner
+import androidx.compose.foundation.text.BasicText
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.lifecycle.Lifecycle
+import androidx.navigation.NavHostController
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@LargeTest
+@RunWith(AndroidJUnit4::class)
+class NavHostPredictiveBackTest {
+    @get:Rule val composeTestRule = createComposeRule()
+
+    @Test
+    fun testNavHostAnimations() {
+        lateinit var navController: NavHostController
+        lateinit var backPressedDispatcher: OnBackPressedDispatcher
+        composeTestRule.setContent {
+            navController = rememberNavController()
+            backPressedDispatcher =
+                LocalOnBackPressedDispatcherOwner.current!!.onBackPressedDispatcher
+            NavHost(navController, startDestination = first) {
+                composable(first) { BasicText(first) }
+                composable(second) { BasicText(second) }
+            }
+        }
+
+        val firstEntry = navController.currentBackStackEntry
+
+        composeTestRule.runOnIdle {
+            assertThat(firstEntry?.lifecycle?.currentState).isEqualTo(Lifecycle.State.RESUMED)
+        }
+
+        composeTestRule.runOnIdle { navController.navigate(second) }
+
+        assertThat(firstEntry?.lifecycle?.currentState).isEqualTo(Lifecycle.State.CREATED)
+        assertThat(navController.currentBackStackEntry?.lifecycle?.currentState)
+            .isEqualTo(Lifecycle.State.STARTED)
+
+        composeTestRule.runOnIdle {
+            assertThat(firstEntry?.lifecycle?.currentState).isEqualTo(Lifecycle.State.CREATED)
+            assertThat(navController.currentBackStackEntry?.lifecycle?.currentState)
+                .isEqualTo(Lifecycle.State.RESUMED)
+        }
+
+        val secondEntry = navController.currentBackStackEntry
+
+        composeTestRule.runOnIdle {
+            backPressedDispatcher.dispatchOnBackStarted(
+                BackEventCompat(0.1F, 0.1F, 0.1F, BackEvent.EDGE_LEFT)
+            )
+            assertThat(navController.currentBackStackEntry?.lifecycle?.currentState)
+                .isEqualTo(Lifecycle.State.STARTED)
+            assertThat(navController.previousBackStackEntry?.lifecycle?.currentState)
+                .isEqualTo(Lifecycle.State.STARTED)
+            backPressedDispatcher.dispatchOnBackProgressed(
+                BackEventCompat(0.1F, 0.1F, 0.5F, BackEvent.EDGE_LEFT)
+            )
+        }
+
+        composeTestRule.waitForIdle()
+
+        composeTestRule.runOnIdle {
+            backPressedDispatcher.dispatchOnBackProgressed(
+                BackEventCompat(0.1F, 0.1F, 0.5F, BackEvent.EDGE_LEFT)
+            )
+        }
+
+        assertThat(navController.currentBackStackEntry?.lifecycle?.currentState)
+            .isEqualTo(Lifecycle.State.STARTED)
+        assertThat(secondEntry?.lifecycle?.currentState).isEqualTo(Lifecycle.State.STARTED)
+
+        composeTestRule.runOnIdle { backPressedDispatcher.dispatchOnBackCancelled() }
+
+        composeTestRule.runOnIdle {
+            assertThat(secondEntry?.lifecycle?.currentState).isEqualTo(Lifecycle.State.RESUMED)
+            assertThat(firstEntry?.lifecycle?.currentState).isEqualTo(Lifecycle.State.CREATED)
+        }
+    }
+}
+
+private const val first = "first"
+private const val second = "second"
diff --git a/navigation/navigation-compose/src/main/java/androidx/navigation/compose/NavHost.kt b/navigation/navigation-compose/src/main/java/androidx/navigation/compose/NavHost.kt
index 373207b..c7020d0 100644
--- a/navigation/navigation-compose/src/main/java/androidx/navigation/compose/NavHost.kt
+++ b/navigation/navigation-compose/src/main/java/androidx/navigation/compose/NavHost.kt
@@ -25,6 +25,7 @@
 import androidx.compose.animation.ExitTransition
 import androidx.compose.animation.SizeTransform
 import androidx.compose.animation.core.SeekableTransitionState
+import androidx.compose.animation.core.animate
 import androidx.compose.animation.core.rememberTransition
 import androidx.compose.animation.core.tween
 import androidx.compose.animation.fadeIn
@@ -58,6 +59,7 @@
 import kotlin.coroutines.cancellation.CancellationException
 import kotlin.reflect.KClass
 import kotlin.reflect.KType
+import kotlinx.coroutines.launch
 
 /**
  * Provides a place in the Compose hierarchy for self contained navigation to occur.
@@ -602,6 +604,8 @@
             SeekableTransitionState(backStackEntry)
         }
 
+        val transition = rememberTransition(transitionState, label = "entry")
+
         if (inPredictiveBack) {
             LaunchedEffect(progress) {
                 val previousEntry = currentBackStack[currentBackStack.size - 2]
@@ -613,12 +617,32 @@
                 // are already on the current state
                 if (transitionState.currentState != backStackEntry) {
                     transitionState.animateTo(backStackEntry)
+                } else {
+                    // convert from nanoseconds to milliseconds
+                    val totalDuration = transition.totalDurationNanos / 1000000
+                    // When the predictive back gesture is cancel, we need to manually animate
+                    // the SeekableTransitionState from where it left off, to zero and then
+                    // snapTo the final position.
+                    animate(
+                        transitionState.fraction,
+                        0f,
+                        animationSpec = tween((transitionState.fraction * totalDuration).toInt())
+                    ) { value, _ ->
+                        [email protected] {
+                            if (value > 0) {
+                                // Seek the original transition back to the currentState
+                                transitionState.seekTo(value)
+                            }
+                            if (value == 0f) {
+                                // Once we animate to the start, we need to snap to the right state.
+                                transitionState.snapTo(backStackEntry)
+                            }
+                        }
+                    }
                 }
             }
         }
 
-        val transition = rememberTransition(transitionState, label = "entry")
-
         transition.AnimatedContent(
             modifier,
             transitionSpec = {
diff --git a/navigation/navigation-dynamic-features-fragment/api/2.8.0-beta04.txt b/navigation/navigation-dynamic-features-fragment/api/2.8.0-beta04.txt
new file mode 100644
index 0000000..575de0b
--- /dev/null
+++ b/navigation/navigation-dynamic-features-fragment/api/2.8.0-beta04.txt
@@ -0,0 +1,73 @@
+// Signature format: 4.0
+package androidx.navigation.dynamicfeatures.fragment {
+
+  @androidx.navigation.Navigator.Name("fragment") public final class DynamicFragmentNavigator extends androidx.navigation.fragment.FragmentNavigator {
+    ctor public DynamicFragmentNavigator(android.content.Context context, androidx.fragment.app.FragmentManager manager, int containerId, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
+    method public androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator.Destination createDestination();
+  }
+
+  public static final class DynamicFragmentNavigator.Destination extends androidx.navigation.fragment.FragmentNavigator.Destination {
+    ctor public DynamicFragmentNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.fragment.FragmentNavigator.Destination> fragmentNavigator);
+    ctor public DynamicFragmentNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public String? getModuleName();
+    method public void setModuleName(String?);
+    property public final String? moduleName;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DynamicFragmentNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.fragment.FragmentNavigator.Destination> {
+    ctor @Deprecated public DynamicFragmentNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator navigator, @IdRes int id, String fragmentClassName);
+    ctor public DynamicFragmentNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator navigator, String route, String fragmentClassName);
+    ctor public DynamicFragmentNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator navigator, kotlin.reflect.KClass<? extends java.lang.Object?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, String fragmentClassName);
+    method public androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator.Destination build();
+    method public String? getModuleName();
+    method public void setModuleName(String?);
+    property public final String? moduleName;
+  }
+
+  public final class DynamicFragmentNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id);
+    method @Deprecated public static inline void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, String fragmentClassName, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route);
+    method public static inline void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, String fragmentClassName, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String fragmentClassName, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.Fragment, reified T> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public static inline <reified F extends androidx.fragment.app.Fragment, reified T> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+  }
+
+  public class DynamicNavHostFragment extends androidx.navigation.fragment.NavHostFragment {
+    ctor public DynamicNavHostFragment();
+    method public static final androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment create(@NavigationRes int graphResId);
+    method public static final androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+    method protected com.google.android.play.core.splitinstall.SplitInstallManager createSplitInstallManager();
+    field public static final androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment.Companion Companion;
+  }
+
+  public static final class DynamicNavHostFragment.Companion {
+    method public androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment create(@NavigationRes int graphResId);
+    method public androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+  }
+
+}
+
+package androidx.navigation.dynamicfeatures.fragment.ui {
+
+  public abstract class AbstractProgressFragment extends androidx.fragment.app.Fragment {
+    ctor public AbstractProgressFragment();
+    ctor public AbstractProgressFragment(int contentLayoutId);
+    method protected abstract void onCancelled();
+    method protected abstract void onFailed(@com.google.android.play.core.splitinstall.model.SplitInstallErrorCode int errorCode);
+    method protected void onInstalled();
+    method protected abstract void onProgress(@com.google.android.play.core.splitinstall.model.SplitInstallSessionStatus int status, long bytesDownloaded, long bytesTotal);
+  }
+
+  public final class DefaultProgressFragment extends androidx.navigation.dynamicfeatures.fragment.ui.AbstractProgressFragment {
+    ctor public DefaultProgressFragment();
+    method protected void onCancelled();
+    method protected void onFailed(@com.google.android.play.core.splitinstall.model.SplitInstallErrorCode int errorCode);
+    method protected void onProgress(int status, long bytesDownloaded, long bytesTotal);
+  }
+
+}
+
diff --git a/navigation/navigation-dynamic-features-fragment/api/2.8.0-beta05.txt b/navigation/navigation-dynamic-features-fragment/api/2.8.0-beta05.txt
new file mode 100644
index 0000000..575de0b
--- /dev/null
+++ b/navigation/navigation-dynamic-features-fragment/api/2.8.0-beta05.txt
@@ -0,0 +1,73 @@
+// Signature format: 4.0
+package androidx.navigation.dynamicfeatures.fragment {
+
+  @androidx.navigation.Navigator.Name("fragment") public final class DynamicFragmentNavigator extends androidx.navigation.fragment.FragmentNavigator {
+    ctor public DynamicFragmentNavigator(android.content.Context context, androidx.fragment.app.FragmentManager manager, int containerId, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
+    method public androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator.Destination createDestination();
+  }
+
+  public static final class DynamicFragmentNavigator.Destination extends androidx.navigation.fragment.FragmentNavigator.Destination {
+    ctor public DynamicFragmentNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.fragment.FragmentNavigator.Destination> fragmentNavigator);
+    ctor public DynamicFragmentNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public String? getModuleName();
+    method public void setModuleName(String?);
+    property public final String? moduleName;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DynamicFragmentNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.fragment.FragmentNavigator.Destination> {
+    ctor @Deprecated public DynamicFragmentNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator navigator, @IdRes int id, String fragmentClassName);
+    ctor public DynamicFragmentNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator navigator, String route, String fragmentClassName);
+    ctor public DynamicFragmentNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator navigator, kotlin.reflect.KClass<? extends java.lang.Object?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, String fragmentClassName);
+    method public androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator.Destination build();
+    method public String? getModuleName();
+    method public void setModuleName(String?);
+    property public final String? moduleName;
+  }
+
+  public final class DynamicFragmentNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id);
+    method @Deprecated public static inline void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, String fragmentClassName, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route);
+    method public static inline void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, String fragmentClassName, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String fragmentClassName, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.Fragment, reified T> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public static inline <reified F extends androidx.fragment.app.Fragment, reified T> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+  }
+
+  public class DynamicNavHostFragment extends androidx.navigation.fragment.NavHostFragment {
+    ctor public DynamicNavHostFragment();
+    method public static final androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment create(@NavigationRes int graphResId);
+    method public static final androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+    method protected com.google.android.play.core.splitinstall.SplitInstallManager createSplitInstallManager();
+    field public static final androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment.Companion Companion;
+  }
+
+  public static final class DynamicNavHostFragment.Companion {
+    method public androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment create(@NavigationRes int graphResId);
+    method public androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+  }
+
+}
+
+package androidx.navigation.dynamicfeatures.fragment.ui {
+
+  public abstract class AbstractProgressFragment extends androidx.fragment.app.Fragment {
+    ctor public AbstractProgressFragment();
+    ctor public AbstractProgressFragment(int contentLayoutId);
+    method protected abstract void onCancelled();
+    method protected abstract void onFailed(@com.google.android.play.core.splitinstall.model.SplitInstallErrorCode int errorCode);
+    method protected void onInstalled();
+    method protected abstract void onProgress(@com.google.android.play.core.splitinstall.model.SplitInstallSessionStatus int status, long bytesDownloaded, long bytesTotal);
+  }
+
+  public final class DefaultProgressFragment extends androidx.navigation.dynamicfeatures.fragment.ui.AbstractProgressFragment {
+    ctor public DefaultProgressFragment();
+    method protected void onCancelled();
+    method protected void onFailed(@com.google.android.play.core.splitinstall.model.SplitInstallErrorCode int errorCode);
+    method protected void onProgress(int status, long bytesDownloaded, long bytesTotal);
+  }
+
+}
+
diff --git a/navigation/navigation-dynamic-features-fragment/api/res-2.8.0-beta04.txt b/navigation/navigation-dynamic-features-fragment/api/res-2.8.0-beta04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-dynamic-features-fragment/api/res-2.8.0-beta04.txt
diff --git a/navigation/navigation-dynamic-features-fragment/api/res-2.8.0-beta05.txt b/navigation/navigation-dynamic-features-fragment/api/res-2.8.0-beta05.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-dynamic-features-fragment/api/res-2.8.0-beta05.txt
diff --git a/navigation/navigation-dynamic-features-fragment/api/restricted_2.8.0-beta04.txt b/navigation/navigation-dynamic-features-fragment/api/restricted_2.8.0-beta04.txt
new file mode 100644
index 0000000..575de0b
--- /dev/null
+++ b/navigation/navigation-dynamic-features-fragment/api/restricted_2.8.0-beta04.txt
@@ -0,0 +1,73 @@
+// Signature format: 4.0
+package androidx.navigation.dynamicfeatures.fragment {
+
+  @androidx.navigation.Navigator.Name("fragment") public final class DynamicFragmentNavigator extends androidx.navigation.fragment.FragmentNavigator {
+    ctor public DynamicFragmentNavigator(android.content.Context context, androidx.fragment.app.FragmentManager manager, int containerId, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
+    method public androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator.Destination createDestination();
+  }
+
+  public static final class DynamicFragmentNavigator.Destination extends androidx.navigation.fragment.FragmentNavigator.Destination {
+    ctor public DynamicFragmentNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.fragment.FragmentNavigator.Destination> fragmentNavigator);
+    ctor public DynamicFragmentNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public String? getModuleName();
+    method public void setModuleName(String?);
+    property public final String? moduleName;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DynamicFragmentNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.fragment.FragmentNavigator.Destination> {
+    ctor @Deprecated public DynamicFragmentNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator navigator, @IdRes int id, String fragmentClassName);
+    ctor public DynamicFragmentNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator navigator, String route, String fragmentClassName);
+    ctor public DynamicFragmentNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator navigator, kotlin.reflect.KClass<? extends java.lang.Object?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, String fragmentClassName);
+    method public androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator.Destination build();
+    method public String? getModuleName();
+    method public void setModuleName(String?);
+    property public final String? moduleName;
+  }
+
+  public final class DynamicFragmentNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id);
+    method @Deprecated public static inline void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, String fragmentClassName, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route);
+    method public static inline void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, String fragmentClassName, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String fragmentClassName, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.Fragment, reified T> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public static inline <reified F extends androidx.fragment.app.Fragment, reified T> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+  }
+
+  public class DynamicNavHostFragment extends androidx.navigation.fragment.NavHostFragment {
+    ctor public DynamicNavHostFragment();
+    method public static final androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment create(@NavigationRes int graphResId);
+    method public static final androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+    method protected com.google.android.play.core.splitinstall.SplitInstallManager createSplitInstallManager();
+    field public static final androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment.Companion Companion;
+  }
+
+  public static final class DynamicNavHostFragment.Companion {
+    method public androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment create(@NavigationRes int graphResId);
+    method public androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+  }
+
+}
+
+package androidx.navigation.dynamicfeatures.fragment.ui {
+
+  public abstract class AbstractProgressFragment extends androidx.fragment.app.Fragment {
+    ctor public AbstractProgressFragment();
+    ctor public AbstractProgressFragment(int contentLayoutId);
+    method protected abstract void onCancelled();
+    method protected abstract void onFailed(@com.google.android.play.core.splitinstall.model.SplitInstallErrorCode int errorCode);
+    method protected void onInstalled();
+    method protected abstract void onProgress(@com.google.android.play.core.splitinstall.model.SplitInstallSessionStatus int status, long bytesDownloaded, long bytesTotal);
+  }
+
+  public final class DefaultProgressFragment extends androidx.navigation.dynamicfeatures.fragment.ui.AbstractProgressFragment {
+    ctor public DefaultProgressFragment();
+    method protected void onCancelled();
+    method protected void onFailed(@com.google.android.play.core.splitinstall.model.SplitInstallErrorCode int errorCode);
+    method protected void onProgress(int status, long bytesDownloaded, long bytesTotal);
+  }
+
+}
+
diff --git a/navigation/navigation-dynamic-features-fragment/api/restricted_2.8.0-beta05.txt b/navigation/navigation-dynamic-features-fragment/api/restricted_2.8.0-beta05.txt
new file mode 100644
index 0000000..575de0b
--- /dev/null
+++ b/navigation/navigation-dynamic-features-fragment/api/restricted_2.8.0-beta05.txt
@@ -0,0 +1,73 @@
+// Signature format: 4.0
+package androidx.navigation.dynamicfeatures.fragment {
+
+  @androidx.navigation.Navigator.Name("fragment") public final class DynamicFragmentNavigator extends androidx.navigation.fragment.FragmentNavigator {
+    ctor public DynamicFragmentNavigator(android.content.Context context, androidx.fragment.app.FragmentManager manager, int containerId, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
+    method public androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator.Destination createDestination();
+  }
+
+  public static final class DynamicFragmentNavigator.Destination extends androidx.navigation.fragment.FragmentNavigator.Destination {
+    ctor public DynamicFragmentNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.fragment.FragmentNavigator.Destination> fragmentNavigator);
+    ctor public DynamicFragmentNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public String? getModuleName();
+    method public void setModuleName(String?);
+    property public final String? moduleName;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DynamicFragmentNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.fragment.FragmentNavigator.Destination> {
+    ctor @Deprecated public DynamicFragmentNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator navigator, @IdRes int id, String fragmentClassName);
+    ctor public DynamicFragmentNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator navigator, String route, String fragmentClassName);
+    ctor public DynamicFragmentNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator navigator, kotlin.reflect.KClass<? extends java.lang.Object?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, String fragmentClassName);
+    method public androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigator.Destination build();
+    method public String? getModuleName();
+    method public void setModuleName(String?);
+    property public final String? moduleName;
+  }
+
+  public final class DynamicFragmentNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id);
+    method @Deprecated public static inline void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, String fragmentClassName, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route);
+    method public static inline void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, String fragmentClassName, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String fragmentClassName, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.Fragment, reified T> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public static inline <reified F extends androidx.fragment.app.Fragment, reified T> void fragment(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.fragment.DynamicFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+  }
+
+  public class DynamicNavHostFragment extends androidx.navigation.fragment.NavHostFragment {
+    ctor public DynamicNavHostFragment();
+    method public static final androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment create(@NavigationRes int graphResId);
+    method public static final androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+    method protected com.google.android.play.core.splitinstall.SplitInstallManager createSplitInstallManager();
+    field public static final androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment.Companion Companion;
+  }
+
+  public static final class DynamicNavHostFragment.Companion {
+    method public androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment create(@NavigationRes int graphResId);
+    method public androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+  }
+
+}
+
+package androidx.navigation.dynamicfeatures.fragment.ui {
+
+  public abstract class AbstractProgressFragment extends androidx.fragment.app.Fragment {
+    ctor public AbstractProgressFragment();
+    ctor public AbstractProgressFragment(int contentLayoutId);
+    method protected abstract void onCancelled();
+    method protected abstract void onFailed(@com.google.android.play.core.splitinstall.model.SplitInstallErrorCode int errorCode);
+    method protected void onInstalled();
+    method protected abstract void onProgress(@com.google.android.play.core.splitinstall.model.SplitInstallSessionStatus int status, long bytesDownloaded, long bytesTotal);
+  }
+
+  public final class DefaultProgressFragment extends androidx.navigation.dynamicfeatures.fragment.ui.AbstractProgressFragment {
+    ctor public DefaultProgressFragment();
+    method protected void onCancelled();
+    method protected void onFailed(@com.google.android.play.core.splitinstall.model.SplitInstallErrorCode int errorCode);
+    method protected void onProgress(int status, long bytesDownloaded, long bytesTotal);
+  }
+
+}
+
diff --git a/navigation/navigation-dynamic-features-runtime/api/2.8.0-beta04.txt b/navigation/navigation-dynamic-features-runtime/api/2.8.0-beta04.txt
new file mode 100644
index 0000000..2761db9
--- /dev/null
+++ b/navigation/navigation-dynamic-features-runtime/api/2.8.0-beta04.txt
@@ -0,0 +1,169 @@
+// Signature format: 4.0
+package androidx.navigation.dynamicfeatures {
+
+  @androidx.navigation.Navigator.Name("activity") public final class DynamicActivityNavigator extends androidx.navigation.ActivityNavigator {
+    ctor public DynamicActivityNavigator(android.content.Context context, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
+    method public androidx.navigation.dynamicfeatures.DynamicActivityNavigator.Destination createDestination();
+  }
+
+  public static final class DynamicActivityNavigator.Destination extends androidx.navigation.ActivityNavigator.Destination {
+    ctor public DynamicActivityNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.ActivityNavigator.Destination> activityNavigator);
+    ctor public DynamicActivityNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public String? getModuleName();
+    method public void setModuleName(String?);
+    property public final String? moduleName;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DynamicActivityNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.ActivityNavigator.Destination> {
+    ctor @Deprecated public DynamicActivityNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.DynamicActivityNavigator activityNavigator, @IdRes int id);
+    ctor public DynamicActivityNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.DynamicActivityNavigator activityNavigator, String route);
+    ctor public DynamicActivityNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.DynamicActivityNavigator activityNavigator, kotlin.reflect.KClass<? extends java.lang.Object?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public androidx.navigation.dynamicfeatures.DynamicActivityNavigator.Destination build();
+    method public String? getAction();
+    method public String? getActivityClassName();
+    method public android.net.Uri? getData();
+    method public String? getDataPattern();
+    method public String? getModuleName();
+    method public String? getTargetPackage();
+    method public void setAction(String?);
+    method public void setActivityClassName(String?);
+    method public void setData(android.net.Uri?);
+    method public void setDataPattern(String?);
+    method public void setModuleName(String?);
+    method public void setTargetPackage(String?);
+    property public final String? action;
+    property public final String? activityClassName;
+    property public final android.net.Uri? data;
+    property public final String? dataPattern;
+    property public final String? moduleName;
+    property public final String? targetPackage;
+  }
+
+  public final class DynamicActivityNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline void activity(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline void activity(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void activity(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+  }
+
+  public final class DynamicExtras implements androidx.navigation.Navigator.Extras {
+    ctor public DynamicExtras();
+    ctor public DynamicExtras(optional androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor);
+    ctor public DynamicExtras(optional androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor, optional androidx.navigation.Navigator.Extras? destinationExtras);
+    method public androidx.navigation.Navigator.Extras? getDestinationExtras();
+    method public androidx.navigation.dynamicfeatures.DynamicInstallMonitor? getInstallMonitor();
+    property public final androidx.navigation.Navigator.Extras? destinationExtras;
+    property public final androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor;
+  }
+
+  @androidx.navigation.Navigator.Name("navigation") public final class DynamicGraphNavigator extends androidx.navigation.NavGraphNavigator {
+    ctor public DynamicGraphNavigator(androidx.navigation.NavigatorProvider navigatorProvider, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
+    method public androidx.navigation.dynamicfeatures.DynamicGraphNavigator.DynamicNavGraph createDestination();
+    method public void installDefaultProgressDestination(kotlin.jvm.functions.Function0<? extends androidx.navigation.NavDestination> progressDestinationSupplier);
+  }
+
+  public static final class DynamicGraphNavigator.DynamicNavGraph extends androidx.navigation.NavGraph {
+    ctor public DynamicGraphNavigator.DynamicNavGraph(androidx.navigation.dynamicfeatures.DynamicGraphNavigator navGraphNavigator, androidx.navigation.NavigatorProvider navigatorProvider);
+    method public String? getModuleName();
+    method public int getProgressDestination();
+    method public void setModuleName(String?);
+    method public void setProgressDestination(int);
+    property public final String? moduleName;
+    property public final int progressDestination;
+  }
+
+  @androidx.navigation.Navigator.Name("include-dynamic") public final class DynamicIncludeGraphNavigator extends androidx.navigation.Navigator<androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator.DynamicIncludeNavGraph> {
+    ctor public DynamicIncludeGraphNavigator(android.content.Context context, androidx.navigation.NavigatorProvider navigatorProvider, androidx.navigation.NavInflater navInflater, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
+    method public androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator.DynamicIncludeNavGraph createDestination();
+  }
+
+  public static final class DynamicIncludeGraphNavigator.DynamicIncludeNavGraph extends androidx.navigation.NavDestination {
+    method public String? getGraphPackage();
+    method public String? getGraphResourceName();
+    method public String? getModuleName();
+    method public void setGraphPackage(String?);
+    method public void setGraphResourceName(String?);
+    method public void setModuleName(String?);
+    property public final String? graphPackage;
+    property public final String? graphResourceName;
+    property public final String? moduleName;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DynamicIncludeNavGraphBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator.DynamicIncludeNavGraph> {
+    ctor @Deprecated public DynamicIncludeNavGraphBuilder(androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator dynamicIncludeGraphNavigator, @IdRes int id, String moduleName, String graphResourceName);
+    ctor public DynamicIncludeNavGraphBuilder(androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator dynamicIncludeGraphNavigator, String route, String moduleName, String graphResourceName);
+    ctor public DynamicIncludeNavGraphBuilder(androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator dynamicIncludeGraphNavigator, kotlin.reflect.KClass<? extends java.lang.Object?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, String moduleName, String graphResourceName);
+    method public androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator.DynamicIncludeNavGraph build();
+    method public String? getGraphPackage();
+    method public void setGraphPackage(String?);
+    property public final String? graphPackage;
+  }
+
+  public final class DynamicIncludeNavGraphBuilderKt {
+    method @Deprecated public static inline void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, String moduleName, String graphResourceName);
+    method @Deprecated public static inline void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, String moduleName, String graphResourceName, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicIncludeNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, String moduleName, String graphResourceName);
+    method public static inline void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, String moduleName, String graphResourceName, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicIncludeNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String moduleName, String graphResourceName, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public static inline <reified T> void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String moduleName, String graphResourceName, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicIncludeNavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public class DynamicInstallManager {
+    ctor public DynamicInstallManager(android.content.Context context, com.google.android.play.core.splitinstall.SplitInstallManager splitInstallManager);
+  }
+
+  public final class DynamicInstallMonitor {
+    ctor public DynamicInstallMonitor();
+    method public void cancelInstall();
+    method public Exception? getException();
+    method public int getSessionId();
+    method public androidx.lifecycle.LiveData<com.google.android.play.core.splitinstall.SplitInstallSessionState> getStatus();
+    method public boolean isInstallRequired();
+    property public final Exception? exception;
+    property public final boolean isInstallRequired;
+    property public final int sessionId;
+    property public final androidx.lifecycle.LiveData<com.google.android.play.core.splitinstall.SplitInstallSessionState> status;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DynamicNavGraphBuilder extends androidx.navigation.NavGraphBuilder {
+    ctor @Deprecated public DynamicNavGraphBuilder(androidx.navigation.NavigatorProvider provider, @IdRes int id, @IdRes int startDestination);
+    ctor public DynamicNavGraphBuilder(androidx.navigation.NavigatorProvider provider, Object startDestination, kotlin.reflect.KClass<? extends java.lang.Object?>? route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    ctor public DynamicNavGraphBuilder(androidx.navigation.NavigatorProvider provider, String startDestination, optional String? route);
+    ctor public DynamicNavGraphBuilder(androidx.navigation.NavigatorProvider provider, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, kotlin.reflect.KClass<? extends java.lang.Object?>? route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public String? getModuleName();
+    method public int getProgressDestination();
+    method public String? getProgressDestinationRoute();
+    method public void setModuleName(String?);
+    method public void setProgressDestination(int);
+    method public void setProgressDestinationRoute(String?);
+    property public final String? moduleName;
+    property public final int progressDestination;
+    property public final String? progressDestinationRoute;
+  }
+
+  public final class DynamicNavGraphBuilderKt {
+    method @Deprecated public static inline void navigation(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void navigation(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, Object startDestination, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline void navigation(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String startDestination, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void navigation(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, Object startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavControllerKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, Object startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavHostKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, Object startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+  }
+
+}
+
diff --git a/navigation/navigation-dynamic-features-runtime/api/2.8.0-beta05.txt b/navigation/navigation-dynamic-features-runtime/api/2.8.0-beta05.txt
new file mode 100644
index 0000000..2761db9
--- /dev/null
+++ b/navigation/navigation-dynamic-features-runtime/api/2.8.0-beta05.txt
@@ -0,0 +1,169 @@
+// Signature format: 4.0
+package androidx.navigation.dynamicfeatures {
+
+  @androidx.navigation.Navigator.Name("activity") public final class DynamicActivityNavigator extends androidx.navigation.ActivityNavigator {
+    ctor public DynamicActivityNavigator(android.content.Context context, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
+    method public androidx.navigation.dynamicfeatures.DynamicActivityNavigator.Destination createDestination();
+  }
+
+  public static final class DynamicActivityNavigator.Destination extends androidx.navigation.ActivityNavigator.Destination {
+    ctor public DynamicActivityNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.ActivityNavigator.Destination> activityNavigator);
+    ctor public DynamicActivityNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public String? getModuleName();
+    method public void setModuleName(String?);
+    property public final String? moduleName;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DynamicActivityNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.ActivityNavigator.Destination> {
+    ctor @Deprecated public DynamicActivityNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.DynamicActivityNavigator activityNavigator, @IdRes int id);
+    ctor public DynamicActivityNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.DynamicActivityNavigator activityNavigator, String route);
+    ctor public DynamicActivityNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.DynamicActivityNavigator activityNavigator, kotlin.reflect.KClass<? extends java.lang.Object?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public androidx.navigation.dynamicfeatures.DynamicActivityNavigator.Destination build();
+    method public String? getAction();
+    method public String? getActivityClassName();
+    method public android.net.Uri? getData();
+    method public String? getDataPattern();
+    method public String? getModuleName();
+    method public String? getTargetPackage();
+    method public void setAction(String?);
+    method public void setActivityClassName(String?);
+    method public void setData(android.net.Uri?);
+    method public void setDataPattern(String?);
+    method public void setModuleName(String?);
+    method public void setTargetPackage(String?);
+    property public final String? action;
+    property public final String? activityClassName;
+    property public final android.net.Uri? data;
+    property public final String? dataPattern;
+    property public final String? moduleName;
+    property public final String? targetPackage;
+  }
+
+  public final class DynamicActivityNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline void activity(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline void activity(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void activity(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+  }
+
+  public final class DynamicExtras implements androidx.navigation.Navigator.Extras {
+    ctor public DynamicExtras();
+    ctor public DynamicExtras(optional androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor);
+    ctor public DynamicExtras(optional androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor, optional androidx.navigation.Navigator.Extras? destinationExtras);
+    method public androidx.navigation.Navigator.Extras? getDestinationExtras();
+    method public androidx.navigation.dynamicfeatures.DynamicInstallMonitor? getInstallMonitor();
+    property public final androidx.navigation.Navigator.Extras? destinationExtras;
+    property public final androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor;
+  }
+
+  @androidx.navigation.Navigator.Name("navigation") public final class DynamicGraphNavigator extends androidx.navigation.NavGraphNavigator {
+    ctor public DynamicGraphNavigator(androidx.navigation.NavigatorProvider navigatorProvider, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
+    method public androidx.navigation.dynamicfeatures.DynamicGraphNavigator.DynamicNavGraph createDestination();
+    method public void installDefaultProgressDestination(kotlin.jvm.functions.Function0<? extends androidx.navigation.NavDestination> progressDestinationSupplier);
+  }
+
+  public static final class DynamicGraphNavigator.DynamicNavGraph extends androidx.navigation.NavGraph {
+    ctor public DynamicGraphNavigator.DynamicNavGraph(androidx.navigation.dynamicfeatures.DynamicGraphNavigator navGraphNavigator, androidx.navigation.NavigatorProvider navigatorProvider);
+    method public String? getModuleName();
+    method public int getProgressDestination();
+    method public void setModuleName(String?);
+    method public void setProgressDestination(int);
+    property public final String? moduleName;
+    property public final int progressDestination;
+  }
+
+  @androidx.navigation.Navigator.Name("include-dynamic") public final class DynamicIncludeGraphNavigator extends androidx.navigation.Navigator<androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator.DynamicIncludeNavGraph> {
+    ctor public DynamicIncludeGraphNavigator(android.content.Context context, androidx.navigation.NavigatorProvider navigatorProvider, androidx.navigation.NavInflater navInflater, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
+    method public androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator.DynamicIncludeNavGraph createDestination();
+  }
+
+  public static final class DynamicIncludeGraphNavigator.DynamicIncludeNavGraph extends androidx.navigation.NavDestination {
+    method public String? getGraphPackage();
+    method public String? getGraphResourceName();
+    method public String? getModuleName();
+    method public void setGraphPackage(String?);
+    method public void setGraphResourceName(String?);
+    method public void setModuleName(String?);
+    property public final String? graphPackage;
+    property public final String? graphResourceName;
+    property public final String? moduleName;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DynamicIncludeNavGraphBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator.DynamicIncludeNavGraph> {
+    ctor @Deprecated public DynamicIncludeNavGraphBuilder(androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator dynamicIncludeGraphNavigator, @IdRes int id, String moduleName, String graphResourceName);
+    ctor public DynamicIncludeNavGraphBuilder(androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator dynamicIncludeGraphNavigator, String route, String moduleName, String graphResourceName);
+    ctor public DynamicIncludeNavGraphBuilder(androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator dynamicIncludeGraphNavigator, kotlin.reflect.KClass<? extends java.lang.Object?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, String moduleName, String graphResourceName);
+    method public androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator.DynamicIncludeNavGraph build();
+    method public String? getGraphPackage();
+    method public void setGraphPackage(String?);
+    property public final String? graphPackage;
+  }
+
+  public final class DynamicIncludeNavGraphBuilderKt {
+    method @Deprecated public static inline void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, String moduleName, String graphResourceName);
+    method @Deprecated public static inline void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, String moduleName, String graphResourceName, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicIncludeNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, String moduleName, String graphResourceName);
+    method public static inline void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, String moduleName, String graphResourceName, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicIncludeNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String moduleName, String graphResourceName, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public static inline <reified T> void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String moduleName, String graphResourceName, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicIncludeNavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public class DynamicInstallManager {
+    ctor public DynamicInstallManager(android.content.Context context, com.google.android.play.core.splitinstall.SplitInstallManager splitInstallManager);
+  }
+
+  public final class DynamicInstallMonitor {
+    ctor public DynamicInstallMonitor();
+    method public void cancelInstall();
+    method public Exception? getException();
+    method public int getSessionId();
+    method public androidx.lifecycle.LiveData<com.google.android.play.core.splitinstall.SplitInstallSessionState> getStatus();
+    method public boolean isInstallRequired();
+    property public final Exception? exception;
+    property public final boolean isInstallRequired;
+    property public final int sessionId;
+    property public final androidx.lifecycle.LiveData<com.google.android.play.core.splitinstall.SplitInstallSessionState> status;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DynamicNavGraphBuilder extends androidx.navigation.NavGraphBuilder {
+    ctor @Deprecated public DynamicNavGraphBuilder(androidx.navigation.NavigatorProvider provider, @IdRes int id, @IdRes int startDestination);
+    ctor public DynamicNavGraphBuilder(androidx.navigation.NavigatorProvider provider, Object startDestination, kotlin.reflect.KClass<? extends java.lang.Object?>? route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    ctor public DynamicNavGraphBuilder(androidx.navigation.NavigatorProvider provider, String startDestination, optional String? route);
+    ctor public DynamicNavGraphBuilder(androidx.navigation.NavigatorProvider provider, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, kotlin.reflect.KClass<? extends java.lang.Object?>? route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public String? getModuleName();
+    method public int getProgressDestination();
+    method public String? getProgressDestinationRoute();
+    method public void setModuleName(String?);
+    method public void setProgressDestination(int);
+    method public void setProgressDestinationRoute(String?);
+    property public final String? moduleName;
+    property public final int progressDestination;
+    property public final String? progressDestinationRoute;
+  }
+
+  public final class DynamicNavGraphBuilderKt {
+    method @Deprecated public static inline void navigation(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void navigation(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, Object startDestination, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline void navigation(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String startDestination, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void navigation(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, Object startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavControllerKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, Object startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavHostKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, Object startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+  }
+
+}
+
diff --git a/navigation/navigation-dynamic-features-runtime/api/res-2.8.0-beta04.txt b/navigation/navigation-dynamic-features-runtime/api/res-2.8.0-beta04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-dynamic-features-runtime/api/res-2.8.0-beta04.txt
diff --git a/navigation/navigation-dynamic-features-runtime/api/res-2.8.0-beta05.txt b/navigation/navigation-dynamic-features-runtime/api/res-2.8.0-beta05.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-dynamic-features-runtime/api/res-2.8.0-beta05.txt
diff --git a/navigation/navigation-dynamic-features-runtime/api/restricted_2.8.0-beta04.txt b/navigation/navigation-dynamic-features-runtime/api/restricted_2.8.0-beta04.txt
new file mode 100644
index 0000000..2761db9
--- /dev/null
+++ b/navigation/navigation-dynamic-features-runtime/api/restricted_2.8.0-beta04.txt
@@ -0,0 +1,169 @@
+// Signature format: 4.0
+package androidx.navigation.dynamicfeatures {
+
+  @androidx.navigation.Navigator.Name("activity") public final class DynamicActivityNavigator extends androidx.navigation.ActivityNavigator {
+    ctor public DynamicActivityNavigator(android.content.Context context, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
+    method public androidx.navigation.dynamicfeatures.DynamicActivityNavigator.Destination createDestination();
+  }
+
+  public static final class DynamicActivityNavigator.Destination extends androidx.navigation.ActivityNavigator.Destination {
+    ctor public DynamicActivityNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.ActivityNavigator.Destination> activityNavigator);
+    ctor public DynamicActivityNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public String? getModuleName();
+    method public void setModuleName(String?);
+    property public final String? moduleName;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DynamicActivityNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.ActivityNavigator.Destination> {
+    ctor @Deprecated public DynamicActivityNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.DynamicActivityNavigator activityNavigator, @IdRes int id);
+    ctor public DynamicActivityNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.DynamicActivityNavigator activityNavigator, String route);
+    ctor public DynamicActivityNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.DynamicActivityNavigator activityNavigator, kotlin.reflect.KClass<? extends java.lang.Object?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public androidx.navigation.dynamicfeatures.DynamicActivityNavigator.Destination build();
+    method public String? getAction();
+    method public String? getActivityClassName();
+    method public android.net.Uri? getData();
+    method public String? getDataPattern();
+    method public String? getModuleName();
+    method public String? getTargetPackage();
+    method public void setAction(String?);
+    method public void setActivityClassName(String?);
+    method public void setData(android.net.Uri?);
+    method public void setDataPattern(String?);
+    method public void setModuleName(String?);
+    method public void setTargetPackage(String?);
+    property public final String? action;
+    property public final String? activityClassName;
+    property public final android.net.Uri? data;
+    property public final String? dataPattern;
+    property public final String? moduleName;
+    property public final String? targetPackage;
+  }
+
+  public final class DynamicActivityNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline void activity(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline void activity(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void activity(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+  }
+
+  public final class DynamicExtras implements androidx.navigation.Navigator.Extras {
+    ctor public DynamicExtras();
+    ctor public DynamicExtras(optional androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor);
+    ctor public DynamicExtras(optional androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor, optional androidx.navigation.Navigator.Extras? destinationExtras);
+    method public androidx.navigation.Navigator.Extras? getDestinationExtras();
+    method public androidx.navigation.dynamicfeatures.DynamicInstallMonitor? getInstallMonitor();
+    property public final androidx.navigation.Navigator.Extras? destinationExtras;
+    property public final androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor;
+  }
+
+  @androidx.navigation.Navigator.Name("navigation") public final class DynamicGraphNavigator extends androidx.navigation.NavGraphNavigator {
+    ctor public DynamicGraphNavigator(androidx.navigation.NavigatorProvider navigatorProvider, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
+    method public androidx.navigation.dynamicfeatures.DynamicGraphNavigator.DynamicNavGraph createDestination();
+    method public void installDefaultProgressDestination(kotlin.jvm.functions.Function0<? extends androidx.navigation.NavDestination> progressDestinationSupplier);
+  }
+
+  public static final class DynamicGraphNavigator.DynamicNavGraph extends androidx.navigation.NavGraph {
+    ctor public DynamicGraphNavigator.DynamicNavGraph(androidx.navigation.dynamicfeatures.DynamicGraphNavigator navGraphNavigator, androidx.navigation.NavigatorProvider navigatorProvider);
+    method public String? getModuleName();
+    method public int getProgressDestination();
+    method public void setModuleName(String?);
+    method public void setProgressDestination(int);
+    property public final String? moduleName;
+    property public final int progressDestination;
+  }
+
+  @androidx.navigation.Navigator.Name("include-dynamic") public final class DynamicIncludeGraphNavigator extends androidx.navigation.Navigator<androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator.DynamicIncludeNavGraph> {
+    ctor public DynamicIncludeGraphNavigator(android.content.Context context, androidx.navigation.NavigatorProvider navigatorProvider, androidx.navigation.NavInflater navInflater, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
+    method public androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator.DynamicIncludeNavGraph createDestination();
+  }
+
+  public static final class DynamicIncludeGraphNavigator.DynamicIncludeNavGraph extends androidx.navigation.NavDestination {
+    method public String? getGraphPackage();
+    method public String? getGraphResourceName();
+    method public String? getModuleName();
+    method public void setGraphPackage(String?);
+    method public void setGraphResourceName(String?);
+    method public void setModuleName(String?);
+    property public final String? graphPackage;
+    property public final String? graphResourceName;
+    property public final String? moduleName;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DynamicIncludeNavGraphBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator.DynamicIncludeNavGraph> {
+    ctor @Deprecated public DynamicIncludeNavGraphBuilder(androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator dynamicIncludeGraphNavigator, @IdRes int id, String moduleName, String graphResourceName);
+    ctor public DynamicIncludeNavGraphBuilder(androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator dynamicIncludeGraphNavigator, String route, String moduleName, String graphResourceName);
+    ctor public DynamicIncludeNavGraphBuilder(androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator dynamicIncludeGraphNavigator, kotlin.reflect.KClass<? extends java.lang.Object?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, String moduleName, String graphResourceName);
+    method public androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator.DynamicIncludeNavGraph build();
+    method public String? getGraphPackage();
+    method public void setGraphPackage(String?);
+    property public final String? graphPackage;
+  }
+
+  public final class DynamicIncludeNavGraphBuilderKt {
+    method @Deprecated public static inline void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, String moduleName, String graphResourceName);
+    method @Deprecated public static inline void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, String moduleName, String graphResourceName, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicIncludeNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, String moduleName, String graphResourceName);
+    method public static inline void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, String moduleName, String graphResourceName, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicIncludeNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String moduleName, String graphResourceName, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public static inline <reified T> void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String moduleName, String graphResourceName, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicIncludeNavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public class DynamicInstallManager {
+    ctor public DynamicInstallManager(android.content.Context context, com.google.android.play.core.splitinstall.SplitInstallManager splitInstallManager);
+  }
+
+  public final class DynamicInstallMonitor {
+    ctor public DynamicInstallMonitor();
+    method public void cancelInstall();
+    method public Exception? getException();
+    method public int getSessionId();
+    method public androidx.lifecycle.LiveData<com.google.android.play.core.splitinstall.SplitInstallSessionState> getStatus();
+    method public boolean isInstallRequired();
+    property public final Exception? exception;
+    property public final boolean isInstallRequired;
+    property public final int sessionId;
+    property public final androidx.lifecycle.LiveData<com.google.android.play.core.splitinstall.SplitInstallSessionState> status;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DynamicNavGraphBuilder extends androidx.navigation.NavGraphBuilder {
+    ctor @Deprecated public DynamicNavGraphBuilder(androidx.navigation.NavigatorProvider provider, @IdRes int id, @IdRes int startDestination);
+    ctor public DynamicNavGraphBuilder(androidx.navigation.NavigatorProvider provider, Object startDestination, kotlin.reflect.KClass<? extends java.lang.Object?>? route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    ctor public DynamicNavGraphBuilder(androidx.navigation.NavigatorProvider provider, String startDestination, optional String? route);
+    ctor public DynamicNavGraphBuilder(androidx.navigation.NavigatorProvider provider, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, kotlin.reflect.KClass<? extends java.lang.Object?>? route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public String? getModuleName();
+    method public int getProgressDestination();
+    method public String? getProgressDestinationRoute();
+    method public void setModuleName(String?);
+    method public void setProgressDestination(int);
+    method public void setProgressDestinationRoute(String?);
+    property public final String? moduleName;
+    property public final int progressDestination;
+    property public final String? progressDestinationRoute;
+  }
+
+  public final class DynamicNavGraphBuilderKt {
+    method @Deprecated public static inline void navigation(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void navigation(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, Object startDestination, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline void navigation(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String startDestination, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void navigation(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, Object startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavControllerKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, Object startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavHostKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, Object startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+  }
+
+}
+
diff --git a/navigation/navigation-dynamic-features-runtime/api/restricted_2.8.0-beta05.txt b/navigation/navigation-dynamic-features-runtime/api/restricted_2.8.0-beta05.txt
new file mode 100644
index 0000000..2761db9
--- /dev/null
+++ b/navigation/navigation-dynamic-features-runtime/api/restricted_2.8.0-beta05.txt
@@ -0,0 +1,169 @@
+// Signature format: 4.0
+package androidx.navigation.dynamicfeatures {
+
+  @androidx.navigation.Navigator.Name("activity") public final class DynamicActivityNavigator extends androidx.navigation.ActivityNavigator {
+    ctor public DynamicActivityNavigator(android.content.Context context, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
+    method public androidx.navigation.dynamicfeatures.DynamicActivityNavigator.Destination createDestination();
+  }
+
+  public static final class DynamicActivityNavigator.Destination extends androidx.navigation.ActivityNavigator.Destination {
+    ctor public DynamicActivityNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.ActivityNavigator.Destination> activityNavigator);
+    ctor public DynamicActivityNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public String? getModuleName();
+    method public void setModuleName(String?);
+    property public final String? moduleName;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DynamicActivityNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.ActivityNavigator.Destination> {
+    ctor @Deprecated public DynamicActivityNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.DynamicActivityNavigator activityNavigator, @IdRes int id);
+    ctor public DynamicActivityNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.DynamicActivityNavigator activityNavigator, String route);
+    ctor public DynamicActivityNavigatorDestinationBuilder(androidx.navigation.dynamicfeatures.DynamicActivityNavigator activityNavigator, kotlin.reflect.KClass<? extends java.lang.Object?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public androidx.navigation.dynamicfeatures.DynamicActivityNavigator.Destination build();
+    method public String? getAction();
+    method public String? getActivityClassName();
+    method public android.net.Uri? getData();
+    method public String? getDataPattern();
+    method public String? getModuleName();
+    method public String? getTargetPackage();
+    method public void setAction(String?);
+    method public void setActivityClassName(String?);
+    method public void setData(android.net.Uri?);
+    method public void setDataPattern(String?);
+    method public void setModuleName(String?);
+    method public void setTargetPackage(String?);
+    property public final String? action;
+    property public final String? activityClassName;
+    property public final android.net.Uri? data;
+    property public final String? dataPattern;
+    property public final String? moduleName;
+    property public final String? targetPackage;
+  }
+
+  public final class DynamicActivityNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline void activity(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline void activity(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void activity(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+  }
+
+  public final class DynamicExtras implements androidx.navigation.Navigator.Extras {
+    ctor public DynamicExtras();
+    ctor public DynamicExtras(optional androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor);
+    ctor public DynamicExtras(optional androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor, optional androidx.navigation.Navigator.Extras? destinationExtras);
+    method public androidx.navigation.Navigator.Extras? getDestinationExtras();
+    method public androidx.navigation.dynamicfeatures.DynamicInstallMonitor? getInstallMonitor();
+    property public final androidx.navigation.Navigator.Extras? destinationExtras;
+    property public final androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor;
+  }
+
+  @androidx.navigation.Navigator.Name("navigation") public final class DynamicGraphNavigator extends androidx.navigation.NavGraphNavigator {
+    ctor public DynamicGraphNavigator(androidx.navigation.NavigatorProvider navigatorProvider, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
+    method public androidx.navigation.dynamicfeatures.DynamicGraphNavigator.DynamicNavGraph createDestination();
+    method public void installDefaultProgressDestination(kotlin.jvm.functions.Function0<? extends androidx.navigation.NavDestination> progressDestinationSupplier);
+  }
+
+  public static final class DynamicGraphNavigator.DynamicNavGraph extends androidx.navigation.NavGraph {
+    ctor public DynamicGraphNavigator.DynamicNavGraph(androidx.navigation.dynamicfeatures.DynamicGraphNavigator navGraphNavigator, androidx.navigation.NavigatorProvider navigatorProvider);
+    method public String? getModuleName();
+    method public int getProgressDestination();
+    method public void setModuleName(String?);
+    method public void setProgressDestination(int);
+    property public final String? moduleName;
+    property public final int progressDestination;
+  }
+
+  @androidx.navigation.Navigator.Name("include-dynamic") public final class DynamicIncludeGraphNavigator extends androidx.navigation.Navigator<androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator.DynamicIncludeNavGraph> {
+    ctor public DynamicIncludeGraphNavigator(android.content.Context context, androidx.navigation.NavigatorProvider navigatorProvider, androidx.navigation.NavInflater navInflater, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
+    method public androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator.DynamicIncludeNavGraph createDestination();
+  }
+
+  public static final class DynamicIncludeGraphNavigator.DynamicIncludeNavGraph extends androidx.navigation.NavDestination {
+    method public String? getGraphPackage();
+    method public String? getGraphResourceName();
+    method public String? getModuleName();
+    method public void setGraphPackage(String?);
+    method public void setGraphResourceName(String?);
+    method public void setModuleName(String?);
+    property public final String? graphPackage;
+    property public final String? graphResourceName;
+    property public final String? moduleName;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DynamicIncludeNavGraphBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator.DynamicIncludeNavGraph> {
+    ctor @Deprecated public DynamicIncludeNavGraphBuilder(androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator dynamicIncludeGraphNavigator, @IdRes int id, String moduleName, String graphResourceName);
+    ctor public DynamicIncludeNavGraphBuilder(androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator dynamicIncludeGraphNavigator, String route, String moduleName, String graphResourceName);
+    ctor public DynamicIncludeNavGraphBuilder(androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator dynamicIncludeGraphNavigator, kotlin.reflect.KClass<? extends java.lang.Object?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, String moduleName, String graphResourceName);
+    method public androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator.DynamicIncludeNavGraph build();
+    method public String? getGraphPackage();
+    method public void setGraphPackage(String?);
+    property public final String? graphPackage;
+  }
+
+  public final class DynamicIncludeNavGraphBuilderKt {
+    method @Deprecated public static inline void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, String moduleName, String graphResourceName);
+    method @Deprecated public static inline void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, String moduleName, String graphResourceName, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicIncludeNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, String moduleName, String graphResourceName);
+    method public static inline void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String route, String moduleName, String graphResourceName, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicIncludeNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String moduleName, String graphResourceName, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public static inline <reified T> void includeDynamic(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String moduleName, String graphResourceName, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicIncludeNavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public class DynamicInstallManager {
+    ctor public DynamicInstallManager(android.content.Context context, com.google.android.play.core.splitinstall.SplitInstallManager splitInstallManager);
+  }
+
+  public final class DynamicInstallMonitor {
+    ctor public DynamicInstallMonitor();
+    method public void cancelInstall();
+    method public Exception? getException();
+    method public int getSessionId();
+    method public androidx.lifecycle.LiveData<com.google.android.play.core.splitinstall.SplitInstallSessionState> getStatus();
+    method public boolean isInstallRequired();
+    property public final Exception? exception;
+    property public final boolean isInstallRequired;
+    property public final int sessionId;
+    property public final androidx.lifecycle.LiveData<com.google.android.play.core.splitinstall.SplitInstallSessionState> status;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DynamicNavGraphBuilder extends androidx.navigation.NavGraphBuilder {
+    ctor @Deprecated public DynamicNavGraphBuilder(androidx.navigation.NavigatorProvider provider, @IdRes int id, @IdRes int startDestination);
+    ctor public DynamicNavGraphBuilder(androidx.navigation.NavigatorProvider provider, Object startDestination, kotlin.reflect.KClass<? extends java.lang.Object?>? route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    ctor public DynamicNavGraphBuilder(androidx.navigation.NavigatorProvider provider, String startDestination, optional String? route);
+    ctor public DynamicNavGraphBuilder(androidx.navigation.NavigatorProvider provider, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, kotlin.reflect.KClass<? extends java.lang.Object?>? route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public String? getModuleName();
+    method public int getProgressDestination();
+    method public String? getProgressDestinationRoute();
+    method public void setModuleName(String?);
+    method public void setProgressDestination(int);
+    method public void setProgressDestinationRoute(String?);
+    property public final String? moduleName;
+    property public final int progressDestination;
+    property public final String? progressDestinationRoute;
+  }
+
+  public final class DynamicNavGraphBuilderKt {
+    method @Deprecated public static inline void navigation(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void navigation(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, Object startDestination, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline void navigation(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, String startDestination, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void navigation(androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method @Deprecated public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, Object startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph navigation(androidx.navigation.NavigatorProvider, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavControllerKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, Object startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavHostKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, Object startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.dynamicfeatures.DynamicNavGraphBuilder,kotlin.Unit> builder);
+  }
+
+}
+
diff --git a/navigation/navigation-fragment-compose/api/2.8.0-beta04.txt b/navigation/navigation-fragment-compose/api/2.8.0-beta04.txt
new file mode 100644
index 0000000..d598ace
--- /dev/null
+++ b/navigation/navigation-fragment-compose/api/2.8.0-beta04.txt
@@ -0,0 +1,37 @@
+// Signature format: 4.0
+package androidx.navigation.fragment.compose {
+
+  public final class ComposableFragment extends androidx.fragment.app.Fragment {
+    method public static androidx.navigation.fragment.compose.ComposableFragment ComposableFragment(String fullyQualifiedName);
+    field public static final androidx.navigation.fragment.compose.ComposableFragment.Companion Companion;
+  }
+
+  public static final class ComposableFragment.Companion {
+    method public androidx.navigation.fragment.compose.ComposableFragment ComposableFragment(String fullyQualifiedName);
+  }
+
+  @androidx.navigation.Navigator.Name("composable") public final class ComposableFragmentNavigator extends androidx.navigation.Navigator<androidx.navigation.fragment.FragmentNavigator.Destination> {
+    ctor public ComposableFragmentNavigator(androidx.navigation.fragment.FragmentNavigator fragmentNavigator);
+    ctor public ComposableFragmentNavigator(androidx.navigation.NavigatorProvider provider);
+    method public androidx.navigation.fragment.FragmentNavigator.Destination createDestination();
+  }
+
+  public class ComposableNavHostFragment extends androidx.navigation.fragment.NavHostFragment {
+    ctor public ComposableNavHostFragment();
+    method public static final androidx.navigation.fragment.compose.ComposableNavHostFragment create(@NavigationRes int graphResId);
+    method public static final androidx.navigation.fragment.compose.ComposableNavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+    field public static final androidx.navigation.fragment.compose.ComposableNavHostFragment.Companion Companion;
+  }
+
+  public static final class ComposableNavHostFragment.Companion {
+    method public androidx.navigation.fragment.compose.ComposableNavHostFragment create(@NavigationRes int graphResId);
+    method public androidx.navigation.fragment.compose.ComposableNavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+  }
+
+  public final class LocalFragmentKt {
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.fragment.app.Fragment> getLocalFragment();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.fragment.app.Fragment> LocalFragment;
+  }
+
+}
+
diff --git a/navigation/navigation-fragment-compose/api/2.8.0-beta05.txt b/navigation/navigation-fragment-compose/api/2.8.0-beta05.txt
new file mode 100644
index 0000000..d598ace
--- /dev/null
+++ b/navigation/navigation-fragment-compose/api/2.8.0-beta05.txt
@@ -0,0 +1,37 @@
+// Signature format: 4.0
+package androidx.navigation.fragment.compose {
+
+  public final class ComposableFragment extends androidx.fragment.app.Fragment {
+    method public static androidx.navigation.fragment.compose.ComposableFragment ComposableFragment(String fullyQualifiedName);
+    field public static final androidx.navigation.fragment.compose.ComposableFragment.Companion Companion;
+  }
+
+  public static final class ComposableFragment.Companion {
+    method public androidx.navigation.fragment.compose.ComposableFragment ComposableFragment(String fullyQualifiedName);
+  }
+
+  @androidx.navigation.Navigator.Name("composable") public final class ComposableFragmentNavigator extends androidx.navigation.Navigator<androidx.navigation.fragment.FragmentNavigator.Destination> {
+    ctor public ComposableFragmentNavigator(androidx.navigation.fragment.FragmentNavigator fragmentNavigator);
+    ctor public ComposableFragmentNavigator(androidx.navigation.NavigatorProvider provider);
+    method public androidx.navigation.fragment.FragmentNavigator.Destination createDestination();
+  }
+
+  public class ComposableNavHostFragment extends androidx.navigation.fragment.NavHostFragment {
+    ctor public ComposableNavHostFragment();
+    method public static final androidx.navigation.fragment.compose.ComposableNavHostFragment create(@NavigationRes int graphResId);
+    method public static final androidx.navigation.fragment.compose.ComposableNavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+    field public static final androidx.navigation.fragment.compose.ComposableNavHostFragment.Companion Companion;
+  }
+
+  public static final class ComposableNavHostFragment.Companion {
+    method public androidx.navigation.fragment.compose.ComposableNavHostFragment create(@NavigationRes int graphResId);
+    method public androidx.navigation.fragment.compose.ComposableNavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+  }
+
+  public final class LocalFragmentKt {
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.fragment.app.Fragment> getLocalFragment();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.fragment.app.Fragment> LocalFragment;
+  }
+
+}
+
diff --git a/navigation/navigation-fragment-compose/api/res-2.8.0-beta04.txt b/navigation/navigation-fragment-compose/api/res-2.8.0-beta04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-fragment-compose/api/res-2.8.0-beta04.txt
diff --git a/navigation/navigation-fragment-compose/api/res-2.8.0-beta05.txt b/navigation/navigation-fragment-compose/api/res-2.8.0-beta05.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-fragment-compose/api/res-2.8.0-beta05.txt
diff --git a/navigation/navigation-fragment-compose/api/restricted_2.8.0-beta04.txt b/navigation/navigation-fragment-compose/api/restricted_2.8.0-beta04.txt
new file mode 100644
index 0000000..d598ace
--- /dev/null
+++ b/navigation/navigation-fragment-compose/api/restricted_2.8.0-beta04.txt
@@ -0,0 +1,37 @@
+// Signature format: 4.0
+package androidx.navigation.fragment.compose {
+
+  public final class ComposableFragment extends androidx.fragment.app.Fragment {
+    method public static androidx.navigation.fragment.compose.ComposableFragment ComposableFragment(String fullyQualifiedName);
+    field public static final androidx.navigation.fragment.compose.ComposableFragment.Companion Companion;
+  }
+
+  public static final class ComposableFragment.Companion {
+    method public androidx.navigation.fragment.compose.ComposableFragment ComposableFragment(String fullyQualifiedName);
+  }
+
+  @androidx.navigation.Navigator.Name("composable") public final class ComposableFragmentNavigator extends androidx.navigation.Navigator<androidx.navigation.fragment.FragmentNavigator.Destination> {
+    ctor public ComposableFragmentNavigator(androidx.navigation.fragment.FragmentNavigator fragmentNavigator);
+    ctor public ComposableFragmentNavigator(androidx.navigation.NavigatorProvider provider);
+    method public androidx.navigation.fragment.FragmentNavigator.Destination createDestination();
+  }
+
+  public class ComposableNavHostFragment extends androidx.navigation.fragment.NavHostFragment {
+    ctor public ComposableNavHostFragment();
+    method public static final androidx.navigation.fragment.compose.ComposableNavHostFragment create(@NavigationRes int graphResId);
+    method public static final androidx.navigation.fragment.compose.ComposableNavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+    field public static final androidx.navigation.fragment.compose.ComposableNavHostFragment.Companion Companion;
+  }
+
+  public static final class ComposableNavHostFragment.Companion {
+    method public androidx.navigation.fragment.compose.ComposableNavHostFragment create(@NavigationRes int graphResId);
+    method public androidx.navigation.fragment.compose.ComposableNavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+  }
+
+  public final class LocalFragmentKt {
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.fragment.app.Fragment> getLocalFragment();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.fragment.app.Fragment> LocalFragment;
+  }
+
+}
+
diff --git a/navigation/navigation-fragment-compose/api/restricted_2.8.0-beta05.txt b/navigation/navigation-fragment-compose/api/restricted_2.8.0-beta05.txt
new file mode 100644
index 0000000..d598ace
--- /dev/null
+++ b/navigation/navigation-fragment-compose/api/restricted_2.8.0-beta05.txt
@@ -0,0 +1,37 @@
+// Signature format: 4.0
+package androidx.navigation.fragment.compose {
+
+  public final class ComposableFragment extends androidx.fragment.app.Fragment {
+    method public static androidx.navigation.fragment.compose.ComposableFragment ComposableFragment(String fullyQualifiedName);
+    field public static final androidx.navigation.fragment.compose.ComposableFragment.Companion Companion;
+  }
+
+  public static final class ComposableFragment.Companion {
+    method public androidx.navigation.fragment.compose.ComposableFragment ComposableFragment(String fullyQualifiedName);
+  }
+
+  @androidx.navigation.Navigator.Name("composable") public final class ComposableFragmentNavigator extends androidx.navigation.Navigator<androidx.navigation.fragment.FragmentNavigator.Destination> {
+    ctor public ComposableFragmentNavigator(androidx.navigation.fragment.FragmentNavigator fragmentNavigator);
+    ctor public ComposableFragmentNavigator(androidx.navigation.NavigatorProvider provider);
+    method public androidx.navigation.fragment.FragmentNavigator.Destination createDestination();
+  }
+
+  public class ComposableNavHostFragment extends androidx.navigation.fragment.NavHostFragment {
+    ctor public ComposableNavHostFragment();
+    method public static final androidx.navigation.fragment.compose.ComposableNavHostFragment create(@NavigationRes int graphResId);
+    method public static final androidx.navigation.fragment.compose.ComposableNavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+    field public static final androidx.navigation.fragment.compose.ComposableNavHostFragment.Companion Companion;
+  }
+
+  public static final class ComposableNavHostFragment.Companion {
+    method public androidx.navigation.fragment.compose.ComposableNavHostFragment create(@NavigationRes int graphResId);
+    method public androidx.navigation.fragment.compose.ComposableNavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+  }
+
+  public final class LocalFragmentKt {
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.fragment.app.Fragment> getLocalFragment();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.fragment.app.Fragment> LocalFragment;
+  }
+
+}
+
diff --git a/navigation/navigation-fragment-ktx/api/2.8.0-beta04.txt b/navigation/navigation-fragment-ktx/api/2.8.0-beta04.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/navigation/navigation-fragment-ktx/api/2.8.0-beta04.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/navigation/navigation-fragment-ktx/api/2.8.0-beta05.txt b/navigation/navigation-fragment-ktx/api/2.8.0-beta05.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/navigation/navigation-fragment-ktx/api/2.8.0-beta05.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/navigation/navigation-fragment-ktx/api/res-2.8.0-beta04.txt b/navigation/navigation-fragment-ktx/api/res-2.8.0-beta04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-fragment-ktx/api/res-2.8.0-beta04.txt
diff --git a/navigation/navigation-fragment-ktx/api/res-2.8.0-beta05.txt b/navigation/navigation-fragment-ktx/api/res-2.8.0-beta05.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-fragment-ktx/api/res-2.8.0-beta05.txt
diff --git a/navigation/navigation-fragment-ktx/api/restricted_2.8.0-beta04.txt b/navigation/navigation-fragment-ktx/api/restricted_2.8.0-beta04.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/navigation/navigation-fragment-ktx/api/restricted_2.8.0-beta04.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/navigation/navigation-fragment-ktx/api/restricted_2.8.0-beta05.txt b/navigation/navigation-fragment-ktx/api/restricted_2.8.0-beta05.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/navigation/navigation-fragment-ktx/api/restricted_2.8.0-beta05.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/navigation/navigation-fragment/api/2.8.0-beta04.txt b/navigation/navigation-fragment/api/2.8.0-beta04.txt
new file mode 100644
index 0000000..0db42b8
--- /dev/null
+++ b/navigation/navigation-fragment/api/2.8.0-beta04.txt
@@ -0,0 +1,131 @@
+// Signature format: 4.0
+package androidx.navigation {
+
+  public final class NavGraphViewModelLazyKt {
+    method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<VM> navGraphViewModels(androidx.fragment.app.Fragment, @IdRes int navGraphId, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras>? extrasProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @Deprecated @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<VM> navGraphViewModels(androidx.fragment.app.Fragment, @IdRes int navGraphId, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<VM> navGraphViewModels(androidx.fragment.app.Fragment, String navGraphRoute, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras>? extrasProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @Deprecated @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<VM> navGraphViewModels(androidx.fragment.app.Fragment, String navGraphRoute, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+  }
+
+}
+
+package androidx.navigation.fragment {
+
+  public abstract class AbstractListDetailFragment extends androidx.fragment.app.Fragment {
+    ctor public AbstractListDetailFragment();
+    method public final androidx.navigation.fragment.NavHostFragment getDetailPaneNavHostFragment();
+    method public final androidx.slidingpanelayout.widget.SlidingPaneLayout getSlidingPaneLayout();
+    method public androidx.navigation.fragment.NavHostFragment onCreateDetailPaneNavHostFragment();
+    method public abstract android.view.View onCreateListPaneView(android.view.LayoutInflater inflater, android.view.ViewGroup? container, android.os.Bundle? savedInstanceState);
+    method @CallSuper public final android.view.View onCreateView(android.view.LayoutInflater inflater, android.view.ViewGroup? container, android.os.Bundle? savedInstanceState);
+    method public void onListPaneViewCreated(android.view.View view, android.os.Bundle? savedInstanceState);
+    method @CallSuper public final void onViewCreated(android.view.View view, android.os.Bundle? savedInstanceState);
+    property public final androidx.navigation.fragment.NavHostFragment detailPaneNavHostFragment;
+    property public final androidx.slidingpanelayout.widget.SlidingPaneLayout slidingPaneLayout;
+  }
+
+  @androidx.navigation.Navigator.Name("dialog") public final class DialogFragmentNavigator extends androidx.navigation.Navigator<androidx.navigation.fragment.DialogFragmentNavigator.Destination> {
+    ctor public DialogFragmentNavigator(android.content.Context context, androidx.fragment.app.FragmentManager fragmentManager);
+    method public androidx.navigation.fragment.DialogFragmentNavigator.Destination createDestination();
+  }
+
+  @androidx.navigation.NavDestination.ClassType(DialogFragment::class) public static class DialogFragmentNavigator.Destination extends androidx.navigation.NavDestination implements androidx.navigation.FloatingWindow {
+    ctor public DialogFragmentNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.fragment.DialogFragmentNavigator.Destination> fragmentNavigator);
+    ctor public DialogFragmentNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public final String getClassName();
+    method public final androidx.navigation.fragment.DialogFragmentNavigator.Destination setClassName(String className);
+    property public final String className;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DialogFragmentNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.fragment.DialogFragmentNavigator.Destination> {
+    ctor @Deprecated public DialogFragmentNavigatorDestinationBuilder(androidx.navigation.fragment.DialogFragmentNavigator navigator, @IdRes int id, kotlin.reflect.KClass<? extends androidx.fragment.app.DialogFragment> fragmentClass);
+    ctor public DialogFragmentNavigatorDestinationBuilder(androidx.navigation.fragment.DialogFragmentNavigator navigator, String route, kotlin.reflect.KClass<? extends androidx.fragment.app.DialogFragment> fragmentClass);
+    ctor public DialogFragmentNavigatorDestinationBuilder(androidx.navigation.fragment.DialogFragmentNavigator navigator, kotlin.reflect.KClass<?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.reflect.KClass<? extends androidx.fragment.app.DialogFragment> fragmentClass);
+    method public androidx.navigation.fragment.DialogFragmentNavigator.Destination build();
+  }
+
+  public final class DialogFragmentNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.DialogFragment> void dialog(androidx.navigation.NavGraphBuilder, @IdRes int id);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.DialogFragment> void dialog(androidx.navigation.NavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.DialogFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.DialogFragment> void dialog(androidx.navigation.NavGraphBuilder, String route);
+    method public static inline <reified F extends androidx.fragment.app.DialogFragment> void dialog(androidx.navigation.NavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.DialogFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.DialogFragment, reified T> void dialog(androidx.navigation.NavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public static inline <reified F extends androidx.fragment.app.DialogFragment, reified T> void dialog(androidx.navigation.NavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.DialogFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+  }
+
+  public final class FragmentKt {
+    method public static androidx.navigation.NavController findNavController(androidx.fragment.app.Fragment);
+  }
+
+  public final class FragmentNavArgsLazyKt {
+    method @MainThread public static inline <reified Args extends androidx.navigation.NavArgs> androidx.navigation.NavArgsLazy<Args> navArgs(androidx.fragment.app.Fragment);
+  }
+
+  @androidx.navigation.Navigator.Name("fragment") public class FragmentNavigator extends androidx.navigation.Navigator<androidx.navigation.fragment.FragmentNavigator.Destination> {
+    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);
+  }
+
+  @androidx.navigation.NavDestination.ClassType(Fragment::class) public static class FragmentNavigator.Destination extends androidx.navigation.NavDestination {
+    ctor public FragmentNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.fragment.FragmentNavigator.Destination> fragmentNavigator);
+    ctor public FragmentNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public final String getClassName();
+    method public final androidx.navigation.fragment.FragmentNavigator.Destination setClassName(String className);
+    property public final String className;
+  }
+
+  public static final class FragmentNavigator.Extras implements androidx.navigation.Navigator.Extras {
+    method public java.util.Map<android.view.View,java.lang.String> getSharedElements();
+    property public final java.util.Map<android.view.View,java.lang.String> sharedElements;
+  }
+
+  public static final class FragmentNavigator.Extras.Builder {
+    ctor public FragmentNavigator.Extras.Builder();
+    method public androidx.navigation.fragment.FragmentNavigator.Extras.Builder addSharedElement(android.view.View sharedElement, String name);
+    method public androidx.navigation.fragment.FragmentNavigator.Extras.Builder addSharedElements(java.util.Map<android.view.View,java.lang.String> sharedElements);
+    method public androidx.navigation.fragment.FragmentNavigator.Extras build();
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class FragmentNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.fragment.FragmentNavigator.Destination> {
+    ctor @Deprecated public FragmentNavigatorDestinationBuilder(androidx.navigation.fragment.FragmentNavigator navigator, @IdRes int id, kotlin.reflect.KClass<? extends androidx.fragment.app.Fragment> fragmentClass);
+    ctor public FragmentNavigatorDestinationBuilder(androidx.navigation.fragment.FragmentNavigator navigator, String route, kotlin.reflect.KClass<? extends androidx.fragment.app.Fragment> fragmentClass);
+    ctor public FragmentNavigatorDestinationBuilder(androidx.navigation.fragment.FragmentNavigator navigator, kotlin.reflect.KClass<?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.reflect.KClass<? extends androidx.fragment.app.Fragment> fragmentClass);
+    method public androidx.navigation.fragment.FragmentNavigator.Destination build();
+  }
+
+  public final class FragmentNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.NavGraphBuilder, @IdRes int id);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.NavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.FragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.NavGraphBuilder, String route);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.NavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.FragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.Fragment, reified T> void fragment(androidx.navigation.NavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public static inline <reified F extends androidx.fragment.app.Fragment, reified T> void fragment(androidx.navigation.NavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.FragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+  }
+
+  public final class FragmentNavigatorExtrasKt {
+    method public static androidx.navigation.fragment.FragmentNavigator.Extras FragmentNavigatorExtras(kotlin.Pair<? extends android.view.View,java.lang.String>... sharedElements);
+  }
+
+  public class NavHostFragment extends androidx.fragment.app.Fragment implements androidx.navigation.NavHost {
+    ctor public NavHostFragment();
+    method public static final androidx.navigation.fragment.NavHostFragment create(@NavigationRes int graphResId);
+    method public static final androidx.navigation.fragment.NavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+    method @Deprecated protected androidx.navigation.Navigator<? extends androidx.navigation.fragment.FragmentNavigator.Destination> createFragmentNavigator();
+    method public static final androidx.navigation.NavController findNavController(androidx.fragment.app.Fragment fragment);
+    method public final androidx.navigation.NavController getNavController();
+    method @Deprecated @CallSuper protected void onCreateNavController(androidx.navigation.NavController navController);
+    method @CallSuper protected void onCreateNavHostController(androidx.navigation.NavHostController navHostController);
+    property public final androidx.navigation.NavController navController;
+    field public static final androidx.navigation.fragment.NavHostFragment.Companion Companion;
+  }
+
+  public static final class NavHostFragment.Companion {
+    method public androidx.navigation.fragment.NavHostFragment create(@NavigationRes int graphResId);
+    method public androidx.navigation.fragment.NavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+    method public androidx.navigation.NavController findNavController(androidx.fragment.app.Fragment fragment);
+  }
+
+}
+
diff --git a/navigation/navigation-fragment/api/2.8.0-beta05.txt b/navigation/navigation-fragment/api/2.8.0-beta05.txt
new file mode 100644
index 0000000..0db42b8
--- /dev/null
+++ b/navigation/navigation-fragment/api/2.8.0-beta05.txt
@@ -0,0 +1,131 @@
+// Signature format: 4.0
+package androidx.navigation {
+
+  public final class NavGraphViewModelLazyKt {
+    method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<VM> navGraphViewModels(androidx.fragment.app.Fragment, @IdRes int navGraphId, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras>? extrasProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @Deprecated @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<VM> navGraphViewModels(androidx.fragment.app.Fragment, @IdRes int navGraphId, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<VM> navGraphViewModels(androidx.fragment.app.Fragment, String navGraphRoute, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras>? extrasProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @Deprecated @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<VM> navGraphViewModels(androidx.fragment.app.Fragment, String navGraphRoute, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+  }
+
+}
+
+package androidx.navigation.fragment {
+
+  public abstract class AbstractListDetailFragment extends androidx.fragment.app.Fragment {
+    ctor public AbstractListDetailFragment();
+    method public final androidx.navigation.fragment.NavHostFragment getDetailPaneNavHostFragment();
+    method public final androidx.slidingpanelayout.widget.SlidingPaneLayout getSlidingPaneLayout();
+    method public androidx.navigation.fragment.NavHostFragment onCreateDetailPaneNavHostFragment();
+    method public abstract android.view.View onCreateListPaneView(android.view.LayoutInflater inflater, android.view.ViewGroup? container, android.os.Bundle? savedInstanceState);
+    method @CallSuper public final android.view.View onCreateView(android.view.LayoutInflater inflater, android.view.ViewGroup? container, android.os.Bundle? savedInstanceState);
+    method public void onListPaneViewCreated(android.view.View view, android.os.Bundle? savedInstanceState);
+    method @CallSuper public final void onViewCreated(android.view.View view, android.os.Bundle? savedInstanceState);
+    property public final androidx.navigation.fragment.NavHostFragment detailPaneNavHostFragment;
+    property public final androidx.slidingpanelayout.widget.SlidingPaneLayout slidingPaneLayout;
+  }
+
+  @androidx.navigation.Navigator.Name("dialog") public final class DialogFragmentNavigator extends androidx.navigation.Navigator<androidx.navigation.fragment.DialogFragmentNavigator.Destination> {
+    ctor public DialogFragmentNavigator(android.content.Context context, androidx.fragment.app.FragmentManager fragmentManager);
+    method public androidx.navigation.fragment.DialogFragmentNavigator.Destination createDestination();
+  }
+
+  @androidx.navigation.NavDestination.ClassType(DialogFragment::class) public static class DialogFragmentNavigator.Destination extends androidx.navigation.NavDestination implements androidx.navigation.FloatingWindow {
+    ctor public DialogFragmentNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.fragment.DialogFragmentNavigator.Destination> fragmentNavigator);
+    ctor public DialogFragmentNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public final String getClassName();
+    method public final androidx.navigation.fragment.DialogFragmentNavigator.Destination setClassName(String className);
+    property public final String className;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DialogFragmentNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.fragment.DialogFragmentNavigator.Destination> {
+    ctor @Deprecated public DialogFragmentNavigatorDestinationBuilder(androidx.navigation.fragment.DialogFragmentNavigator navigator, @IdRes int id, kotlin.reflect.KClass<? extends androidx.fragment.app.DialogFragment> fragmentClass);
+    ctor public DialogFragmentNavigatorDestinationBuilder(androidx.navigation.fragment.DialogFragmentNavigator navigator, String route, kotlin.reflect.KClass<? extends androidx.fragment.app.DialogFragment> fragmentClass);
+    ctor public DialogFragmentNavigatorDestinationBuilder(androidx.navigation.fragment.DialogFragmentNavigator navigator, kotlin.reflect.KClass<?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.reflect.KClass<? extends androidx.fragment.app.DialogFragment> fragmentClass);
+    method public androidx.navigation.fragment.DialogFragmentNavigator.Destination build();
+  }
+
+  public final class DialogFragmentNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.DialogFragment> void dialog(androidx.navigation.NavGraphBuilder, @IdRes int id);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.DialogFragment> void dialog(androidx.navigation.NavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.DialogFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.DialogFragment> void dialog(androidx.navigation.NavGraphBuilder, String route);
+    method public static inline <reified F extends androidx.fragment.app.DialogFragment> void dialog(androidx.navigation.NavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.DialogFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.DialogFragment, reified T> void dialog(androidx.navigation.NavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public static inline <reified F extends androidx.fragment.app.DialogFragment, reified T> void dialog(androidx.navigation.NavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.DialogFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+  }
+
+  public final class FragmentKt {
+    method public static androidx.navigation.NavController findNavController(androidx.fragment.app.Fragment);
+  }
+
+  public final class FragmentNavArgsLazyKt {
+    method @MainThread public static inline <reified Args extends androidx.navigation.NavArgs> androidx.navigation.NavArgsLazy<Args> navArgs(androidx.fragment.app.Fragment);
+  }
+
+  @androidx.navigation.Navigator.Name("fragment") public class FragmentNavigator extends androidx.navigation.Navigator<androidx.navigation.fragment.FragmentNavigator.Destination> {
+    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);
+  }
+
+  @androidx.navigation.NavDestination.ClassType(Fragment::class) public static class FragmentNavigator.Destination extends androidx.navigation.NavDestination {
+    ctor public FragmentNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.fragment.FragmentNavigator.Destination> fragmentNavigator);
+    ctor public FragmentNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public final String getClassName();
+    method public final androidx.navigation.fragment.FragmentNavigator.Destination setClassName(String className);
+    property public final String className;
+  }
+
+  public static final class FragmentNavigator.Extras implements androidx.navigation.Navigator.Extras {
+    method public java.util.Map<android.view.View,java.lang.String> getSharedElements();
+    property public final java.util.Map<android.view.View,java.lang.String> sharedElements;
+  }
+
+  public static final class FragmentNavigator.Extras.Builder {
+    ctor public FragmentNavigator.Extras.Builder();
+    method public androidx.navigation.fragment.FragmentNavigator.Extras.Builder addSharedElement(android.view.View sharedElement, String name);
+    method public androidx.navigation.fragment.FragmentNavigator.Extras.Builder addSharedElements(java.util.Map<android.view.View,java.lang.String> sharedElements);
+    method public androidx.navigation.fragment.FragmentNavigator.Extras build();
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class FragmentNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.fragment.FragmentNavigator.Destination> {
+    ctor @Deprecated public FragmentNavigatorDestinationBuilder(androidx.navigation.fragment.FragmentNavigator navigator, @IdRes int id, kotlin.reflect.KClass<? extends androidx.fragment.app.Fragment> fragmentClass);
+    ctor public FragmentNavigatorDestinationBuilder(androidx.navigation.fragment.FragmentNavigator navigator, String route, kotlin.reflect.KClass<? extends androidx.fragment.app.Fragment> fragmentClass);
+    ctor public FragmentNavigatorDestinationBuilder(androidx.navigation.fragment.FragmentNavigator navigator, kotlin.reflect.KClass<?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.reflect.KClass<? extends androidx.fragment.app.Fragment> fragmentClass);
+    method public androidx.navigation.fragment.FragmentNavigator.Destination build();
+  }
+
+  public final class FragmentNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.NavGraphBuilder, @IdRes int id);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.NavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.FragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.NavGraphBuilder, String route);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.NavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.FragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.Fragment, reified T> void fragment(androidx.navigation.NavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public static inline <reified F extends androidx.fragment.app.Fragment, reified T> void fragment(androidx.navigation.NavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.FragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+  }
+
+  public final class FragmentNavigatorExtrasKt {
+    method public static androidx.navigation.fragment.FragmentNavigator.Extras FragmentNavigatorExtras(kotlin.Pair<? extends android.view.View,java.lang.String>... sharedElements);
+  }
+
+  public class NavHostFragment extends androidx.fragment.app.Fragment implements androidx.navigation.NavHost {
+    ctor public NavHostFragment();
+    method public static final androidx.navigation.fragment.NavHostFragment create(@NavigationRes int graphResId);
+    method public static final androidx.navigation.fragment.NavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+    method @Deprecated protected androidx.navigation.Navigator<? extends androidx.navigation.fragment.FragmentNavigator.Destination> createFragmentNavigator();
+    method public static final androidx.navigation.NavController findNavController(androidx.fragment.app.Fragment fragment);
+    method public final androidx.navigation.NavController getNavController();
+    method @Deprecated @CallSuper protected void onCreateNavController(androidx.navigation.NavController navController);
+    method @CallSuper protected void onCreateNavHostController(androidx.navigation.NavHostController navHostController);
+    property public final androidx.navigation.NavController navController;
+    field public static final androidx.navigation.fragment.NavHostFragment.Companion Companion;
+  }
+
+  public static final class NavHostFragment.Companion {
+    method public androidx.navigation.fragment.NavHostFragment create(@NavigationRes int graphResId);
+    method public androidx.navigation.fragment.NavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+    method public androidx.navigation.NavController findNavController(androidx.fragment.app.Fragment fragment);
+  }
+
+}
+
diff --git a/navigation/navigation-fragment/api/res-2.8.0-beta04.txt b/navigation/navigation-fragment/api/res-2.8.0-beta04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-fragment/api/res-2.8.0-beta04.txt
diff --git a/navigation/navigation-fragment/api/res-2.8.0-beta05.txt b/navigation/navigation-fragment/api/res-2.8.0-beta05.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-fragment/api/res-2.8.0-beta05.txt
diff --git a/navigation/navigation-fragment/api/restricted_2.8.0-beta04.txt b/navigation/navigation-fragment/api/restricted_2.8.0-beta04.txt
new file mode 100644
index 0000000..0db42b8
--- /dev/null
+++ b/navigation/navigation-fragment/api/restricted_2.8.0-beta04.txt
@@ -0,0 +1,131 @@
+// Signature format: 4.0
+package androidx.navigation {
+
+  public final class NavGraphViewModelLazyKt {
+    method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<VM> navGraphViewModels(androidx.fragment.app.Fragment, @IdRes int navGraphId, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras>? extrasProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @Deprecated @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<VM> navGraphViewModels(androidx.fragment.app.Fragment, @IdRes int navGraphId, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<VM> navGraphViewModels(androidx.fragment.app.Fragment, String navGraphRoute, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras>? extrasProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @Deprecated @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<VM> navGraphViewModels(androidx.fragment.app.Fragment, String navGraphRoute, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+  }
+
+}
+
+package androidx.navigation.fragment {
+
+  public abstract class AbstractListDetailFragment extends androidx.fragment.app.Fragment {
+    ctor public AbstractListDetailFragment();
+    method public final androidx.navigation.fragment.NavHostFragment getDetailPaneNavHostFragment();
+    method public final androidx.slidingpanelayout.widget.SlidingPaneLayout getSlidingPaneLayout();
+    method public androidx.navigation.fragment.NavHostFragment onCreateDetailPaneNavHostFragment();
+    method public abstract android.view.View onCreateListPaneView(android.view.LayoutInflater inflater, android.view.ViewGroup? container, android.os.Bundle? savedInstanceState);
+    method @CallSuper public final android.view.View onCreateView(android.view.LayoutInflater inflater, android.view.ViewGroup? container, android.os.Bundle? savedInstanceState);
+    method public void onListPaneViewCreated(android.view.View view, android.os.Bundle? savedInstanceState);
+    method @CallSuper public final void onViewCreated(android.view.View view, android.os.Bundle? savedInstanceState);
+    property public final androidx.navigation.fragment.NavHostFragment detailPaneNavHostFragment;
+    property public final androidx.slidingpanelayout.widget.SlidingPaneLayout slidingPaneLayout;
+  }
+
+  @androidx.navigation.Navigator.Name("dialog") public final class DialogFragmentNavigator extends androidx.navigation.Navigator<androidx.navigation.fragment.DialogFragmentNavigator.Destination> {
+    ctor public DialogFragmentNavigator(android.content.Context context, androidx.fragment.app.FragmentManager fragmentManager);
+    method public androidx.navigation.fragment.DialogFragmentNavigator.Destination createDestination();
+  }
+
+  @androidx.navigation.NavDestination.ClassType(DialogFragment::class) public static class DialogFragmentNavigator.Destination extends androidx.navigation.NavDestination implements androidx.navigation.FloatingWindow {
+    ctor public DialogFragmentNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.fragment.DialogFragmentNavigator.Destination> fragmentNavigator);
+    ctor public DialogFragmentNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public final String getClassName();
+    method public final androidx.navigation.fragment.DialogFragmentNavigator.Destination setClassName(String className);
+    property public final String className;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DialogFragmentNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.fragment.DialogFragmentNavigator.Destination> {
+    ctor @Deprecated public DialogFragmentNavigatorDestinationBuilder(androidx.navigation.fragment.DialogFragmentNavigator navigator, @IdRes int id, kotlin.reflect.KClass<? extends androidx.fragment.app.DialogFragment> fragmentClass);
+    ctor public DialogFragmentNavigatorDestinationBuilder(androidx.navigation.fragment.DialogFragmentNavigator navigator, String route, kotlin.reflect.KClass<? extends androidx.fragment.app.DialogFragment> fragmentClass);
+    ctor public DialogFragmentNavigatorDestinationBuilder(androidx.navigation.fragment.DialogFragmentNavigator navigator, kotlin.reflect.KClass<?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.reflect.KClass<? extends androidx.fragment.app.DialogFragment> fragmentClass);
+    method public androidx.navigation.fragment.DialogFragmentNavigator.Destination build();
+  }
+
+  public final class DialogFragmentNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.DialogFragment> void dialog(androidx.navigation.NavGraphBuilder, @IdRes int id);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.DialogFragment> void dialog(androidx.navigation.NavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.DialogFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.DialogFragment> void dialog(androidx.navigation.NavGraphBuilder, String route);
+    method public static inline <reified F extends androidx.fragment.app.DialogFragment> void dialog(androidx.navigation.NavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.DialogFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.DialogFragment, reified T> void dialog(androidx.navigation.NavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public static inline <reified F extends androidx.fragment.app.DialogFragment, reified T> void dialog(androidx.navigation.NavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.DialogFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+  }
+
+  public final class FragmentKt {
+    method public static androidx.navigation.NavController findNavController(androidx.fragment.app.Fragment);
+  }
+
+  public final class FragmentNavArgsLazyKt {
+    method @MainThread public static inline <reified Args extends androidx.navigation.NavArgs> androidx.navigation.NavArgsLazy<Args> navArgs(androidx.fragment.app.Fragment);
+  }
+
+  @androidx.navigation.Navigator.Name("fragment") public class FragmentNavigator extends androidx.navigation.Navigator<androidx.navigation.fragment.FragmentNavigator.Destination> {
+    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);
+  }
+
+  @androidx.navigation.NavDestination.ClassType(Fragment::class) public static class FragmentNavigator.Destination extends androidx.navigation.NavDestination {
+    ctor public FragmentNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.fragment.FragmentNavigator.Destination> fragmentNavigator);
+    ctor public FragmentNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public final String getClassName();
+    method public final androidx.navigation.fragment.FragmentNavigator.Destination setClassName(String className);
+    property public final String className;
+  }
+
+  public static final class FragmentNavigator.Extras implements androidx.navigation.Navigator.Extras {
+    method public java.util.Map<android.view.View,java.lang.String> getSharedElements();
+    property public final java.util.Map<android.view.View,java.lang.String> sharedElements;
+  }
+
+  public static final class FragmentNavigator.Extras.Builder {
+    ctor public FragmentNavigator.Extras.Builder();
+    method public androidx.navigation.fragment.FragmentNavigator.Extras.Builder addSharedElement(android.view.View sharedElement, String name);
+    method public androidx.navigation.fragment.FragmentNavigator.Extras.Builder addSharedElements(java.util.Map<android.view.View,java.lang.String> sharedElements);
+    method public androidx.navigation.fragment.FragmentNavigator.Extras build();
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class FragmentNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.fragment.FragmentNavigator.Destination> {
+    ctor @Deprecated public FragmentNavigatorDestinationBuilder(androidx.navigation.fragment.FragmentNavigator navigator, @IdRes int id, kotlin.reflect.KClass<? extends androidx.fragment.app.Fragment> fragmentClass);
+    ctor public FragmentNavigatorDestinationBuilder(androidx.navigation.fragment.FragmentNavigator navigator, String route, kotlin.reflect.KClass<? extends androidx.fragment.app.Fragment> fragmentClass);
+    ctor public FragmentNavigatorDestinationBuilder(androidx.navigation.fragment.FragmentNavigator navigator, kotlin.reflect.KClass<?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.reflect.KClass<? extends androidx.fragment.app.Fragment> fragmentClass);
+    method public androidx.navigation.fragment.FragmentNavigator.Destination build();
+  }
+
+  public final class FragmentNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.NavGraphBuilder, @IdRes int id);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.NavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.FragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.NavGraphBuilder, String route);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.NavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.FragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.Fragment, reified T> void fragment(androidx.navigation.NavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public static inline <reified F extends androidx.fragment.app.Fragment, reified T> void fragment(androidx.navigation.NavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.FragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+  }
+
+  public final class FragmentNavigatorExtrasKt {
+    method public static androidx.navigation.fragment.FragmentNavigator.Extras FragmentNavigatorExtras(kotlin.Pair<? extends android.view.View,java.lang.String>... sharedElements);
+  }
+
+  public class NavHostFragment extends androidx.fragment.app.Fragment implements androidx.navigation.NavHost {
+    ctor public NavHostFragment();
+    method public static final androidx.navigation.fragment.NavHostFragment create(@NavigationRes int graphResId);
+    method public static final androidx.navigation.fragment.NavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+    method @Deprecated protected androidx.navigation.Navigator<? extends androidx.navigation.fragment.FragmentNavigator.Destination> createFragmentNavigator();
+    method public static final androidx.navigation.NavController findNavController(androidx.fragment.app.Fragment fragment);
+    method public final androidx.navigation.NavController getNavController();
+    method @Deprecated @CallSuper protected void onCreateNavController(androidx.navigation.NavController navController);
+    method @CallSuper protected void onCreateNavHostController(androidx.navigation.NavHostController navHostController);
+    property public final androidx.navigation.NavController navController;
+    field public static final androidx.navigation.fragment.NavHostFragment.Companion Companion;
+  }
+
+  public static final class NavHostFragment.Companion {
+    method public androidx.navigation.fragment.NavHostFragment create(@NavigationRes int graphResId);
+    method public androidx.navigation.fragment.NavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+    method public androidx.navigation.NavController findNavController(androidx.fragment.app.Fragment fragment);
+  }
+
+}
+
diff --git a/navigation/navigation-fragment/api/restricted_2.8.0-beta05.txt b/navigation/navigation-fragment/api/restricted_2.8.0-beta05.txt
new file mode 100644
index 0000000..0db42b8
--- /dev/null
+++ b/navigation/navigation-fragment/api/restricted_2.8.0-beta05.txt
@@ -0,0 +1,131 @@
+// Signature format: 4.0
+package androidx.navigation {
+
+  public final class NavGraphViewModelLazyKt {
+    method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<VM> navGraphViewModels(androidx.fragment.app.Fragment, @IdRes int navGraphId, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras>? extrasProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @Deprecated @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<VM> navGraphViewModels(androidx.fragment.app.Fragment, @IdRes int navGraphId, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<VM> navGraphViewModels(androidx.fragment.app.Fragment, String navGraphRoute, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras>? extrasProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+    method @Deprecated @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<VM> navGraphViewModels(androidx.fragment.app.Fragment, String navGraphRoute, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+  }
+
+}
+
+package androidx.navigation.fragment {
+
+  public abstract class AbstractListDetailFragment extends androidx.fragment.app.Fragment {
+    ctor public AbstractListDetailFragment();
+    method public final androidx.navigation.fragment.NavHostFragment getDetailPaneNavHostFragment();
+    method public final androidx.slidingpanelayout.widget.SlidingPaneLayout getSlidingPaneLayout();
+    method public androidx.navigation.fragment.NavHostFragment onCreateDetailPaneNavHostFragment();
+    method public abstract android.view.View onCreateListPaneView(android.view.LayoutInflater inflater, android.view.ViewGroup? container, android.os.Bundle? savedInstanceState);
+    method @CallSuper public final android.view.View onCreateView(android.view.LayoutInflater inflater, android.view.ViewGroup? container, android.os.Bundle? savedInstanceState);
+    method public void onListPaneViewCreated(android.view.View view, android.os.Bundle? savedInstanceState);
+    method @CallSuper public final void onViewCreated(android.view.View view, android.os.Bundle? savedInstanceState);
+    property public final androidx.navigation.fragment.NavHostFragment detailPaneNavHostFragment;
+    property public final androidx.slidingpanelayout.widget.SlidingPaneLayout slidingPaneLayout;
+  }
+
+  @androidx.navigation.Navigator.Name("dialog") public final class DialogFragmentNavigator extends androidx.navigation.Navigator<androidx.navigation.fragment.DialogFragmentNavigator.Destination> {
+    ctor public DialogFragmentNavigator(android.content.Context context, androidx.fragment.app.FragmentManager fragmentManager);
+    method public androidx.navigation.fragment.DialogFragmentNavigator.Destination createDestination();
+  }
+
+  @androidx.navigation.NavDestination.ClassType(DialogFragment::class) public static class DialogFragmentNavigator.Destination extends androidx.navigation.NavDestination implements androidx.navigation.FloatingWindow {
+    ctor public DialogFragmentNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.fragment.DialogFragmentNavigator.Destination> fragmentNavigator);
+    ctor public DialogFragmentNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public final String getClassName();
+    method public final androidx.navigation.fragment.DialogFragmentNavigator.Destination setClassName(String className);
+    property public final String className;
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class DialogFragmentNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.fragment.DialogFragmentNavigator.Destination> {
+    ctor @Deprecated public DialogFragmentNavigatorDestinationBuilder(androidx.navigation.fragment.DialogFragmentNavigator navigator, @IdRes int id, kotlin.reflect.KClass<? extends androidx.fragment.app.DialogFragment> fragmentClass);
+    ctor public DialogFragmentNavigatorDestinationBuilder(androidx.navigation.fragment.DialogFragmentNavigator navigator, String route, kotlin.reflect.KClass<? extends androidx.fragment.app.DialogFragment> fragmentClass);
+    ctor public DialogFragmentNavigatorDestinationBuilder(androidx.navigation.fragment.DialogFragmentNavigator navigator, kotlin.reflect.KClass<?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.reflect.KClass<? extends androidx.fragment.app.DialogFragment> fragmentClass);
+    method public androidx.navigation.fragment.DialogFragmentNavigator.Destination build();
+  }
+
+  public final class DialogFragmentNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.DialogFragment> void dialog(androidx.navigation.NavGraphBuilder, @IdRes int id);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.DialogFragment> void dialog(androidx.navigation.NavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.DialogFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.DialogFragment> void dialog(androidx.navigation.NavGraphBuilder, String route);
+    method public static inline <reified F extends androidx.fragment.app.DialogFragment> void dialog(androidx.navigation.NavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.DialogFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.DialogFragment, reified T> void dialog(androidx.navigation.NavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public static inline <reified F extends androidx.fragment.app.DialogFragment, reified T> void dialog(androidx.navigation.NavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.DialogFragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+  }
+
+  public final class FragmentKt {
+    method public static androidx.navigation.NavController findNavController(androidx.fragment.app.Fragment);
+  }
+
+  public final class FragmentNavArgsLazyKt {
+    method @MainThread public static inline <reified Args extends androidx.navigation.NavArgs> androidx.navigation.NavArgsLazy<Args> navArgs(androidx.fragment.app.Fragment);
+  }
+
+  @androidx.navigation.Navigator.Name("fragment") public class FragmentNavigator extends androidx.navigation.Navigator<androidx.navigation.fragment.FragmentNavigator.Destination> {
+    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);
+  }
+
+  @androidx.navigation.NavDestination.ClassType(Fragment::class) public static class FragmentNavigator.Destination extends androidx.navigation.NavDestination {
+    ctor public FragmentNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.fragment.FragmentNavigator.Destination> fragmentNavigator);
+    ctor public FragmentNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public final String getClassName();
+    method public final androidx.navigation.fragment.FragmentNavigator.Destination setClassName(String className);
+    property public final String className;
+  }
+
+  public static final class FragmentNavigator.Extras implements androidx.navigation.Navigator.Extras {
+    method public java.util.Map<android.view.View,java.lang.String> getSharedElements();
+    property public final java.util.Map<android.view.View,java.lang.String> sharedElements;
+  }
+
+  public static final class FragmentNavigator.Extras.Builder {
+    ctor public FragmentNavigator.Extras.Builder();
+    method public androidx.navigation.fragment.FragmentNavigator.Extras.Builder addSharedElement(android.view.View sharedElement, String name);
+    method public androidx.navigation.fragment.FragmentNavigator.Extras.Builder addSharedElements(java.util.Map<android.view.View,java.lang.String> sharedElements);
+    method public androidx.navigation.fragment.FragmentNavigator.Extras build();
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class FragmentNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.fragment.FragmentNavigator.Destination> {
+    ctor @Deprecated public FragmentNavigatorDestinationBuilder(androidx.navigation.fragment.FragmentNavigator navigator, @IdRes int id, kotlin.reflect.KClass<? extends androidx.fragment.app.Fragment> fragmentClass);
+    ctor public FragmentNavigatorDestinationBuilder(androidx.navigation.fragment.FragmentNavigator navigator, String route, kotlin.reflect.KClass<? extends androidx.fragment.app.Fragment> fragmentClass);
+    ctor public FragmentNavigatorDestinationBuilder(androidx.navigation.fragment.FragmentNavigator navigator, kotlin.reflect.KClass<?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.reflect.KClass<? extends androidx.fragment.app.Fragment> fragmentClass);
+    method public androidx.navigation.fragment.FragmentNavigator.Destination build();
+  }
+
+  public final class FragmentNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.NavGraphBuilder, @IdRes int id);
+    method @Deprecated public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.NavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.FragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.NavGraphBuilder, String route);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> void fragment(androidx.navigation.NavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.FragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified F extends androidx.fragment.app.Fragment, reified T> void fragment(androidx.navigation.NavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public static inline <reified F extends androidx.fragment.app.Fragment, reified T> void fragment(androidx.navigation.NavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.fragment.FragmentNavigatorDestinationBuilder,kotlin.Unit> builder);
+  }
+
+  public final class FragmentNavigatorExtrasKt {
+    method public static androidx.navigation.fragment.FragmentNavigator.Extras FragmentNavigatorExtras(kotlin.Pair<? extends android.view.View,java.lang.String>... sharedElements);
+  }
+
+  public class NavHostFragment extends androidx.fragment.app.Fragment implements androidx.navigation.NavHost {
+    ctor public NavHostFragment();
+    method public static final androidx.navigation.fragment.NavHostFragment create(@NavigationRes int graphResId);
+    method public static final androidx.navigation.fragment.NavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+    method @Deprecated protected androidx.navigation.Navigator<? extends androidx.navigation.fragment.FragmentNavigator.Destination> createFragmentNavigator();
+    method public static final androidx.navigation.NavController findNavController(androidx.fragment.app.Fragment fragment);
+    method public final androidx.navigation.NavController getNavController();
+    method @Deprecated @CallSuper protected void onCreateNavController(androidx.navigation.NavController navController);
+    method @CallSuper protected void onCreateNavHostController(androidx.navigation.NavHostController navHostController);
+    property public final androidx.navigation.NavController navController;
+    field public static final androidx.navigation.fragment.NavHostFragment.Companion Companion;
+  }
+
+  public static final class NavHostFragment.Companion {
+    method public androidx.navigation.fragment.NavHostFragment create(@NavigationRes int graphResId);
+    method public androidx.navigation.fragment.NavHostFragment create(@NavigationRes int graphResId, optional android.os.Bundle? startDestinationArgs);
+    method public androidx.navigation.NavController findNavController(androidx.fragment.app.Fragment fragment);
+  }
+
+}
+
diff --git a/navigation/navigation-runtime-ktx/api/2.8.0-beta04.txt b/navigation/navigation-runtime-ktx/api/2.8.0-beta04.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/navigation/navigation-runtime-ktx/api/2.8.0-beta04.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/navigation/navigation-runtime-ktx/api/2.8.0-beta05.txt b/navigation/navigation-runtime-ktx/api/2.8.0-beta05.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/navigation/navigation-runtime-ktx/api/2.8.0-beta05.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/navigation/navigation-runtime-ktx/api/res-2.8.0-beta04.txt b/navigation/navigation-runtime-ktx/api/res-2.8.0-beta04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-runtime-ktx/api/res-2.8.0-beta04.txt
diff --git a/navigation/navigation-runtime-ktx/api/res-2.8.0-beta05.txt b/navigation/navigation-runtime-ktx/api/res-2.8.0-beta05.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-runtime-ktx/api/res-2.8.0-beta05.txt
diff --git a/navigation/navigation-runtime-ktx/api/restricted_2.8.0-beta04.txt b/navigation/navigation-runtime-ktx/api/restricted_2.8.0-beta04.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/navigation/navigation-runtime-ktx/api/restricted_2.8.0-beta04.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/navigation/navigation-runtime-ktx/api/restricted_2.8.0-beta05.txt b/navigation/navigation-runtime-ktx/api/restricted_2.8.0-beta05.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/navigation/navigation-runtime-ktx/api/restricted_2.8.0-beta05.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/navigation/navigation-runtime/api/2.8.0-beta04.txt b/navigation/navigation-runtime/api/2.8.0-beta04.txt
new file mode 100644
index 0000000..b801964
--- /dev/null
+++ b/navigation/navigation-runtime/api/2.8.0-beta04.txt
@@ -0,0 +1,246 @@
+// Signature format: 4.0
+package androidx.navigation {
+
+  public final class ActivityKt {
+    method public static androidx.navigation.NavController findNavController(android.app.Activity, @IdRes int viewId);
+  }
+
+  public final class ActivityNavArgsLazyKt {
+    method @MainThread public static inline <reified Args extends androidx.navigation.NavArgs> androidx.navigation.NavArgsLazy<Args> navArgs(android.app.Activity);
+  }
+
+  @androidx.navigation.Navigator.Name("activity") public class ActivityNavigator extends androidx.navigation.Navigator<androidx.navigation.ActivityNavigator.Destination> {
+    ctor public ActivityNavigator(android.content.Context context);
+    method public static final void applyPopAnimationsToPendingTransition(android.app.Activity activity);
+    method public androidx.navigation.ActivityNavigator.Destination createDestination();
+    method public androidx.navigation.NavDestination? navigate(androidx.navigation.ActivityNavigator.Destination destination, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    field public static final androidx.navigation.ActivityNavigator.Companion Companion;
+  }
+
+  public static final class ActivityNavigator.Companion {
+    method public void applyPopAnimationsToPendingTransition(android.app.Activity activity);
+  }
+
+  @androidx.navigation.NavDestination.ClassType(Activity::class) public static class ActivityNavigator.Destination extends androidx.navigation.NavDestination {
+    ctor public ActivityNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.ActivityNavigator.Destination> activityNavigator);
+    ctor public ActivityNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public final String? getAction();
+    method public final android.content.ComponentName? getComponent();
+    method public final android.net.Uri? getData();
+    method public final String? getDataPattern();
+    method public final android.content.Intent? getIntent();
+    method public final String? getTargetPackage();
+    method public final androidx.navigation.ActivityNavigator.Destination setAction(String? action);
+    method public final androidx.navigation.ActivityNavigator.Destination setComponentName(android.content.ComponentName? name);
+    method public final androidx.navigation.ActivityNavigator.Destination setData(android.net.Uri? data);
+    method public final androidx.navigation.ActivityNavigator.Destination setDataPattern(String? dataPattern);
+    method public final androidx.navigation.ActivityNavigator.Destination setIntent(android.content.Intent? intent);
+    method public final androidx.navigation.ActivityNavigator.Destination setTargetPackage(String? packageName);
+    property public final String? action;
+    property public final android.content.ComponentName? component;
+    property public final android.net.Uri? data;
+    property public final String? dataPattern;
+    property public final android.content.Intent? intent;
+    property public final String? targetPackage;
+  }
+
+  public static final class ActivityNavigator.Extras implements androidx.navigation.Navigator.Extras {
+    method public androidx.core.app.ActivityOptionsCompat? getActivityOptions();
+    method public int getFlags();
+    property public final androidx.core.app.ActivityOptionsCompat? activityOptions;
+    property public final int flags;
+  }
+
+  public static final class ActivityNavigator.Extras.Builder {
+    ctor public ActivityNavigator.Extras.Builder();
+    method public androidx.navigation.ActivityNavigator.Extras.Builder addFlags(int flags);
+    method public androidx.navigation.ActivityNavigator.Extras build();
+    method public androidx.navigation.ActivityNavigator.Extras.Builder setActivityOptions(androidx.core.app.ActivityOptionsCompat activityOptions);
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class ActivityNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.ActivityNavigator.Destination> {
+    ctor @Deprecated public ActivityNavigatorDestinationBuilder(androidx.navigation.ActivityNavigator navigator, @IdRes int id);
+    ctor public ActivityNavigatorDestinationBuilder(androidx.navigation.ActivityNavigator navigator, String route);
+    ctor public ActivityNavigatorDestinationBuilder(androidx.navigation.ActivityNavigator navigator, kotlin.reflect.KClass<?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public androidx.navigation.ActivityNavigator.Destination build();
+    method public String? getAction();
+    method public kotlin.reflect.KClass<? extends android.app.Activity>? getActivityClass();
+    method public android.net.Uri? getData();
+    method public String? getDataPattern();
+    method public String? getTargetPackage();
+    method public void setAction(String?);
+    method public void setActivityClass(kotlin.reflect.KClass<? extends android.app.Activity>?);
+    method public void setData(android.net.Uri?);
+    method public void setDataPattern(String?);
+    method public void setTargetPackage(String?);
+    property public final String? action;
+    property public final kotlin.reflect.KClass<? extends android.app.Activity>? activityClass;
+    property public final android.net.Uri? data;
+    property public final String? dataPattern;
+    property public final String? targetPackage;
+  }
+
+  public final class ActivityNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline void activity(androidx.navigation.NavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.ActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline void activity(androidx.navigation.NavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.ActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void activity(androidx.navigation.NavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.ActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+  }
+
+  public final class ActivityNavigatorExtrasKt {
+    method public static androidx.navigation.ActivityNavigator.Extras ActivityNavigatorExtras(optional androidx.core.app.ActivityOptionsCompat? activityOptions, optional int flags);
+  }
+
+  public class NavController {
+    ctor public NavController(android.content.Context context);
+    method public void addOnDestinationChangedListener(androidx.navigation.NavController.OnDestinationChangedListener listener);
+    method @MainThread public inline <reified T> boolean clearBackStack();
+    method @MainThread public final boolean clearBackStack(@IdRes int destinationId);
+    method @MainThread public final boolean clearBackStack(String route);
+    method @MainThread public final <T> boolean clearBackStack(T route);
+    method public androidx.navigation.NavDeepLinkBuilder createDeepLink();
+    method @SuppressCompatibility @androidx.navigation.NavDeepLinkSaveStateControl public static final void enableDeepLinkSaveState(boolean saveState);
+    method public inline <reified T> androidx.navigation.NavBackStackEntry getBackStackEntry();
+    method public androidx.navigation.NavBackStackEntry getBackStackEntry(@IdRes int destinationId);
+    method public final androidx.navigation.NavBackStackEntry getBackStackEntry(String route);
+    method public final <T> androidx.navigation.NavBackStackEntry getBackStackEntry(T route);
+    method public androidx.navigation.NavBackStackEntry? getCurrentBackStackEntry();
+    method public final kotlinx.coroutines.flow.Flow<androidx.navigation.NavBackStackEntry> getCurrentBackStackEntryFlow();
+    method public androidx.navigation.NavDestination? getCurrentDestination();
+    method @MainThread public androidx.navigation.NavGraph getGraph();
+    method public androidx.navigation.NavInflater getNavInflater();
+    method public androidx.navigation.NavigatorProvider getNavigatorProvider();
+    method public androidx.navigation.NavBackStackEntry? getPreviousBackStackEntry();
+    method public androidx.lifecycle.ViewModelStoreOwner getViewModelStoreOwner(@IdRes int navGraphId);
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getVisibleEntries();
+    method @MainThread public boolean handleDeepLink(android.content.Intent? intent);
+    method @MainThread public void navigate(android.net.Uri deepLink);
+    method @MainThread public void navigate(android.net.Uri deepLink, androidx.navigation.NavOptions? navOptions);
+    method @MainThread public void navigate(android.net.Uri deepLink, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public void navigate(androidx.navigation.NavDeepLinkRequest request);
+    method @MainThread public void navigate(androidx.navigation.NavDeepLinkRequest request, androidx.navigation.NavOptions? navOptions);
+    method @MainThread public void navigate(androidx.navigation.NavDeepLinkRequest request, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public void navigate(androidx.navigation.NavDirections directions);
+    method @MainThread public void navigate(androidx.navigation.NavDirections directions, androidx.navigation.Navigator.Extras navigatorExtras);
+    method @MainThread public void navigate(androidx.navigation.NavDirections directions, androidx.navigation.NavOptions? navOptions);
+    method @MainThread public void navigate(@IdRes int resId);
+    method @MainThread public void navigate(@IdRes int resId, android.os.Bundle? args);
+    method @MainThread public void navigate(@IdRes int resId, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions);
+    method @MainThread public void navigate(@IdRes int resId, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public final void navigate(String route);
+    method @MainThread public final void navigate(String route, optional androidx.navigation.NavOptions? navOptions);
+    method @MainThread public final void navigate(String route, optional androidx.navigation.NavOptions? navOptions, optional androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public final void navigate(String route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavOptionsBuilder,kotlin.Unit> builder);
+    method @MainThread public final <T> void navigate(T route);
+    method @MainThread public final <T> void navigate(T route, optional androidx.navigation.NavOptions? navOptions);
+    method @MainThread public final <T> void navigate(T route, optional androidx.navigation.NavOptions? navOptions, optional androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public final <T> void navigate(T route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavOptionsBuilder,kotlin.Unit> builder);
+    method @MainThread public boolean navigateUp();
+    method @MainThread public boolean popBackStack();
+    method @MainThread public inline <reified T> boolean popBackStack(boolean inclusive, optional boolean saveState);
+    method @MainThread public boolean popBackStack(@IdRes int destinationId, boolean inclusive);
+    method @MainThread public boolean popBackStack(@IdRes int destinationId, boolean inclusive, boolean saveState);
+    method @MainThread public final boolean popBackStack(String route, boolean inclusive);
+    method @MainThread public final boolean popBackStack(String route, boolean inclusive, optional boolean saveState);
+    method @MainThread public final <T> boolean popBackStack(T route, boolean inclusive);
+    method @MainThread public final <T> boolean popBackStack(T route, boolean inclusive, optional boolean saveState);
+    method public void removeOnDestinationChangedListener(androidx.navigation.NavController.OnDestinationChangedListener listener);
+    method @CallSuper public void restoreState(android.os.Bundle? navState);
+    method @CallSuper public android.os.Bundle? saveState();
+    method @CallSuper @MainThread public void setGraph(androidx.navigation.NavGraph);
+    method @CallSuper @MainThread public void setGraph(androidx.navigation.NavGraph graph, android.os.Bundle? startDestinationArgs);
+    method @CallSuper @MainThread public void setGraph(@NavigationRes int graphResId);
+    method @CallSuper @MainThread public void setGraph(@NavigationRes int graphResId, android.os.Bundle? startDestinationArgs);
+    property public androidx.navigation.NavBackStackEntry? currentBackStackEntry;
+    property public final kotlinx.coroutines.flow.Flow<androidx.navigation.NavBackStackEntry> currentBackStackEntryFlow;
+    property public androidx.navigation.NavDestination? currentDestination;
+    property @MainThread public androidx.navigation.NavGraph graph;
+    property public androidx.navigation.NavInflater navInflater;
+    property public androidx.navigation.NavigatorProvider navigatorProvider;
+    property public androidx.navigation.NavBackStackEntry? previousBackStackEntry;
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> visibleEntries;
+    field public static final androidx.navigation.NavController.Companion Companion;
+    field public static final String KEY_DEEP_LINK_INTENT = "android-support-nav:controller:deepLinkIntent";
+  }
+
+  public static final class NavController.Companion {
+    method @SuppressCompatibility @androidx.navigation.NavDeepLinkSaveStateControl public void enableDeepLinkSaveState(boolean saveState);
+  }
+
+  public static fun interface NavController.OnDestinationChangedListener {
+    method public void onDestinationChanged(androidx.navigation.NavController controller, androidx.navigation.NavDestination destination, android.os.Bundle? arguments);
+  }
+
+  public final class NavControllerKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, Object startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavDeepLinkBuilder {
+    ctor public NavDeepLinkBuilder(android.content.Context context);
+    method public androidx.navigation.NavDeepLinkBuilder addDestination(@IdRes int destId);
+    method public androidx.navigation.NavDeepLinkBuilder addDestination(@IdRes int destId, optional android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder addDestination(String route);
+    method public androidx.navigation.NavDeepLinkBuilder addDestination(String route, optional android.os.Bundle? args);
+    method public android.app.PendingIntent createPendingIntent();
+    method public androidx.core.app.TaskStackBuilder createTaskStackBuilder();
+    method public androidx.navigation.NavDeepLinkBuilder setArguments(android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder setComponentName(android.content.ComponentName componentName);
+    method public androidx.navigation.NavDeepLinkBuilder setComponentName(Class<? extends android.app.Activity?> activityClass);
+    method public androidx.navigation.NavDeepLinkBuilder setDestination(@IdRes int destId);
+    method public androidx.navigation.NavDeepLinkBuilder setDestination(@IdRes int destId, optional android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder setDestination(String destRoute);
+    method public androidx.navigation.NavDeepLinkBuilder setDestination(String destRoute, optional android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder setGraph(androidx.navigation.NavGraph navGraph);
+    method public androidx.navigation.NavDeepLinkBuilder setGraph(@NavigationRes int navGraphId);
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn(level=kotlin.RequiresOptIn.Level.WARNING) @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=kotlin.annotation.AnnotationTarget.FUNCTION) public @interface NavDeepLinkSaveStateControl {
+  }
+
+  public interface NavHost {
+    method public androidx.navigation.NavController getNavController();
+    property public abstract androidx.navigation.NavController navController;
+  }
+
+  public class NavHostController extends androidx.navigation.NavController {
+    ctor public NavHostController(android.content.Context context);
+    method public final void enableOnBackPressed(boolean enabled);
+    method public final void setLifecycleOwner(androidx.lifecycle.LifecycleOwner owner);
+    method public final void setOnBackPressedDispatcher(androidx.activity.OnBackPressedDispatcher dispatcher);
+    method public final void setViewModelStore(androidx.lifecycle.ViewModelStore viewModelStore);
+  }
+
+  public final class NavHostKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, Object startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavInflater {
+    ctor public NavInflater(android.content.Context context, androidx.navigation.NavigatorProvider navigatorProvider);
+    method public androidx.navigation.NavGraph inflate(@NavigationRes int graphResId);
+    field public static final androidx.navigation.NavInflater.Companion Companion;
+  }
+
+  public static final class NavInflater.Companion {
+  }
+
+  public final class Navigation {
+    method public static android.view.View.OnClickListener createNavigateOnClickListener(androidx.navigation.NavDirections directions);
+    method public static android.view.View.OnClickListener createNavigateOnClickListener(@IdRes int resId);
+    method public static android.view.View.OnClickListener createNavigateOnClickListener(@IdRes int resId, optional android.os.Bundle? args);
+    method public static androidx.navigation.NavController findNavController(android.app.Activity activity, @IdRes int viewId);
+    method public static androidx.navigation.NavController findNavController(android.view.View view);
+    method public static void setViewNavController(android.view.View view, androidx.navigation.NavController? controller);
+    field public static final androidx.navigation.Navigation INSTANCE;
+  }
+
+  public final class ViewKt {
+    method public static androidx.navigation.NavController findNavController(android.view.View);
+  }
+
+}
+
diff --git a/navigation/navigation-runtime/api/2.8.0-beta05.txt b/navigation/navigation-runtime/api/2.8.0-beta05.txt
new file mode 100644
index 0000000..b801964
--- /dev/null
+++ b/navigation/navigation-runtime/api/2.8.0-beta05.txt
@@ -0,0 +1,246 @@
+// Signature format: 4.0
+package androidx.navigation {
+
+  public final class ActivityKt {
+    method public static androidx.navigation.NavController findNavController(android.app.Activity, @IdRes int viewId);
+  }
+
+  public final class ActivityNavArgsLazyKt {
+    method @MainThread public static inline <reified Args extends androidx.navigation.NavArgs> androidx.navigation.NavArgsLazy<Args> navArgs(android.app.Activity);
+  }
+
+  @androidx.navigation.Navigator.Name("activity") public class ActivityNavigator extends androidx.navigation.Navigator<androidx.navigation.ActivityNavigator.Destination> {
+    ctor public ActivityNavigator(android.content.Context context);
+    method public static final void applyPopAnimationsToPendingTransition(android.app.Activity activity);
+    method public androidx.navigation.ActivityNavigator.Destination createDestination();
+    method public androidx.navigation.NavDestination? navigate(androidx.navigation.ActivityNavigator.Destination destination, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    field public static final androidx.navigation.ActivityNavigator.Companion Companion;
+  }
+
+  public static final class ActivityNavigator.Companion {
+    method public void applyPopAnimationsToPendingTransition(android.app.Activity activity);
+  }
+
+  @androidx.navigation.NavDestination.ClassType(Activity::class) public static class ActivityNavigator.Destination extends androidx.navigation.NavDestination {
+    ctor public ActivityNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.ActivityNavigator.Destination> activityNavigator);
+    ctor public ActivityNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public final String? getAction();
+    method public final android.content.ComponentName? getComponent();
+    method public final android.net.Uri? getData();
+    method public final String? getDataPattern();
+    method public final android.content.Intent? getIntent();
+    method public final String? getTargetPackage();
+    method public final androidx.navigation.ActivityNavigator.Destination setAction(String? action);
+    method public final androidx.navigation.ActivityNavigator.Destination setComponentName(android.content.ComponentName? name);
+    method public final androidx.navigation.ActivityNavigator.Destination setData(android.net.Uri? data);
+    method public final androidx.navigation.ActivityNavigator.Destination setDataPattern(String? dataPattern);
+    method public final androidx.navigation.ActivityNavigator.Destination setIntent(android.content.Intent? intent);
+    method public final androidx.navigation.ActivityNavigator.Destination setTargetPackage(String? packageName);
+    property public final String? action;
+    property public final android.content.ComponentName? component;
+    property public final android.net.Uri? data;
+    property public final String? dataPattern;
+    property public final android.content.Intent? intent;
+    property public final String? targetPackage;
+  }
+
+  public static final class ActivityNavigator.Extras implements androidx.navigation.Navigator.Extras {
+    method public androidx.core.app.ActivityOptionsCompat? getActivityOptions();
+    method public int getFlags();
+    property public final androidx.core.app.ActivityOptionsCompat? activityOptions;
+    property public final int flags;
+  }
+
+  public static final class ActivityNavigator.Extras.Builder {
+    ctor public ActivityNavigator.Extras.Builder();
+    method public androidx.navigation.ActivityNavigator.Extras.Builder addFlags(int flags);
+    method public androidx.navigation.ActivityNavigator.Extras build();
+    method public androidx.navigation.ActivityNavigator.Extras.Builder setActivityOptions(androidx.core.app.ActivityOptionsCompat activityOptions);
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class ActivityNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.ActivityNavigator.Destination> {
+    ctor @Deprecated public ActivityNavigatorDestinationBuilder(androidx.navigation.ActivityNavigator navigator, @IdRes int id);
+    ctor public ActivityNavigatorDestinationBuilder(androidx.navigation.ActivityNavigator navigator, String route);
+    ctor public ActivityNavigatorDestinationBuilder(androidx.navigation.ActivityNavigator navigator, kotlin.reflect.KClass<?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public androidx.navigation.ActivityNavigator.Destination build();
+    method public String? getAction();
+    method public kotlin.reflect.KClass<? extends android.app.Activity>? getActivityClass();
+    method public android.net.Uri? getData();
+    method public String? getDataPattern();
+    method public String? getTargetPackage();
+    method public void setAction(String?);
+    method public void setActivityClass(kotlin.reflect.KClass<? extends android.app.Activity>?);
+    method public void setData(android.net.Uri?);
+    method public void setDataPattern(String?);
+    method public void setTargetPackage(String?);
+    property public final String? action;
+    property public final kotlin.reflect.KClass<? extends android.app.Activity>? activityClass;
+    property public final android.net.Uri? data;
+    property public final String? dataPattern;
+    property public final String? targetPackage;
+  }
+
+  public final class ActivityNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline void activity(androidx.navigation.NavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.ActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline void activity(androidx.navigation.NavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.ActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void activity(androidx.navigation.NavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.ActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+  }
+
+  public final class ActivityNavigatorExtrasKt {
+    method public static androidx.navigation.ActivityNavigator.Extras ActivityNavigatorExtras(optional androidx.core.app.ActivityOptionsCompat? activityOptions, optional int flags);
+  }
+
+  public class NavController {
+    ctor public NavController(android.content.Context context);
+    method public void addOnDestinationChangedListener(androidx.navigation.NavController.OnDestinationChangedListener listener);
+    method @MainThread public inline <reified T> boolean clearBackStack();
+    method @MainThread public final boolean clearBackStack(@IdRes int destinationId);
+    method @MainThread public final boolean clearBackStack(String route);
+    method @MainThread public final <T> boolean clearBackStack(T route);
+    method public androidx.navigation.NavDeepLinkBuilder createDeepLink();
+    method @SuppressCompatibility @androidx.navigation.NavDeepLinkSaveStateControl public static final void enableDeepLinkSaveState(boolean saveState);
+    method public inline <reified T> androidx.navigation.NavBackStackEntry getBackStackEntry();
+    method public androidx.navigation.NavBackStackEntry getBackStackEntry(@IdRes int destinationId);
+    method public final androidx.navigation.NavBackStackEntry getBackStackEntry(String route);
+    method public final <T> androidx.navigation.NavBackStackEntry getBackStackEntry(T route);
+    method public androidx.navigation.NavBackStackEntry? getCurrentBackStackEntry();
+    method public final kotlinx.coroutines.flow.Flow<androidx.navigation.NavBackStackEntry> getCurrentBackStackEntryFlow();
+    method public androidx.navigation.NavDestination? getCurrentDestination();
+    method @MainThread public androidx.navigation.NavGraph getGraph();
+    method public androidx.navigation.NavInflater getNavInflater();
+    method public androidx.navigation.NavigatorProvider getNavigatorProvider();
+    method public androidx.navigation.NavBackStackEntry? getPreviousBackStackEntry();
+    method public androidx.lifecycle.ViewModelStoreOwner getViewModelStoreOwner(@IdRes int navGraphId);
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getVisibleEntries();
+    method @MainThread public boolean handleDeepLink(android.content.Intent? intent);
+    method @MainThread public void navigate(android.net.Uri deepLink);
+    method @MainThread public void navigate(android.net.Uri deepLink, androidx.navigation.NavOptions? navOptions);
+    method @MainThread public void navigate(android.net.Uri deepLink, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public void navigate(androidx.navigation.NavDeepLinkRequest request);
+    method @MainThread public void navigate(androidx.navigation.NavDeepLinkRequest request, androidx.navigation.NavOptions? navOptions);
+    method @MainThread public void navigate(androidx.navigation.NavDeepLinkRequest request, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public void navigate(androidx.navigation.NavDirections directions);
+    method @MainThread public void navigate(androidx.navigation.NavDirections directions, androidx.navigation.Navigator.Extras navigatorExtras);
+    method @MainThread public void navigate(androidx.navigation.NavDirections directions, androidx.navigation.NavOptions? navOptions);
+    method @MainThread public void navigate(@IdRes int resId);
+    method @MainThread public void navigate(@IdRes int resId, android.os.Bundle? args);
+    method @MainThread public void navigate(@IdRes int resId, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions);
+    method @MainThread public void navigate(@IdRes int resId, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public final void navigate(String route);
+    method @MainThread public final void navigate(String route, optional androidx.navigation.NavOptions? navOptions);
+    method @MainThread public final void navigate(String route, optional androidx.navigation.NavOptions? navOptions, optional androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public final void navigate(String route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavOptionsBuilder,kotlin.Unit> builder);
+    method @MainThread public final <T> void navigate(T route);
+    method @MainThread public final <T> void navigate(T route, optional androidx.navigation.NavOptions? navOptions);
+    method @MainThread public final <T> void navigate(T route, optional androidx.navigation.NavOptions? navOptions, optional androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public final <T> void navigate(T route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavOptionsBuilder,kotlin.Unit> builder);
+    method @MainThread public boolean navigateUp();
+    method @MainThread public boolean popBackStack();
+    method @MainThread public inline <reified T> boolean popBackStack(boolean inclusive, optional boolean saveState);
+    method @MainThread public boolean popBackStack(@IdRes int destinationId, boolean inclusive);
+    method @MainThread public boolean popBackStack(@IdRes int destinationId, boolean inclusive, boolean saveState);
+    method @MainThread public final boolean popBackStack(String route, boolean inclusive);
+    method @MainThread public final boolean popBackStack(String route, boolean inclusive, optional boolean saveState);
+    method @MainThread public final <T> boolean popBackStack(T route, boolean inclusive);
+    method @MainThread public final <T> boolean popBackStack(T route, boolean inclusive, optional boolean saveState);
+    method public void removeOnDestinationChangedListener(androidx.navigation.NavController.OnDestinationChangedListener listener);
+    method @CallSuper public void restoreState(android.os.Bundle? navState);
+    method @CallSuper public android.os.Bundle? saveState();
+    method @CallSuper @MainThread public void setGraph(androidx.navigation.NavGraph);
+    method @CallSuper @MainThread public void setGraph(androidx.navigation.NavGraph graph, android.os.Bundle? startDestinationArgs);
+    method @CallSuper @MainThread public void setGraph(@NavigationRes int graphResId);
+    method @CallSuper @MainThread public void setGraph(@NavigationRes int graphResId, android.os.Bundle? startDestinationArgs);
+    property public androidx.navigation.NavBackStackEntry? currentBackStackEntry;
+    property public final kotlinx.coroutines.flow.Flow<androidx.navigation.NavBackStackEntry> currentBackStackEntryFlow;
+    property public androidx.navigation.NavDestination? currentDestination;
+    property @MainThread public androidx.navigation.NavGraph graph;
+    property public androidx.navigation.NavInflater navInflater;
+    property public androidx.navigation.NavigatorProvider navigatorProvider;
+    property public androidx.navigation.NavBackStackEntry? previousBackStackEntry;
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> visibleEntries;
+    field public static final androidx.navigation.NavController.Companion Companion;
+    field public static final String KEY_DEEP_LINK_INTENT = "android-support-nav:controller:deepLinkIntent";
+  }
+
+  public static final class NavController.Companion {
+    method @SuppressCompatibility @androidx.navigation.NavDeepLinkSaveStateControl public void enableDeepLinkSaveState(boolean saveState);
+  }
+
+  public static fun interface NavController.OnDestinationChangedListener {
+    method public void onDestinationChanged(androidx.navigation.NavController controller, androidx.navigation.NavDestination destination, android.os.Bundle? arguments);
+  }
+
+  public final class NavControllerKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, Object startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavDeepLinkBuilder {
+    ctor public NavDeepLinkBuilder(android.content.Context context);
+    method public androidx.navigation.NavDeepLinkBuilder addDestination(@IdRes int destId);
+    method public androidx.navigation.NavDeepLinkBuilder addDestination(@IdRes int destId, optional android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder addDestination(String route);
+    method public androidx.navigation.NavDeepLinkBuilder addDestination(String route, optional android.os.Bundle? args);
+    method public android.app.PendingIntent createPendingIntent();
+    method public androidx.core.app.TaskStackBuilder createTaskStackBuilder();
+    method public androidx.navigation.NavDeepLinkBuilder setArguments(android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder setComponentName(android.content.ComponentName componentName);
+    method public androidx.navigation.NavDeepLinkBuilder setComponentName(Class<? extends android.app.Activity?> activityClass);
+    method public androidx.navigation.NavDeepLinkBuilder setDestination(@IdRes int destId);
+    method public androidx.navigation.NavDeepLinkBuilder setDestination(@IdRes int destId, optional android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder setDestination(String destRoute);
+    method public androidx.navigation.NavDeepLinkBuilder setDestination(String destRoute, optional android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder setGraph(androidx.navigation.NavGraph navGraph);
+    method public androidx.navigation.NavDeepLinkBuilder setGraph(@NavigationRes int navGraphId);
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn(level=kotlin.RequiresOptIn.Level.WARNING) @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=kotlin.annotation.AnnotationTarget.FUNCTION) public @interface NavDeepLinkSaveStateControl {
+  }
+
+  public interface NavHost {
+    method public androidx.navigation.NavController getNavController();
+    property public abstract androidx.navigation.NavController navController;
+  }
+
+  public class NavHostController extends androidx.navigation.NavController {
+    ctor public NavHostController(android.content.Context context);
+    method public final void enableOnBackPressed(boolean enabled);
+    method public final void setLifecycleOwner(androidx.lifecycle.LifecycleOwner owner);
+    method public final void setOnBackPressedDispatcher(androidx.activity.OnBackPressedDispatcher dispatcher);
+    method public final void setViewModelStore(androidx.lifecycle.ViewModelStore viewModelStore);
+  }
+
+  public final class NavHostKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, Object startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavInflater {
+    ctor public NavInflater(android.content.Context context, androidx.navigation.NavigatorProvider navigatorProvider);
+    method public androidx.navigation.NavGraph inflate(@NavigationRes int graphResId);
+    field public static final androidx.navigation.NavInflater.Companion Companion;
+  }
+
+  public static final class NavInflater.Companion {
+  }
+
+  public final class Navigation {
+    method public static android.view.View.OnClickListener createNavigateOnClickListener(androidx.navigation.NavDirections directions);
+    method public static android.view.View.OnClickListener createNavigateOnClickListener(@IdRes int resId);
+    method public static android.view.View.OnClickListener createNavigateOnClickListener(@IdRes int resId, optional android.os.Bundle? args);
+    method public static androidx.navigation.NavController findNavController(android.app.Activity activity, @IdRes int viewId);
+    method public static androidx.navigation.NavController findNavController(android.view.View view);
+    method public static void setViewNavController(android.view.View view, androidx.navigation.NavController? controller);
+    field public static final androidx.navigation.Navigation INSTANCE;
+  }
+
+  public final class ViewKt {
+    method public static androidx.navigation.NavController findNavController(android.view.View);
+  }
+
+}
+
diff --git a/navigation/navigation-runtime/api/res-2.8.0-beta04.txt b/navigation/navigation-runtime/api/res-2.8.0-beta04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-runtime/api/res-2.8.0-beta04.txt
diff --git a/navigation/navigation-runtime/api/res-2.8.0-beta05.txt b/navigation/navigation-runtime/api/res-2.8.0-beta05.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-runtime/api/res-2.8.0-beta05.txt
diff --git a/navigation/navigation-runtime/api/restricted_2.8.0-beta04.txt b/navigation/navigation-runtime/api/restricted_2.8.0-beta04.txt
new file mode 100644
index 0000000..b801964
--- /dev/null
+++ b/navigation/navigation-runtime/api/restricted_2.8.0-beta04.txt
@@ -0,0 +1,246 @@
+// Signature format: 4.0
+package androidx.navigation {
+
+  public final class ActivityKt {
+    method public static androidx.navigation.NavController findNavController(android.app.Activity, @IdRes int viewId);
+  }
+
+  public final class ActivityNavArgsLazyKt {
+    method @MainThread public static inline <reified Args extends androidx.navigation.NavArgs> androidx.navigation.NavArgsLazy<Args> navArgs(android.app.Activity);
+  }
+
+  @androidx.navigation.Navigator.Name("activity") public class ActivityNavigator extends androidx.navigation.Navigator<androidx.navigation.ActivityNavigator.Destination> {
+    ctor public ActivityNavigator(android.content.Context context);
+    method public static final void applyPopAnimationsToPendingTransition(android.app.Activity activity);
+    method public androidx.navigation.ActivityNavigator.Destination createDestination();
+    method public androidx.navigation.NavDestination? navigate(androidx.navigation.ActivityNavigator.Destination destination, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    field public static final androidx.navigation.ActivityNavigator.Companion Companion;
+  }
+
+  public static final class ActivityNavigator.Companion {
+    method public void applyPopAnimationsToPendingTransition(android.app.Activity activity);
+  }
+
+  @androidx.navigation.NavDestination.ClassType(Activity::class) public static class ActivityNavigator.Destination extends androidx.navigation.NavDestination {
+    ctor public ActivityNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.ActivityNavigator.Destination> activityNavigator);
+    ctor public ActivityNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public final String? getAction();
+    method public final android.content.ComponentName? getComponent();
+    method public final android.net.Uri? getData();
+    method public final String? getDataPattern();
+    method public final android.content.Intent? getIntent();
+    method public final String? getTargetPackage();
+    method public final androidx.navigation.ActivityNavigator.Destination setAction(String? action);
+    method public final androidx.navigation.ActivityNavigator.Destination setComponentName(android.content.ComponentName? name);
+    method public final androidx.navigation.ActivityNavigator.Destination setData(android.net.Uri? data);
+    method public final androidx.navigation.ActivityNavigator.Destination setDataPattern(String? dataPattern);
+    method public final androidx.navigation.ActivityNavigator.Destination setIntent(android.content.Intent? intent);
+    method public final androidx.navigation.ActivityNavigator.Destination setTargetPackage(String? packageName);
+    property public final String? action;
+    property public final android.content.ComponentName? component;
+    property public final android.net.Uri? data;
+    property public final String? dataPattern;
+    property public final android.content.Intent? intent;
+    property public final String? targetPackage;
+  }
+
+  public static final class ActivityNavigator.Extras implements androidx.navigation.Navigator.Extras {
+    method public androidx.core.app.ActivityOptionsCompat? getActivityOptions();
+    method public int getFlags();
+    property public final androidx.core.app.ActivityOptionsCompat? activityOptions;
+    property public final int flags;
+  }
+
+  public static final class ActivityNavigator.Extras.Builder {
+    ctor public ActivityNavigator.Extras.Builder();
+    method public androidx.navigation.ActivityNavigator.Extras.Builder addFlags(int flags);
+    method public androidx.navigation.ActivityNavigator.Extras build();
+    method public androidx.navigation.ActivityNavigator.Extras.Builder setActivityOptions(androidx.core.app.ActivityOptionsCompat activityOptions);
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class ActivityNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.ActivityNavigator.Destination> {
+    ctor @Deprecated public ActivityNavigatorDestinationBuilder(androidx.navigation.ActivityNavigator navigator, @IdRes int id);
+    ctor public ActivityNavigatorDestinationBuilder(androidx.navigation.ActivityNavigator navigator, String route);
+    ctor public ActivityNavigatorDestinationBuilder(androidx.navigation.ActivityNavigator navigator, kotlin.reflect.KClass<?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public androidx.navigation.ActivityNavigator.Destination build();
+    method public String? getAction();
+    method public kotlin.reflect.KClass<? extends android.app.Activity>? getActivityClass();
+    method public android.net.Uri? getData();
+    method public String? getDataPattern();
+    method public String? getTargetPackage();
+    method public void setAction(String?);
+    method public void setActivityClass(kotlin.reflect.KClass<? extends android.app.Activity>?);
+    method public void setData(android.net.Uri?);
+    method public void setDataPattern(String?);
+    method public void setTargetPackage(String?);
+    property public final String? action;
+    property public final kotlin.reflect.KClass<? extends android.app.Activity>? activityClass;
+    property public final android.net.Uri? data;
+    property public final String? dataPattern;
+    property public final String? targetPackage;
+  }
+
+  public final class ActivityNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline void activity(androidx.navigation.NavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.ActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline void activity(androidx.navigation.NavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.ActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void activity(androidx.navigation.NavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.ActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+  }
+
+  public final class ActivityNavigatorExtrasKt {
+    method public static androidx.navigation.ActivityNavigator.Extras ActivityNavigatorExtras(optional androidx.core.app.ActivityOptionsCompat? activityOptions, optional int flags);
+  }
+
+  public class NavController {
+    ctor public NavController(android.content.Context context);
+    method public void addOnDestinationChangedListener(androidx.navigation.NavController.OnDestinationChangedListener listener);
+    method @MainThread public inline <reified T> boolean clearBackStack();
+    method @MainThread public final boolean clearBackStack(@IdRes int destinationId);
+    method @MainThread public final boolean clearBackStack(String route);
+    method @MainThread public final <T> boolean clearBackStack(T route);
+    method public androidx.navigation.NavDeepLinkBuilder createDeepLink();
+    method @SuppressCompatibility @androidx.navigation.NavDeepLinkSaveStateControl public static final void enableDeepLinkSaveState(boolean saveState);
+    method public inline <reified T> androidx.navigation.NavBackStackEntry getBackStackEntry();
+    method public androidx.navigation.NavBackStackEntry getBackStackEntry(@IdRes int destinationId);
+    method public final androidx.navigation.NavBackStackEntry getBackStackEntry(String route);
+    method public final <T> androidx.navigation.NavBackStackEntry getBackStackEntry(T route);
+    method public androidx.navigation.NavBackStackEntry? getCurrentBackStackEntry();
+    method public final kotlinx.coroutines.flow.Flow<androidx.navigation.NavBackStackEntry> getCurrentBackStackEntryFlow();
+    method public androidx.navigation.NavDestination? getCurrentDestination();
+    method @MainThread public androidx.navigation.NavGraph getGraph();
+    method public androidx.navigation.NavInflater getNavInflater();
+    method public androidx.navigation.NavigatorProvider getNavigatorProvider();
+    method public androidx.navigation.NavBackStackEntry? getPreviousBackStackEntry();
+    method public androidx.lifecycle.ViewModelStoreOwner getViewModelStoreOwner(@IdRes int navGraphId);
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getVisibleEntries();
+    method @MainThread public boolean handleDeepLink(android.content.Intent? intent);
+    method @MainThread public void navigate(android.net.Uri deepLink);
+    method @MainThread public void navigate(android.net.Uri deepLink, androidx.navigation.NavOptions? navOptions);
+    method @MainThread public void navigate(android.net.Uri deepLink, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public void navigate(androidx.navigation.NavDeepLinkRequest request);
+    method @MainThread public void navigate(androidx.navigation.NavDeepLinkRequest request, androidx.navigation.NavOptions? navOptions);
+    method @MainThread public void navigate(androidx.navigation.NavDeepLinkRequest request, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public void navigate(androidx.navigation.NavDirections directions);
+    method @MainThread public void navigate(androidx.navigation.NavDirections directions, androidx.navigation.Navigator.Extras navigatorExtras);
+    method @MainThread public void navigate(androidx.navigation.NavDirections directions, androidx.navigation.NavOptions? navOptions);
+    method @MainThread public void navigate(@IdRes int resId);
+    method @MainThread public void navigate(@IdRes int resId, android.os.Bundle? args);
+    method @MainThread public void navigate(@IdRes int resId, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions);
+    method @MainThread public void navigate(@IdRes int resId, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public final void navigate(String route);
+    method @MainThread public final void navigate(String route, optional androidx.navigation.NavOptions? navOptions);
+    method @MainThread public final void navigate(String route, optional androidx.navigation.NavOptions? navOptions, optional androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public final void navigate(String route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavOptionsBuilder,kotlin.Unit> builder);
+    method @MainThread public final <T> void navigate(T route);
+    method @MainThread public final <T> void navigate(T route, optional androidx.navigation.NavOptions? navOptions);
+    method @MainThread public final <T> void navigate(T route, optional androidx.navigation.NavOptions? navOptions, optional androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public final <T> void navigate(T route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavOptionsBuilder,kotlin.Unit> builder);
+    method @MainThread public boolean navigateUp();
+    method @MainThread public boolean popBackStack();
+    method @MainThread public inline <reified T> boolean popBackStack(boolean inclusive, optional boolean saveState);
+    method @MainThread public boolean popBackStack(@IdRes int destinationId, boolean inclusive);
+    method @MainThread public boolean popBackStack(@IdRes int destinationId, boolean inclusive, boolean saveState);
+    method @MainThread public final boolean popBackStack(String route, boolean inclusive);
+    method @MainThread public final boolean popBackStack(String route, boolean inclusive, optional boolean saveState);
+    method @MainThread public final <T> boolean popBackStack(T route, boolean inclusive);
+    method @MainThread public final <T> boolean popBackStack(T route, boolean inclusive, optional boolean saveState);
+    method public void removeOnDestinationChangedListener(androidx.navigation.NavController.OnDestinationChangedListener listener);
+    method @CallSuper public void restoreState(android.os.Bundle? navState);
+    method @CallSuper public android.os.Bundle? saveState();
+    method @CallSuper @MainThread public void setGraph(androidx.navigation.NavGraph);
+    method @CallSuper @MainThread public void setGraph(androidx.navigation.NavGraph graph, android.os.Bundle? startDestinationArgs);
+    method @CallSuper @MainThread public void setGraph(@NavigationRes int graphResId);
+    method @CallSuper @MainThread public void setGraph(@NavigationRes int graphResId, android.os.Bundle? startDestinationArgs);
+    property public androidx.navigation.NavBackStackEntry? currentBackStackEntry;
+    property public final kotlinx.coroutines.flow.Flow<androidx.navigation.NavBackStackEntry> currentBackStackEntryFlow;
+    property public androidx.navigation.NavDestination? currentDestination;
+    property @MainThread public androidx.navigation.NavGraph graph;
+    property public androidx.navigation.NavInflater navInflater;
+    property public androidx.navigation.NavigatorProvider navigatorProvider;
+    property public androidx.navigation.NavBackStackEntry? previousBackStackEntry;
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> visibleEntries;
+    field public static final androidx.navigation.NavController.Companion Companion;
+    field public static final String KEY_DEEP_LINK_INTENT = "android-support-nav:controller:deepLinkIntent";
+  }
+
+  public static final class NavController.Companion {
+    method @SuppressCompatibility @androidx.navigation.NavDeepLinkSaveStateControl public void enableDeepLinkSaveState(boolean saveState);
+  }
+
+  public static fun interface NavController.OnDestinationChangedListener {
+    method public void onDestinationChanged(androidx.navigation.NavController controller, androidx.navigation.NavDestination destination, android.os.Bundle? arguments);
+  }
+
+  public final class NavControllerKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, Object startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavDeepLinkBuilder {
+    ctor public NavDeepLinkBuilder(android.content.Context context);
+    method public androidx.navigation.NavDeepLinkBuilder addDestination(@IdRes int destId);
+    method public androidx.navigation.NavDeepLinkBuilder addDestination(@IdRes int destId, optional android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder addDestination(String route);
+    method public androidx.navigation.NavDeepLinkBuilder addDestination(String route, optional android.os.Bundle? args);
+    method public android.app.PendingIntent createPendingIntent();
+    method public androidx.core.app.TaskStackBuilder createTaskStackBuilder();
+    method public androidx.navigation.NavDeepLinkBuilder setArguments(android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder setComponentName(android.content.ComponentName componentName);
+    method public androidx.navigation.NavDeepLinkBuilder setComponentName(Class<? extends android.app.Activity?> activityClass);
+    method public androidx.navigation.NavDeepLinkBuilder setDestination(@IdRes int destId);
+    method public androidx.navigation.NavDeepLinkBuilder setDestination(@IdRes int destId, optional android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder setDestination(String destRoute);
+    method public androidx.navigation.NavDeepLinkBuilder setDestination(String destRoute, optional android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder setGraph(androidx.navigation.NavGraph navGraph);
+    method public androidx.navigation.NavDeepLinkBuilder setGraph(@NavigationRes int navGraphId);
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn(level=kotlin.RequiresOptIn.Level.WARNING) @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=kotlin.annotation.AnnotationTarget.FUNCTION) public @interface NavDeepLinkSaveStateControl {
+  }
+
+  public interface NavHost {
+    method public androidx.navigation.NavController getNavController();
+    property public abstract androidx.navigation.NavController navController;
+  }
+
+  public class NavHostController extends androidx.navigation.NavController {
+    ctor public NavHostController(android.content.Context context);
+    method public final void enableOnBackPressed(boolean enabled);
+    method public final void setLifecycleOwner(androidx.lifecycle.LifecycleOwner owner);
+    method public final void setOnBackPressedDispatcher(androidx.activity.OnBackPressedDispatcher dispatcher);
+    method public final void setViewModelStore(androidx.lifecycle.ViewModelStore viewModelStore);
+  }
+
+  public final class NavHostKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, Object startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavInflater {
+    ctor public NavInflater(android.content.Context context, androidx.navigation.NavigatorProvider navigatorProvider);
+    method public androidx.navigation.NavGraph inflate(@NavigationRes int graphResId);
+    field public static final androidx.navigation.NavInflater.Companion Companion;
+  }
+
+  public static final class NavInflater.Companion {
+  }
+
+  public final class Navigation {
+    method public static android.view.View.OnClickListener createNavigateOnClickListener(androidx.navigation.NavDirections directions);
+    method public static android.view.View.OnClickListener createNavigateOnClickListener(@IdRes int resId);
+    method public static android.view.View.OnClickListener createNavigateOnClickListener(@IdRes int resId, optional android.os.Bundle? args);
+    method public static androidx.navigation.NavController findNavController(android.app.Activity activity, @IdRes int viewId);
+    method public static androidx.navigation.NavController findNavController(android.view.View view);
+    method public static void setViewNavController(android.view.View view, androidx.navigation.NavController? controller);
+    field public static final androidx.navigation.Navigation INSTANCE;
+  }
+
+  public final class ViewKt {
+    method public static androidx.navigation.NavController findNavController(android.view.View);
+  }
+
+}
+
diff --git a/navigation/navigation-runtime/api/restricted_2.8.0-beta05.txt b/navigation/navigation-runtime/api/restricted_2.8.0-beta05.txt
new file mode 100644
index 0000000..b801964
--- /dev/null
+++ b/navigation/navigation-runtime/api/restricted_2.8.0-beta05.txt
@@ -0,0 +1,246 @@
+// Signature format: 4.0
+package androidx.navigation {
+
+  public final class ActivityKt {
+    method public static androidx.navigation.NavController findNavController(android.app.Activity, @IdRes int viewId);
+  }
+
+  public final class ActivityNavArgsLazyKt {
+    method @MainThread public static inline <reified Args extends androidx.navigation.NavArgs> androidx.navigation.NavArgsLazy<Args> navArgs(android.app.Activity);
+  }
+
+  @androidx.navigation.Navigator.Name("activity") public class ActivityNavigator extends androidx.navigation.Navigator<androidx.navigation.ActivityNavigator.Destination> {
+    ctor public ActivityNavigator(android.content.Context context);
+    method public static final void applyPopAnimationsToPendingTransition(android.app.Activity activity);
+    method public androidx.navigation.ActivityNavigator.Destination createDestination();
+    method public androidx.navigation.NavDestination? navigate(androidx.navigation.ActivityNavigator.Destination destination, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    field public static final androidx.navigation.ActivityNavigator.Companion Companion;
+  }
+
+  public static final class ActivityNavigator.Companion {
+    method public void applyPopAnimationsToPendingTransition(android.app.Activity activity);
+  }
+
+  @androidx.navigation.NavDestination.ClassType(Activity::class) public static class ActivityNavigator.Destination extends androidx.navigation.NavDestination {
+    ctor public ActivityNavigator.Destination(androidx.navigation.Navigator<? extends androidx.navigation.ActivityNavigator.Destination> activityNavigator);
+    ctor public ActivityNavigator.Destination(androidx.navigation.NavigatorProvider navigatorProvider);
+    method public final String? getAction();
+    method public final android.content.ComponentName? getComponent();
+    method public final android.net.Uri? getData();
+    method public final String? getDataPattern();
+    method public final android.content.Intent? getIntent();
+    method public final String? getTargetPackage();
+    method public final androidx.navigation.ActivityNavigator.Destination setAction(String? action);
+    method public final androidx.navigation.ActivityNavigator.Destination setComponentName(android.content.ComponentName? name);
+    method public final androidx.navigation.ActivityNavigator.Destination setData(android.net.Uri? data);
+    method public final androidx.navigation.ActivityNavigator.Destination setDataPattern(String? dataPattern);
+    method public final androidx.navigation.ActivityNavigator.Destination setIntent(android.content.Intent? intent);
+    method public final androidx.navigation.ActivityNavigator.Destination setTargetPackage(String? packageName);
+    property public final String? action;
+    property public final android.content.ComponentName? component;
+    property public final android.net.Uri? data;
+    property public final String? dataPattern;
+    property public final android.content.Intent? intent;
+    property public final String? targetPackage;
+  }
+
+  public static final class ActivityNavigator.Extras implements androidx.navigation.Navigator.Extras {
+    method public androidx.core.app.ActivityOptionsCompat? getActivityOptions();
+    method public int getFlags();
+    property public final androidx.core.app.ActivityOptionsCompat? activityOptions;
+    property public final int flags;
+  }
+
+  public static final class ActivityNavigator.Extras.Builder {
+    ctor public ActivityNavigator.Extras.Builder();
+    method public androidx.navigation.ActivityNavigator.Extras.Builder addFlags(int flags);
+    method public androidx.navigation.ActivityNavigator.Extras build();
+    method public androidx.navigation.ActivityNavigator.Extras.Builder setActivityOptions(androidx.core.app.ActivityOptionsCompat activityOptions);
+  }
+
+  @androidx.navigation.NavDestinationDsl public final class ActivityNavigatorDestinationBuilder extends androidx.navigation.NavDestinationBuilder<androidx.navigation.ActivityNavigator.Destination> {
+    ctor @Deprecated public ActivityNavigatorDestinationBuilder(androidx.navigation.ActivityNavigator navigator, @IdRes int id);
+    ctor public ActivityNavigatorDestinationBuilder(androidx.navigation.ActivityNavigator navigator, String route);
+    ctor public ActivityNavigatorDestinationBuilder(androidx.navigation.ActivityNavigator navigator, kotlin.reflect.KClass<?> route, java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+    method public androidx.navigation.ActivityNavigator.Destination build();
+    method public String? getAction();
+    method public kotlin.reflect.KClass<? extends android.app.Activity>? getActivityClass();
+    method public android.net.Uri? getData();
+    method public String? getDataPattern();
+    method public String? getTargetPackage();
+    method public void setAction(String?);
+    method public void setActivityClass(kotlin.reflect.KClass<? extends android.app.Activity>?);
+    method public void setData(android.net.Uri?);
+    method public void setDataPattern(String?);
+    method public void setTargetPackage(String?);
+    property public final String? action;
+    property public final kotlin.reflect.KClass<? extends android.app.Activity>? activityClass;
+    property public final android.net.Uri? data;
+    property public final String? dataPattern;
+    property public final String? targetPackage;
+  }
+
+  public final class ActivityNavigatorDestinationBuilderKt {
+    method @Deprecated public static inline void activity(androidx.navigation.NavGraphBuilder, @IdRes int id, kotlin.jvm.functions.Function1<? super androidx.navigation.ActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline void activity(androidx.navigation.NavGraphBuilder, String route, kotlin.jvm.functions.Function1<? super androidx.navigation.ActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+    method public static inline <reified T> void activity(androidx.navigation.NavGraphBuilder, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.ActivityNavigatorDestinationBuilder,kotlin.Unit> builder);
+  }
+
+  public final class ActivityNavigatorExtrasKt {
+    method public static androidx.navigation.ActivityNavigator.Extras ActivityNavigatorExtras(optional androidx.core.app.ActivityOptionsCompat? activityOptions, optional int flags);
+  }
+
+  public class NavController {
+    ctor public NavController(android.content.Context context);
+    method public void addOnDestinationChangedListener(androidx.navigation.NavController.OnDestinationChangedListener listener);
+    method @MainThread public inline <reified T> boolean clearBackStack();
+    method @MainThread public final boolean clearBackStack(@IdRes int destinationId);
+    method @MainThread public final boolean clearBackStack(String route);
+    method @MainThread public final <T> boolean clearBackStack(T route);
+    method public androidx.navigation.NavDeepLinkBuilder createDeepLink();
+    method @SuppressCompatibility @androidx.navigation.NavDeepLinkSaveStateControl public static final void enableDeepLinkSaveState(boolean saveState);
+    method public inline <reified T> androidx.navigation.NavBackStackEntry getBackStackEntry();
+    method public androidx.navigation.NavBackStackEntry getBackStackEntry(@IdRes int destinationId);
+    method public final androidx.navigation.NavBackStackEntry getBackStackEntry(String route);
+    method public final <T> androidx.navigation.NavBackStackEntry getBackStackEntry(T route);
+    method public androidx.navigation.NavBackStackEntry? getCurrentBackStackEntry();
+    method public final kotlinx.coroutines.flow.Flow<androidx.navigation.NavBackStackEntry> getCurrentBackStackEntryFlow();
+    method public androidx.navigation.NavDestination? getCurrentDestination();
+    method @MainThread public androidx.navigation.NavGraph getGraph();
+    method public androidx.navigation.NavInflater getNavInflater();
+    method public androidx.navigation.NavigatorProvider getNavigatorProvider();
+    method public androidx.navigation.NavBackStackEntry? getPreviousBackStackEntry();
+    method public androidx.lifecycle.ViewModelStoreOwner getViewModelStoreOwner(@IdRes int navGraphId);
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getVisibleEntries();
+    method @MainThread public boolean handleDeepLink(android.content.Intent? intent);
+    method @MainThread public void navigate(android.net.Uri deepLink);
+    method @MainThread public void navigate(android.net.Uri deepLink, androidx.navigation.NavOptions? navOptions);
+    method @MainThread public void navigate(android.net.Uri deepLink, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public void navigate(androidx.navigation.NavDeepLinkRequest request);
+    method @MainThread public void navigate(androidx.navigation.NavDeepLinkRequest request, androidx.navigation.NavOptions? navOptions);
+    method @MainThread public void navigate(androidx.navigation.NavDeepLinkRequest request, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public void navigate(androidx.navigation.NavDirections directions);
+    method @MainThread public void navigate(androidx.navigation.NavDirections directions, androidx.navigation.Navigator.Extras navigatorExtras);
+    method @MainThread public void navigate(androidx.navigation.NavDirections directions, androidx.navigation.NavOptions? navOptions);
+    method @MainThread public void navigate(@IdRes int resId);
+    method @MainThread public void navigate(@IdRes int resId, android.os.Bundle? args);
+    method @MainThread public void navigate(@IdRes int resId, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions);
+    method @MainThread public void navigate(@IdRes int resId, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public final void navigate(String route);
+    method @MainThread public final void navigate(String route, optional androidx.navigation.NavOptions? navOptions);
+    method @MainThread public final void navigate(String route, optional androidx.navigation.NavOptions? navOptions, optional androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public final void navigate(String route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavOptionsBuilder,kotlin.Unit> builder);
+    method @MainThread public final <T> void navigate(T route);
+    method @MainThread public final <T> void navigate(T route, optional androidx.navigation.NavOptions? navOptions);
+    method @MainThread public final <T> void navigate(T route, optional androidx.navigation.NavOptions? navOptions, optional androidx.navigation.Navigator.Extras? navigatorExtras);
+    method @MainThread public final <T> void navigate(T route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavOptionsBuilder,kotlin.Unit> builder);
+    method @MainThread public boolean navigateUp();
+    method @MainThread public boolean popBackStack();
+    method @MainThread public inline <reified T> boolean popBackStack(boolean inclusive, optional boolean saveState);
+    method @MainThread public boolean popBackStack(@IdRes int destinationId, boolean inclusive);
+    method @MainThread public boolean popBackStack(@IdRes int destinationId, boolean inclusive, boolean saveState);
+    method @MainThread public final boolean popBackStack(String route, boolean inclusive);
+    method @MainThread public final boolean popBackStack(String route, boolean inclusive, optional boolean saveState);
+    method @MainThread public final <T> boolean popBackStack(T route, boolean inclusive);
+    method @MainThread public final <T> boolean popBackStack(T route, boolean inclusive, optional boolean saveState);
+    method public void removeOnDestinationChangedListener(androidx.navigation.NavController.OnDestinationChangedListener listener);
+    method @CallSuper public void restoreState(android.os.Bundle? navState);
+    method @CallSuper public android.os.Bundle? saveState();
+    method @CallSuper @MainThread public void setGraph(androidx.navigation.NavGraph);
+    method @CallSuper @MainThread public void setGraph(androidx.navigation.NavGraph graph, android.os.Bundle? startDestinationArgs);
+    method @CallSuper @MainThread public void setGraph(@NavigationRes int graphResId);
+    method @CallSuper @MainThread public void setGraph(@NavigationRes int graphResId, android.os.Bundle? startDestinationArgs);
+    property public androidx.navigation.NavBackStackEntry? currentBackStackEntry;
+    property public final kotlinx.coroutines.flow.Flow<androidx.navigation.NavBackStackEntry> currentBackStackEntryFlow;
+    property public androidx.navigation.NavDestination? currentDestination;
+    property @MainThread public androidx.navigation.NavGraph graph;
+    property public androidx.navigation.NavInflater navInflater;
+    property public androidx.navigation.NavigatorProvider navigatorProvider;
+    property public androidx.navigation.NavBackStackEntry? previousBackStackEntry;
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> visibleEntries;
+    field public static final androidx.navigation.NavController.Companion Companion;
+    field public static final String KEY_DEEP_LINK_INTENT = "android-support-nav:controller:deepLinkIntent";
+  }
+
+  public static final class NavController.Companion {
+    method @SuppressCompatibility @androidx.navigation.NavDeepLinkSaveStateControl public void enableDeepLinkSaveState(boolean saveState);
+  }
+
+  public static fun interface NavController.OnDestinationChangedListener {
+    method public void onDestinationChanged(androidx.navigation.NavController controller, androidx.navigation.NavDestination destination, android.os.Bundle? arguments);
+  }
+
+  public final class NavControllerKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, Object startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavController, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavDeepLinkBuilder {
+    ctor public NavDeepLinkBuilder(android.content.Context context);
+    method public androidx.navigation.NavDeepLinkBuilder addDestination(@IdRes int destId);
+    method public androidx.navigation.NavDeepLinkBuilder addDestination(@IdRes int destId, optional android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder addDestination(String route);
+    method public androidx.navigation.NavDeepLinkBuilder addDestination(String route, optional android.os.Bundle? args);
+    method public android.app.PendingIntent createPendingIntent();
+    method public androidx.core.app.TaskStackBuilder createTaskStackBuilder();
+    method public androidx.navigation.NavDeepLinkBuilder setArguments(android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder setComponentName(android.content.ComponentName componentName);
+    method public androidx.navigation.NavDeepLinkBuilder setComponentName(Class<? extends android.app.Activity?> activityClass);
+    method public androidx.navigation.NavDeepLinkBuilder setDestination(@IdRes int destId);
+    method public androidx.navigation.NavDeepLinkBuilder setDestination(@IdRes int destId, optional android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder setDestination(String destRoute);
+    method public androidx.navigation.NavDeepLinkBuilder setDestination(String destRoute, optional android.os.Bundle? args);
+    method public androidx.navigation.NavDeepLinkBuilder setGraph(androidx.navigation.NavGraph navGraph);
+    method public androidx.navigation.NavDeepLinkBuilder setGraph(@NavigationRes int navGraphId);
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn(level=kotlin.RequiresOptIn.Level.WARNING) @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=kotlin.annotation.AnnotationTarget.FUNCTION) public @interface NavDeepLinkSaveStateControl {
+  }
+
+  public interface NavHost {
+    method public androidx.navigation.NavController getNavController();
+    property public abstract androidx.navigation.NavController navController;
+  }
+
+  public class NavHostController extends androidx.navigation.NavController {
+    ctor public NavHostController(android.content.Context context);
+    method public final void enableOnBackPressed(boolean enabled);
+    method public final void setLifecycleOwner(androidx.lifecycle.LifecycleOwner owner);
+    method public final void setOnBackPressedDispatcher(androidx.activity.OnBackPressedDispatcher dispatcher);
+    method public final void setViewModelStore(androidx.lifecycle.ViewModelStore viewModelStore);
+  }
+
+  public final class NavHostKt {
+    method @Deprecated public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, optional @IdRes int id, @IdRes int startDestination, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, Object startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, String startDestination, optional String? route, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+    method public static inline androidx.navigation.NavGraph createGraph(androidx.navigation.NavHost, kotlin.reflect.KClass<? extends java.lang.Object?> startDestination, optional kotlin.reflect.KClass<? extends java.lang.Object?>? route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap, kotlin.jvm.functions.Function1<? super androidx.navigation.NavGraphBuilder,kotlin.Unit> builder);
+  }
+
+  public final class NavInflater {
+    ctor public NavInflater(android.content.Context context, androidx.navigation.NavigatorProvider navigatorProvider);
+    method public androidx.navigation.NavGraph inflate(@NavigationRes int graphResId);
+    field public static final androidx.navigation.NavInflater.Companion Companion;
+  }
+
+  public static final class NavInflater.Companion {
+  }
+
+  public final class Navigation {
+    method public static android.view.View.OnClickListener createNavigateOnClickListener(androidx.navigation.NavDirections directions);
+    method public static android.view.View.OnClickListener createNavigateOnClickListener(@IdRes int resId);
+    method public static android.view.View.OnClickListener createNavigateOnClickListener(@IdRes int resId, optional android.os.Bundle? args);
+    method public static androidx.navigation.NavController findNavController(android.app.Activity activity, @IdRes int viewId);
+    method public static androidx.navigation.NavController findNavController(android.view.View view);
+    method public static void setViewNavController(android.view.View view, androidx.navigation.NavController? controller);
+    field public static final androidx.navigation.Navigation INSTANCE;
+  }
+
+  public final class ViewKt {
+    method public static androidx.navigation.NavController findNavController(android.view.View);
+  }
+
+}
+
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerRouteTest.kt b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerRouteTest.kt
index d3bf4ac..a408809 100644
--- a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerRouteTest.kt
+++ b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerRouteTest.kt
@@ -625,6 +625,130 @@
 
     @UiThreadTest
     @Test
+    fun testNavigateSingleTopSharedStartDestination() {
+        val navController = createNavController()
+        navController.graph =
+            navController.createGraph(route = "root", startDestination = "graph_one") {
+                navigation(route = "graph_one", startDestination = "shared_startDest") {
+                    test("shared_startDest")
+                }
+                navigation(route = "graph_two", startDestination = "shared_startDest") {
+                    test("shared_startDest")
+                }
+            }
+        assertThat(navController.currentBackStack.value.map { it.destination.route })
+            .containsExactly("root", "graph_one", "shared_startDest")
+            .inOrder()
+
+        navController.navigate("graph_one") { launchSingleTop = true }
+        assertThat(navController.currentBackStack.value.map { it.destination.route })
+            .containsExactly("root", "graph_one", "shared_startDest")
+            .inOrder()
+    }
+
+    @UiThreadTest
+    @Test
+    fun testNavigateSingleTopSharedStartDestinationDifferentGraph() {
+        val navController = createNavController()
+        navController.graph =
+            navController.createGraph(route = "root", startDestination = "graph_one") {
+                navigation(route = "graph_one", startDestination = "shared_startDest") {
+                    test("shared_startDest")
+                }
+                navigation(route = "graph_two", startDestination = "shared_startDest") {
+                    test("shared_startDest")
+                }
+            }
+        assertThat(navController.currentBackStack.value.map { it.destination.route })
+            .containsExactly("root", "graph_one", "shared_startDest")
+            .inOrder()
+
+        navController.navigate("graph_two") { launchSingleTop = true }
+        assertThat(navController.currentBackStack.value.map { it.destination.route })
+            .containsExactly(
+                "root",
+                "graph_one",
+                "shared_startDest",
+                "graph_two",
+                "shared_startDest"
+            )
+            .inOrder()
+
+        // should be single top
+        navController.navigate("graph_two") { launchSingleTop = true }
+        assertThat(navController.currentBackStack.value.map { it.destination.route })
+            .containsExactly(
+                "root",
+                "graph_one",
+                "shared_startDest",
+                "graph_two",
+                "shared_startDest"
+            )
+            .inOrder()
+    }
+
+    @UiThreadTest
+    @Test
+    fun testNavigateSingleTopSharedStartDestinationAlternatingGraph() {
+        val navController = createNavController()
+        navController.graph =
+            navController.createGraph(route = "root", startDestination = "graph_one") {
+                navigation(route = "graph_one", startDestination = "shared_startDest") {
+                    test("shared_startDest")
+                }
+                navigation(route = "graph_two", startDestination = "shared_startDest") {
+                    test("shared_startDest")
+                }
+            }
+        assertThat(navController.currentBackStack.value.map { it.destination.route })
+            .containsExactly("root", "graph_one", "shared_startDest")
+            .inOrder()
+
+        // go to different graph
+        navController.navigate("graph_two") { launchSingleTop = true }
+        assertThat(navController.currentBackStack.value.map { it.destination.route })
+            .containsExactly(
+                "root",
+                "graph_one",
+                "shared_startDest",
+                "graph_two",
+                "shared_startDest"
+            )
+            .inOrder()
+
+        // go back to original graph
+        navController.navigate("graph_one") { launchSingleTop = true }
+        // should not be single top
+        assertThat(navController.currentBackStack.value.map { it.destination.route })
+            .containsExactly(
+                "root",
+                "graph_one",
+                "shared_startDest",
+                "graph_two",
+                "shared_startDest",
+                "graph_one",
+                "shared_startDest",
+            )
+            .inOrder()
+
+        // single top to original graph again
+        navController.navigate("graph_one") { launchSingleTop = true }
+        // should be single top
+        assertThat(navController.currentBackStack.value.map { it.destination.route })
+            .containsExactly(
+                "root",
+                "graph_one",
+                "shared_startDest",
+                "graph_two",
+                "shared_startDest",
+                "graph_one",
+                "shared_startDest",
+            )
+            .inOrder()
+    }
+
+    @UiThreadTest
+    @Test
     @Suppress("DEPRECATION")
     fun testNavigateViaDeepLink() {
         val navController = createNavController()
diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt b/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
index 8234afa..537a184 100644
--- a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
+++ b/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
@@ -42,6 +42,7 @@
 import androidx.lifecycle.ViewModelStoreOwner
 import androidx.navigation.NavDestination.Companion.createRoute
 import androidx.navigation.NavDestination.Companion.hierarchy
+import androidx.navigation.NavGraph.Companion.childHierarchy
 import androidx.navigation.NavGraph.Companion.findStartDestination
 import androidx.navigation.serialization.generateHashCode
 import androidx.navigation.serialization.generateRouteWithArgs
@@ -1984,22 +1985,30 @@
 
     private fun launchSingleTopInternal(node: NavDestination, args: Bundle?): Boolean {
         val currentBackStackEntry = currentBackStackEntry
-        val nodeId = if (node is NavGraph) node.findStartDestination().id else node.id
-        if (nodeId != currentBackStackEntry?.destination?.id) return false
+        val nodeIndex = backQueue.indexOfLast { it.destination === node }
+        // early return when node isn't even in backQueue
+        if (nodeIndex == -1) return false
+        if (node is NavGraph) {
+            // get expected singleTop stack
+            val childHierarchyId = node.childHierarchy().map { it.id }.toList()
+            // if actual backQueue size does not match expected singleTop stack size, we know its
+            // not a single top
+            if (backQueue.size - nodeIndex != childHierarchyId.size) return false
+            val backQueueId = backQueue.subList(nodeIndex, backQueue.size).map { it.destination.id }
+            // then make sure the backstack and singleTop stack is exact match
+            if (backQueueId != childHierarchyId) return false
+        } else if (node.id != currentBackStackEntry?.destination?.id) {
+            return false
+        }
 
         val tempBackQueue: ArrayDeque<NavBackStackEntry> = ArrayDeque()
         // pop from startDestination back to original node and create a new entry for each
-        backQueue
-            .indexOfLast { it.destination === node }
-            .let { nodeIndex ->
-                while (backQueue.lastIndex >= nodeIndex) {
-                    val oldEntry = backQueue.removeLast()
-                    unlinkChildFromParent(oldEntry)
-                    val newEntry =
-                        NavBackStackEntry(oldEntry, oldEntry.destination.addInDefaultArgs(args))
-                    tempBackQueue.addFirst(newEntry)
-                }
-            }
+        while (backQueue.lastIndex >= nodeIndex) {
+            val oldEntry = backQueue.removeLast()
+            unlinkChildFromParent(oldEntry)
+            val newEntry = NavBackStackEntry(oldEntry, oldEntry.destination.addInDefaultArgs(args))
+            tempBackQueue.addFirst(newEntry)
+        }
 
         // add each new entry to backQueue starting from original node to startDestination
         tempBackQueue.forEach { newEntry ->
diff --git a/navigation/navigation-testing/api/2.8.0-beta04.txt b/navigation/navigation-testing/api/2.8.0-beta04.txt
new file mode 100644
index 0000000..ebd90df
--- /dev/null
+++ b/navigation/navigation-testing/api/2.8.0-beta04.txt
@@ -0,0 +1,27 @@
+// Signature format: 4.0
+package androidx.navigation.testing {
+
+  public final class SavedStateHandleFactoryKt {
+    method public static operator androidx.lifecycle.SavedStateHandle invoke(androidx.lifecycle.SavedStateHandle.Companion, Object route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+  }
+
+  public final class TestNavHostController extends androidx.navigation.NavHostController {
+    ctor public TestNavHostController(android.content.Context context);
+    method public java.util.List<androidx.navigation.NavBackStackEntry> getBackStack();
+    method public void setCurrentDestination(@IdRes int destId);
+    method public void setCurrentDestination(@IdRes int destId, optional android.os.Bundle args);
+    method public void setCurrentDestination(String destRoute);
+    method public void setCurrentDestination(String destRoute, optional android.os.Bundle args);
+    property public final java.util.List<androidx.navigation.NavBackStackEntry> backStack;
+  }
+
+  public final class TestNavigatorState extends androidx.navigation.NavigatorState {
+    ctor public TestNavigatorState();
+    ctor public TestNavigatorState(optional android.content.Context? context);
+    ctor public TestNavigatorState(optional android.content.Context? context, optional kotlinx.coroutines.CoroutineDispatcher coroutineDispatcher);
+    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/2.8.0-beta05.txt b/navigation/navigation-testing/api/2.8.0-beta05.txt
new file mode 100644
index 0000000..ebd90df
--- /dev/null
+++ b/navigation/navigation-testing/api/2.8.0-beta05.txt
@@ -0,0 +1,27 @@
+// Signature format: 4.0
+package androidx.navigation.testing {
+
+  public final class SavedStateHandleFactoryKt {
+    method public static operator androidx.lifecycle.SavedStateHandle invoke(androidx.lifecycle.SavedStateHandle.Companion, Object route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+  }
+
+  public final class TestNavHostController extends androidx.navigation.NavHostController {
+    ctor public TestNavHostController(android.content.Context context);
+    method public java.util.List<androidx.navigation.NavBackStackEntry> getBackStack();
+    method public void setCurrentDestination(@IdRes int destId);
+    method public void setCurrentDestination(@IdRes int destId, optional android.os.Bundle args);
+    method public void setCurrentDestination(String destRoute);
+    method public void setCurrentDestination(String destRoute, optional android.os.Bundle args);
+    property public final java.util.List<androidx.navigation.NavBackStackEntry> backStack;
+  }
+
+  public final class TestNavigatorState extends androidx.navigation.NavigatorState {
+    ctor public TestNavigatorState();
+    ctor public TestNavigatorState(optional android.content.Context? context);
+    ctor public TestNavigatorState(optional android.content.Context? context, optional kotlinx.coroutines.CoroutineDispatcher coroutineDispatcher);
+    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/res-2.8.0-beta04.txt b/navigation/navigation-testing/api/res-2.8.0-beta04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-testing/api/res-2.8.0-beta04.txt
diff --git a/navigation/navigation-testing/api/res-2.8.0-beta05.txt b/navigation/navigation-testing/api/res-2.8.0-beta05.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-testing/api/res-2.8.0-beta05.txt
diff --git a/navigation/navigation-testing/api/restricted_2.8.0-beta04.txt b/navigation/navigation-testing/api/restricted_2.8.0-beta04.txt
new file mode 100644
index 0000000..ebd90df
--- /dev/null
+++ b/navigation/navigation-testing/api/restricted_2.8.0-beta04.txt
@@ -0,0 +1,27 @@
+// Signature format: 4.0
+package androidx.navigation.testing {
+
+  public final class SavedStateHandleFactoryKt {
+    method public static operator androidx.lifecycle.SavedStateHandle invoke(androidx.lifecycle.SavedStateHandle.Companion, Object route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+  }
+
+  public final class TestNavHostController extends androidx.navigation.NavHostController {
+    ctor public TestNavHostController(android.content.Context context);
+    method public java.util.List<androidx.navigation.NavBackStackEntry> getBackStack();
+    method public void setCurrentDestination(@IdRes int destId);
+    method public void setCurrentDestination(@IdRes int destId, optional android.os.Bundle args);
+    method public void setCurrentDestination(String destRoute);
+    method public void setCurrentDestination(String destRoute, optional android.os.Bundle args);
+    property public final java.util.List<androidx.navigation.NavBackStackEntry> backStack;
+  }
+
+  public final class TestNavigatorState extends androidx.navigation.NavigatorState {
+    ctor public TestNavigatorState();
+    ctor public TestNavigatorState(optional android.content.Context? context);
+    ctor public TestNavigatorState(optional android.content.Context? context, optional kotlinx.coroutines.CoroutineDispatcher coroutineDispatcher);
+    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_2.8.0-beta05.txt b/navigation/navigation-testing/api/restricted_2.8.0-beta05.txt
new file mode 100644
index 0000000..ebd90df
--- /dev/null
+++ b/navigation/navigation-testing/api/restricted_2.8.0-beta05.txt
@@ -0,0 +1,27 @@
+// Signature format: 4.0
+package androidx.navigation.testing {
+
+  public final class SavedStateHandleFactoryKt {
+    method public static operator androidx.lifecycle.SavedStateHandle invoke(androidx.lifecycle.SavedStateHandle.Companion, Object route, optional java.util.Map<kotlin.reflect.KType,androidx.navigation.NavType<? extends java.lang.Object?>> typeMap);
+  }
+
+  public final class TestNavHostController extends androidx.navigation.NavHostController {
+    ctor public TestNavHostController(android.content.Context context);
+    method public java.util.List<androidx.navigation.NavBackStackEntry> getBackStack();
+    method public void setCurrentDestination(@IdRes int destId);
+    method public void setCurrentDestination(@IdRes int destId, optional android.os.Bundle args);
+    method public void setCurrentDestination(String destRoute);
+    method public void setCurrentDestination(String destRoute, optional android.os.Bundle args);
+    property public final java.util.List<androidx.navigation.NavBackStackEntry> backStack;
+  }
+
+  public final class TestNavigatorState extends androidx.navigation.NavigatorState {
+    ctor public TestNavigatorState();
+    ctor public TestNavigatorState(optional android.content.Context? context);
+    ctor public TestNavigatorState(optional android.content.Context? context, optional kotlinx.coroutines.CoroutineDispatcher coroutineDispatcher);
+    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-ui-ktx/api/2.8.0-beta04.txt b/navigation/navigation-ui-ktx/api/2.8.0-beta04.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/navigation/navigation-ui-ktx/api/2.8.0-beta04.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/navigation/navigation-ui-ktx/api/2.8.0-beta05.txt b/navigation/navigation-ui-ktx/api/2.8.0-beta05.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/navigation/navigation-ui-ktx/api/2.8.0-beta05.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/navigation/navigation-ui-ktx/api/res-2.8.0-beta04.txt b/navigation/navigation-ui-ktx/api/res-2.8.0-beta04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-ui-ktx/api/res-2.8.0-beta04.txt
diff --git a/navigation/navigation-ui-ktx/api/res-2.8.0-beta05.txt b/navigation/navigation-ui-ktx/api/res-2.8.0-beta05.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/navigation/navigation-ui-ktx/api/res-2.8.0-beta05.txt
diff --git a/navigation/navigation-ui-ktx/api/restricted_2.8.0-beta04.txt b/navigation/navigation-ui-ktx/api/restricted_2.8.0-beta04.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/navigation/navigation-ui-ktx/api/restricted_2.8.0-beta04.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/navigation/navigation-ui-ktx/api/restricted_2.8.0-beta05.txt b/navigation/navigation-ui-ktx/api/restricted_2.8.0-beta05.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/navigation/navigation-ui-ktx/api/restricted_2.8.0-beta05.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/navigation/navigation-ui/api/2.8.0-beta04.txt b/navigation/navigation-ui/api/2.8.0-beta04.txt
new file mode 100644
index 0000000..326d323
--- /dev/null
+++ b/navigation/navigation-ui/api/2.8.0-beta04.txt
@@ -0,0 +1,94 @@
+// Signature format: 4.0
+package androidx.navigation.ui {
+
+  public final class ActivityKt {
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity, androidx.navigation.NavController navController, androidx.drawerlayout.widget.DrawerLayout? drawerLayout);
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+  }
+
+  public final class AppBarConfiguration {
+    method @Deprecated public androidx.drawerlayout.widget.DrawerLayout? getDrawerLayout();
+    method public androidx.navigation.ui.AppBarConfiguration.OnNavigateUpListener? getFallbackOnNavigateUpListener();
+    method public androidx.customview.widget.Openable? getOpenableLayout();
+    method public java.util.Set<java.lang.Integer> getTopLevelDestinations();
+    method public boolean isTopLevelDestination(androidx.navigation.NavDestination destination);
+    property @Deprecated public final androidx.drawerlayout.widget.DrawerLayout? drawerLayout;
+    property public final androidx.navigation.ui.AppBarConfiguration.OnNavigateUpListener? fallbackOnNavigateUpListener;
+    property public final androidx.customview.widget.Openable? openableLayout;
+    property public final java.util.Set<java.lang.Integer> topLevelDestinations;
+  }
+
+  public static final class AppBarConfiguration.Builder {
+    ctor public AppBarConfiguration.Builder(android.view.Menu topLevelMenu);
+    ctor public AppBarConfiguration.Builder(androidx.navigation.NavGraph navGraph);
+    ctor public AppBarConfiguration.Builder(int... topLevelDestinationIds);
+    ctor public AppBarConfiguration.Builder(java.util.Set<java.lang.Integer> topLevelDestinationIds);
+    method public androidx.navigation.ui.AppBarConfiguration build();
+    method @Deprecated public androidx.navigation.ui.AppBarConfiguration.Builder setDrawerLayout(androidx.drawerlayout.widget.DrawerLayout? drawerLayout);
+    method public androidx.navigation.ui.AppBarConfiguration.Builder setFallbackOnNavigateUpListener(androidx.navigation.ui.AppBarConfiguration.OnNavigateUpListener? fallbackOnNavigateUpListener);
+    method public androidx.navigation.ui.AppBarConfiguration.Builder setOpenableLayout(androidx.customview.widget.Openable? openableLayout);
+  }
+
+  public static fun interface AppBarConfiguration.OnNavigateUpListener {
+    method public boolean onNavigateUp();
+  }
+
+  public final class AppBarConfigurationKt {
+    method public static inline androidx.navigation.ui.AppBarConfiguration AppBarConfiguration(android.view.Menu topLevelMenu, optional androidx.customview.widget.Openable? drawerLayout, optional kotlin.jvm.functions.Function0<java.lang.Boolean> fallbackOnNavigateUpListener);
+    method public static inline androidx.navigation.ui.AppBarConfiguration AppBarConfiguration(androidx.navigation.NavGraph navGraph, optional androidx.customview.widget.Openable? drawerLayout, optional kotlin.jvm.functions.Function0<java.lang.Boolean> fallbackOnNavigateUpListener);
+    method public static inline androidx.navigation.ui.AppBarConfiguration AppBarConfiguration(java.util.Set<java.lang.Integer> topLevelDestinationIds, optional androidx.customview.widget.Openable? drawerLayout, optional kotlin.jvm.functions.Function0<java.lang.Boolean> fallbackOnNavigateUpListener);
+  }
+
+  public final class BottomNavigationViewKt {
+    method public static void setupWithNavController(com.google.android.material.navigation.NavigationBarView, androidx.navigation.NavController navController);
+  }
+
+  public final class CollapsingToolbarLayoutKt {
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, androidx.drawerlayout.widget.DrawerLayout? drawerLayout);
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+  }
+
+  public final class MenuItemKt {
+    method public static boolean onNavDestinationSelected(android.view.MenuItem, androidx.navigation.NavController navController);
+  }
+
+  public final class NavControllerKt {
+    method public static boolean navigateUp(androidx.navigation.NavController, androidx.customview.widget.Openable? drawerLayout);
+    method public static boolean navigateUp(androidx.navigation.NavController, androidx.navigation.ui.AppBarConfiguration appBarConfiguration);
+  }
+
+  public final class NavigationUI {
+    method public static boolean navigateUp(androidx.navigation.NavController navController, androidx.customview.widget.Openable? openableLayout);
+    method public static boolean navigateUp(androidx.navigation.NavController navController, androidx.navigation.ui.AppBarConfiguration configuration);
+    method public static boolean onNavDestinationSelected(android.view.MenuItem item, androidx.navigation.NavController navController);
+    method @SuppressCompatibility @androidx.navigation.ui.NavigationUiSaveStateControl public static boolean onNavDestinationSelected(android.view.MenuItem item, androidx.navigation.NavController navController, boolean saveState);
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity activity, androidx.navigation.NavController navController);
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity activity, androidx.navigation.NavController navController, androidx.customview.widget.Openable? openableLayout);
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity activity, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController);
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, androidx.customview.widget.Openable? openableLayout);
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout collapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController);
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout collapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, androidx.customview.widget.Openable? openableLayout);
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout collapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+    method public static void setupWithNavController(com.google.android.material.navigation.NavigationBarView navigationBarView, androidx.navigation.NavController navController);
+    method @SuppressCompatibility @androidx.navigation.ui.NavigationUiSaveStateControl public static void setupWithNavController(com.google.android.material.navigation.NavigationBarView navigationBarView, androidx.navigation.NavController navController, boolean saveState);
+    method public static void setupWithNavController(com.google.android.material.navigation.NavigationView navigationView, androidx.navigation.NavController navController);
+    method @SuppressCompatibility @androidx.navigation.ui.NavigationUiSaveStateControl public static void setupWithNavController(com.google.android.material.navigation.NavigationView navigationView, androidx.navigation.NavController navController, boolean saveState);
+    field public static final androidx.navigation.ui.NavigationUI INSTANCE;
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn(level=kotlin.RequiresOptIn.Level.WARNING) @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=kotlin.annotation.AnnotationTarget.FUNCTION) public @interface NavigationUiSaveStateControl {
+  }
+
+  public final class NavigationViewKt {
+    method public static void setupWithNavController(com.google.android.material.navigation.NavigationView, androidx.navigation.NavController navController);
+  }
+
+  public final class ToolbarKt {
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar, androidx.navigation.NavController navController, androidx.drawerlayout.widget.DrawerLayout? drawerLayout);
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+  }
+
+}
+
diff --git a/navigation/navigation-ui/api/2.8.0-beta05.txt b/navigation/navigation-ui/api/2.8.0-beta05.txt
new file mode 100644
index 0000000..326d323
--- /dev/null
+++ b/navigation/navigation-ui/api/2.8.0-beta05.txt
@@ -0,0 +1,94 @@
+// Signature format: 4.0
+package androidx.navigation.ui {
+
+  public final class ActivityKt {
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity, androidx.navigation.NavController navController, androidx.drawerlayout.widget.DrawerLayout? drawerLayout);
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+  }
+
+  public final class AppBarConfiguration {
+    method @Deprecated public androidx.drawerlayout.widget.DrawerLayout? getDrawerLayout();
+    method public androidx.navigation.ui.AppBarConfiguration.OnNavigateUpListener? getFallbackOnNavigateUpListener();
+    method public androidx.customview.widget.Openable? getOpenableLayout();
+    method public java.util.Set<java.lang.Integer> getTopLevelDestinations();
+    method public boolean isTopLevelDestination(androidx.navigation.NavDestination destination);
+    property @Deprecated public final androidx.drawerlayout.widget.DrawerLayout? drawerLayout;
+    property public final androidx.navigation.ui.AppBarConfiguration.OnNavigateUpListener? fallbackOnNavigateUpListener;
+    property public final androidx.customview.widget.Openable? openableLayout;
+    property public final java.util.Set<java.lang.Integer> topLevelDestinations;
+  }
+
+  public static final class AppBarConfiguration.Builder {
+    ctor public AppBarConfiguration.Builder(android.view.Menu topLevelMenu);
+    ctor public AppBarConfiguration.Builder(androidx.navigation.NavGraph navGraph);
+    ctor public AppBarConfiguration.Builder(int... topLevelDestinationIds);
+    ctor public AppBarConfiguration.Builder(java.util.Set<java.lang.Integer> topLevelDestinationIds);
+    method public androidx.navigation.ui.AppBarConfiguration build();
+    method @Deprecated public androidx.navigation.ui.AppBarConfiguration.Builder setDrawerLayout(androidx.drawerlayout.widget.DrawerLayout? drawerLayout);
+    method public androidx.navigation.ui.AppBarConfiguration.Builder setFallbackOnNavigateUpListener(androidx.navigation.ui.AppBarConfiguration.OnNavigateUpListener? fallbackOnNavigateUpListener);
+    method public androidx.navigation.ui.AppBarConfiguration.Builder setOpenableLayout(androidx.customview.widget.Openable? openableLayout);
+  }
+
+  public static fun interface AppBarConfiguration.OnNavigateUpListener {
+    method public boolean onNavigateUp();
+  }
+
+  public final class AppBarConfigurationKt {
+    method public static inline androidx.navigation.ui.AppBarConfiguration AppBarConfiguration(android.view.Menu topLevelMenu, optional androidx.customview.widget.Openable? drawerLayout, optional kotlin.jvm.functions.Function0<java.lang.Boolean> fallbackOnNavigateUpListener);
+    method public static inline androidx.navigation.ui.AppBarConfiguration AppBarConfiguration(androidx.navigation.NavGraph navGraph, optional androidx.customview.widget.Openable? drawerLayout, optional kotlin.jvm.functions.Function0<java.lang.Boolean> fallbackOnNavigateUpListener);
+    method public static inline androidx.navigation.ui.AppBarConfiguration AppBarConfiguration(java.util.Set<java.lang.Integer> topLevelDestinationIds, optional androidx.customview.widget.Openable? drawerLayout, optional kotlin.jvm.functions.Function0<java.lang.Boolean> fallbackOnNavigateUpListener);
+  }
+
+  public final class BottomNavigationViewKt {
+    method public static void setupWithNavController(com.google.android.material.navigation.NavigationBarView, androidx.navigation.NavController navController);
+  }
+
+  public final class CollapsingToolbarLayoutKt {
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, androidx.drawerlayout.widget.DrawerLayout? drawerLayout);
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+  }
+
+  public final class MenuItemKt {
+    method public static boolean onNavDestinationSelected(android.view.MenuItem, androidx.navigation.NavController navController);
+  }
+
+  public final class NavControllerKt {
+    method public static boolean navigateUp(androidx.navigation.NavController, androidx.customview.widget.Openable? drawerLayout);
+    method public static boolean navigateUp(androidx.navigation.NavController, androidx.navigation.ui.AppBarConfiguration appBarConfiguration);
+  }
+
+  public final class NavigationUI {
+    method public static boolean navigateUp(androidx.navigation.NavController navController, androidx.customview.widget.Openable? openableLayout);
+    method public static boolean navigateUp(androidx.navigation.NavController navController, androidx.navigation.ui.AppBarConfiguration configuration);
+    method public static boolean onNavDestinationSelected(android.view.MenuItem item, androidx.navigation.NavController navController);
+    method @SuppressCompatibility @androidx.navigation.ui.NavigationUiSaveStateControl public static boolean onNavDestinationSelected(android.view.MenuItem item, androidx.navigation.NavController navController, boolean saveState);
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity activity, androidx.navigation.NavController navController);
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity activity, androidx.navigation.NavController navController, androidx.customview.widget.Openable? openableLayout);
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity activity, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController);
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, androidx.customview.widget.Openable? openableLayout);
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout collapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController);
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout collapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, androidx.customview.widget.Openable? openableLayout);
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout collapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+    method public static void setupWithNavController(com.google.android.material.navigation.NavigationBarView navigationBarView, androidx.navigation.NavController navController);
+    method @SuppressCompatibility @androidx.navigation.ui.NavigationUiSaveStateControl public static void setupWithNavController(com.google.android.material.navigation.NavigationBarView navigationBarView, androidx.navigation.NavController navController, boolean saveState);
+    method public static void setupWithNavController(com.google.android.material.navigation.NavigationView navigationView, androidx.navigation.NavController navController);
+    method @SuppressCompatibility @androidx.navigation.ui.NavigationUiSaveStateControl public static void setupWithNavController(com.google.android.material.navigation.NavigationView navigationView, androidx.navigation.NavController navController, boolean saveState);
+    field public static final androidx.navigation.ui.NavigationUI INSTANCE;
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn(level=kotlin.RequiresOptIn.Level.WARNING) @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=kotlin.annotation.AnnotationTarget.FUNCTION) public @interface NavigationUiSaveStateControl {
+  }
+
+  public final class NavigationViewKt {
+    method public static void setupWithNavController(com.google.android.material.navigation.NavigationView, androidx.navigation.NavController navController);
+  }
+
+  public final class ToolbarKt {
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar, androidx.navigation.NavController navController, androidx.drawerlayout.widget.DrawerLayout? drawerLayout);
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+  }
+
+}
+
diff --git a/navigation/navigation-ui/api/res-2.8.0-beta04.txt b/navigation/navigation-ui/api/res-2.8.0-beta04.txt
new file mode 100644
index 0000000..e65fdbe
--- /dev/null
+++ b/navigation/navigation-ui/api/res-2.8.0-beta04.txt
@@ -0,0 +1,8 @@
+anim nav_default_enter_anim
+anim nav_default_exit_anim
+anim nav_default_pop_enter_anim
+anim nav_default_pop_exit_anim
+animator nav_default_enter_anim
+animator nav_default_exit_anim
+animator nav_default_pop_enter_anim
+animator nav_default_pop_exit_anim
diff --git a/navigation/navigation-ui/api/res-2.8.0-beta05.txt b/navigation/navigation-ui/api/res-2.8.0-beta05.txt
new file mode 100644
index 0000000..e65fdbe
--- /dev/null
+++ b/navigation/navigation-ui/api/res-2.8.0-beta05.txt
@@ -0,0 +1,8 @@
+anim nav_default_enter_anim
+anim nav_default_exit_anim
+anim nav_default_pop_enter_anim
+anim nav_default_pop_exit_anim
+animator nav_default_enter_anim
+animator nav_default_exit_anim
+animator nav_default_pop_enter_anim
+animator nav_default_pop_exit_anim
diff --git a/navigation/navigation-ui/api/restricted_2.8.0-beta04.txt b/navigation/navigation-ui/api/restricted_2.8.0-beta04.txt
new file mode 100644
index 0000000..326d323
--- /dev/null
+++ b/navigation/navigation-ui/api/restricted_2.8.0-beta04.txt
@@ -0,0 +1,94 @@
+// Signature format: 4.0
+package androidx.navigation.ui {
+
+  public final class ActivityKt {
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity, androidx.navigation.NavController navController, androidx.drawerlayout.widget.DrawerLayout? drawerLayout);
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+  }
+
+  public final class AppBarConfiguration {
+    method @Deprecated public androidx.drawerlayout.widget.DrawerLayout? getDrawerLayout();
+    method public androidx.navigation.ui.AppBarConfiguration.OnNavigateUpListener? getFallbackOnNavigateUpListener();
+    method public androidx.customview.widget.Openable? getOpenableLayout();
+    method public java.util.Set<java.lang.Integer> getTopLevelDestinations();
+    method public boolean isTopLevelDestination(androidx.navigation.NavDestination destination);
+    property @Deprecated public final androidx.drawerlayout.widget.DrawerLayout? drawerLayout;
+    property public final androidx.navigation.ui.AppBarConfiguration.OnNavigateUpListener? fallbackOnNavigateUpListener;
+    property public final androidx.customview.widget.Openable? openableLayout;
+    property public final java.util.Set<java.lang.Integer> topLevelDestinations;
+  }
+
+  public static final class AppBarConfiguration.Builder {
+    ctor public AppBarConfiguration.Builder(android.view.Menu topLevelMenu);
+    ctor public AppBarConfiguration.Builder(androidx.navigation.NavGraph navGraph);
+    ctor public AppBarConfiguration.Builder(int... topLevelDestinationIds);
+    ctor public AppBarConfiguration.Builder(java.util.Set<java.lang.Integer> topLevelDestinationIds);
+    method public androidx.navigation.ui.AppBarConfiguration build();
+    method @Deprecated public androidx.navigation.ui.AppBarConfiguration.Builder setDrawerLayout(androidx.drawerlayout.widget.DrawerLayout? drawerLayout);
+    method public androidx.navigation.ui.AppBarConfiguration.Builder setFallbackOnNavigateUpListener(androidx.navigation.ui.AppBarConfiguration.OnNavigateUpListener? fallbackOnNavigateUpListener);
+    method public androidx.navigation.ui.AppBarConfiguration.Builder setOpenableLayout(androidx.customview.widget.Openable? openableLayout);
+  }
+
+  public static fun interface AppBarConfiguration.OnNavigateUpListener {
+    method public boolean onNavigateUp();
+  }
+
+  public final class AppBarConfigurationKt {
+    method public static inline androidx.navigation.ui.AppBarConfiguration AppBarConfiguration(android.view.Menu topLevelMenu, optional androidx.customview.widget.Openable? drawerLayout, optional kotlin.jvm.functions.Function0<java.lang.Boolean> fallbackOnNavigateUpListener);
+    method public static inline androidx.navigation.ui.AppBarConfiguration AppBarConfiguration(androidx.navigation.NavGraph navGraph, optional androidx.customview.widget.Openable? drawerLayout, optional kotlin.jvm.functions.Function0<java.lang.Boolean> fallbackOnNavigateUpListener);
+    method public static inline androidx.navigation.ui.AppBarConfiguration AppBarConfiguration(java.util.Set<java.lang.Integer> topLevelDestinationIds, optional androidx.customview.widget.Openable? drawerLayout, optional kotlin.jvm.functions.Function0<java.lang.Boolean> fallbackOnNavigateUpListener);
+  }
+
+  public final class BottomNavigationViewKt {
+    method public static void setupWithNavController(com.google.android.material.navigation.NavigationBarView, androidx.navigation.NavController navController);
+  }
+
+  public final class CollapsingToolbarLayoutKt {
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, androidx.drawerlayout.widget.DrawerLayout? drawerLayout);
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+  }
+
+  public final class MenuItemKt {
+    method public static boolean onNavDestinationSelected(android.view.MenuItem, androidx.navigation.NavController navController);
+  }
+
+  public final class NavControllerKt {
+    method public static boolean navigateUp(androidx.navigation.NavController, androidx.customview.widget.Openable? drawerLayout);
+    method public static boolean navigateUp(androidx.navigation.NavController, androidx.navigation.ui.AppBarConfiguration appBarConfiguration);
+  }
+
+  public final class NavigationUI {
+    method public static boolean navigateUp(androidx.navigation.NavController navController, androidx.customview.widget.Openable? openableLayout);
+    method public static boolean navigateUp(androidx.navigation.NavController navController, androidx.navigation.ui.AppBarConfiguration configuration);
+    method public static boolean onNavDestinationSelected(android.view.MenuItem item, androidx.navigation.NavController navController);
+    method @SuppressCompatibility @androidx.navigation.ui.NavigationUiSaveStateControl public static boolean onNavDestinationSelected(android.view.MenuItem item, androidx.navigation.NavController navController, boolean saveState);
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity activity, androidx.navigation.NavController navController);
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity activity, androidx.navigation.NavController navController, androidx.customview.widget.Openable? openableLayout);
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity activity, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController);
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, androidx.customview.widget.Openable? openableLayout);
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout collapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController);
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout collapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, androidx.customview.widget.Openable? openableLayout);
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout collapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+    method public static void setupWithNavController(com.google.android.material.navigation.NavigationBarView navigationBarView, androidx.navigation.NavController navController);
+    method @SuppressCompatibility @androidx.navigation.ui.NavigationUiSaveStateControl public static void setupWithNavController(com.google.android.material.navigation.NavigationBarView navigationBarView, androidx.navigation.NavController navController, boolean saveState);
+    method public static void setupWithNavController(com.google.android.material.navigation.NavigationView navigationView, androidx.navigation.NavController navController);
+    method @SuppressCompatibility @androidx.navigation.ui.NavigationUiSaveStateControl public static void setupWithNavController(com.google.android.material.navigation.NavigationView navigationView, androidx.navigation.NavController navController, boolean saveState);
+    field public static final androidx.navigation.ui.NavigationUI INSTANCE;
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn(level=kotlin.RequiresOptIn.Level.WARNING) @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=kotlin.annotation.AnnotationTarget.FUNCTION) public @interface NavigationUiSaveStateControl {
+  }
+
+  public final class NavigationViewKt {
+    method public static void setupWithNavController(com.google.android.material.navigation.NavigationView, androidx.navigation.NavController navController);
+  }
+
+  public final class ToolbarKt {
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar, androidx.navigation.NavController navController, androidx.drawerlayout.widget.DrawerLayout? drawerLayout);
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+  }
+
+}
+
diff --git a/navigation/navigation-ui/api/restricted_2.8.0-beta05.txt b/navigation/navigation-ui/api/restricted_2.8.0-beta05.txt
new file mode 100644
index 0000000..326d323
--- /dev/null
+++ b/navigation/navigation-ui/api/restricted_2.8.0-beta05.txt
@@ -0,0 +1,94 @@
+// Signature format: 4.0
+package androidx.navigation.ui {
+
+  public final class ActivityKt {
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity, androidx.navigation.NavController navController, androidx.drawerlayout.widget.DrawerLayout? drawerLayout);
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+  }
+
+  public final class AppBarConfiguration {
+    method @Deprecated public androidx.drawerlayout.widget.DrawerLayout? getDrawerLayout();
+    method public androidx.navigation.ui.AppBarConfiguration.OnNavigateUpListener? getFallbackOnNavigateUpListener();
+    method public androidx.customview.widget.Openable? getOpenableLayout();
+    method public java.util.Set<java.lang.Integer> getTopLevelDestinations();
+    method public boolean isTopLevelDestination(androidx.navigation.NavDestination destination);
+    property @Deprecated public final androidx.drawerlayout.widget.DrawerLayout? drawerLayout;
+    property public final androidx.navigation.ui.AppBarConfiguration.OnNavigateUpListener? fallbackOnNavigateUpListener;
+    property public final androidx.customview.widget.Openable? openableLayout;
+    property public final java.util.Set<java.lang.Integer> topLevelDestinations;
+  }
+
+  public static final class AppBarConfiguration.Builder {
+    ctor public AppBarConfiguration.Builder(android.view.Menu topLevelMenu);
+    ctor public AppBarConfiguration.Builder(androidx.navigation.NavGraph navGraph);
+    ctor public AppBarConfiguration.Builder(int... topLevelDestinationIds);
+    ctor public AppBarConfiguration.Builder(java.util.Set<java.lang.Integer> topLevelDestinationIds);
+    method public androidx.navigation.ui.AppBarConfiguration build();
+    method @Deprecated public androidx.navigation.ui.AppBarConfiguration.Builder setDrawerLayout(androidx.drawerlayout.widget.DrawerLayout? drawerLayout);
+    method public androidx.navigation.ui.AppBarConfiguration.Builder setFallbackOnNavigateUpListener(androidx.navigation.ui.AppBarConfiguration.OnNavigateUpListener? fallbackOnNavigateUpListener);
+    method public androidx.navigation.ui.AppBarConfiguration.Builder setOpenableLayout(androidx.customview.widget.Openable? openableLayout);
+  }
+
+  public static fun interface AppBarConfiguration.OnNavigateUpListener {
+    method public boolean onNavigateUp();
+  }
+
+  public final class AppBarConfigurationKt {
+    method public static inline androidx.navigation.ui.AppBarConfiguration AppBarConfiguration(android.view.Menu topLevelMenu, optional androidx.customview.widget.Openable? drawerLayout, optional kotlin.jvm.functions.Function0<java.lang.Boolean> fallbackOnNavigateUpListener);
+    method public static inline androidx.navigation.ui.AppBarConfiguration AppBarConfiguration(androidx.navigation.NavGraph navGraph, optional androidx.customview.widget.Openable? drawerLayout, optional kotlin.jvm.functions.Function0<java.lang.Boolean> fallbackOnNavigateUpListener);
+    method public static inline androidx.navigation.ui.AppBarConfiguration AppBarConfiguration(java.util.Set<java.lang.Integer> topLevelDestinationIds, optional androidx.customview.widget.Openable? drawerLayout, optional kotlin.jvm.functions.Function0<java.lang.Boolean> fallbackOnNavigateUpListener);
+  }
+
+  public final class BottomNavigationViewKt {
+    method public static void setupWithNavController(com.google.android.material.navigation.NavigationBarView, androidx.navigation.NavController navController);
+  }
+
+  public final class CollapsingToolbarLayoutKt {
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, androidx.drawerlayout.widget.DrawerLayout? drawerLayout);
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+  }
+
+  public final class MenuItemKt {
+    method public static boolean onNavDestinationSelected(android.view.MenuItem, androidx.navigation.NavController navController);
+  }
+
+  public final class NavControllerKt {
+    method public static boolean navigateUp(androidx.navigation.NavController, androidx.customview.widget.Openable? drawerLayout);
+    method public static boolean navigateUp(androidx.navigation.NavController, androidx.navigation.ui.AppBarConfiguration appBarConfiguration);
+  }
+
+  public final class NavigationUI {
+    method public static boolean navigateUp(androidx.navigation.NavController navController, androidx.customview.widget.Openable? openableLayout);
+    method public static boolean navigateUp(androidx.navigation.NavController navController, androidx.navigation.ui.AppBarConfiguration configuration);
+    method public static boolean onNavDestinationSelected(android.view.MenuItem item, androidx.navigation.NavController navController);
+    method @SuppressCompatibility @androidx.navigation.ui.NavigationUiSaveStateControl public static boolean onNavDestinationSelected(android.view.MenuItem item, androidx.navigation.NavController navController, boolean saveState);
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity activity, androidx.navigation.NavController navController);
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity activity, androidx.navigation.NavController navController, androidx.customview.widget.Openable? openableLayout);
+    method public static void setupActionBarWithNavController(androidx.appcompat.app.AppCompatActivity activity, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController);
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, androidx.customview.widget.Openable? openableLayout);
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout collapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController);
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout collapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, androidx.customview.widget.Openable? openableLayout);
+    method public static void setupWithNavController(com.google.android.material.appbar.CollapsingToolbarLayout collapsingToolbarLayout, androidx.appcompat.widget.Toolbar toolbar, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+    method public static void setupWithNavController(com.google.android.material.navigation.NavigationBarView navigationBarView, androidx.navigation.NavController navController);
+    method @SuppressCompatibility @androidx.navigation.ui.NavigationUiSaveStateControl public static void setupWithNavController(com.google.android.material.navigation.NavigationBarView navigationBarView, androidx.navigation.NavController navController, boolean saveState);
+    method public static void setupWithNavController(com.google.android.material.navigation.NavigationView navigationView, androidx.navigation.NavController navController);
+    method @SuppressCompatibility @androidx.navigation.ui.NavigationUiSaveStateControl public static void setupWithNavController(com.google.android.material.navigation.NavigationView navigationView, androidx.navigation.NavController navController, boolean saveState);
+    field public static final androidx.navigation.ui.NavigationUI INSTANCE;
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn(level=kotlin.RequiresOptIn.Level.WARNING) @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=kotlin.annotation.AnnotationTarget.FUNCTION) public @interface NavigationUiSaveStateControl {
+  }
+
+  public final class NavigationViewKt {
+    method public static void setupWithNavController(com.google.android.material.navigation.NavigationView, androidx.navigation.NavController navController);
+  }
+
+  public final class ToolbarKt {
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar, androidx.navigation.NavController navController, androidx.drawerlayout.widget.DrawerLayout? drawerLayout);
+    method public static void setupWithNavController(androidx.appcompat.widget.Toolbar, androidx.navigation.NavController navController, optional androidx.navigation.ui.AppBarConfiguration configuration);
+  }
+
+}
+
diff --git a/paging/paging-common/build.gradle b/paging/paging-common/build.gradle
index aa49e18..d47fe82 100644
--- a/paging/paging-common/build.gradle
+++ b/paging/paging-common/build.gradle
@@ -27,9 +27,9 @@
 import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
 import org.jetbrains.kotlin.konan.target.Family
 
-
 plugins {
     id("AndroidXPlugin")
+    id("com.android.library")
 }
 
 androidXMultiplatform {
@@ -39,14 +39,7 @@
     mac()
     linux()
     ios()
-    androidLibrary {
-        namespace = "androidx.paging.common"
-        withAndroidTestOnDeviceBuilder {
-            it.compilationName = "instrumentedTest"
-            it.defaultSourceSetName = "androidInstrumentedTest"
-            it.sourceSetTreeName = "test"
-        }
-    }
+    android()
 
     defaultPlatform(PlatformIdentifier.JVM)
 
@@ -153,3 +146,7 @@
     legacyDisableKotlinStrictApiMode = true
     samples(project(":paging:paging-samples"))
 }
+
+android {
+    namespace "androidx.paging.common"
+}
diff --git a/paging/paging-common/lint-baseline.xml b/paging/paging-common/lint-baseline.xml
deleted file mode 100644
index c592686..0000000
--- a/paging/paging-common/lint-baseline.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.6.0-alpha03" type="baseline" client="gradle" dependencies="false" name="AGP (8.6.0-alpha03)" variant="all" version="8.6.0-alpha03">
-
-    <issue
-        id="NewApi"
-        message="Call requires API level 26 (current min is 21): `java.util.regex.Matcher#start` (called from `kotlin.text.MatchGroupCollection#get(String)`)"
-        errorLine1="        fun pageDataFlowCount() = (counters[PAGED_DATA_FLOW] ?: error(&quot;unexpected&quot;)).get()"
-        errorLine2="                                                                                     ~~~">
-        <location
-            file="src/commonTest/kotlin/androidx/paging/CachingTest.kt"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level 26 (current min is 21): `java.util.regex.Matcher#start` (called from `kotlin.text.MatchGroupCollection#get(String)`)"
-        errorLine1="        fun pageEventFlowCount() = (counters[PAGE_EVENT_FLOW] ?: error(&quot;unexpected&quot;)).get()"
-        errorLine2="                                                                                      ~~~">
-        <location
-            file="src/commonTest/kotlin/androidx/paging/CachingTest.kt"/>
-    </issue>
-
-    <issue
-        id="BanThreadSleep"
-        message="Uses Thread.sleep()"
-        errorLine1="                Thread.sleep(1000)"
-        errorLine2="                       ~~~~~">
-        <location
-            file="src/commonJvmAndroidTest/kotlin/androidx/paging/PagedListTest.kt"/>
-    </issue>
-
-    <issue
-        id="BanThreadSleep"
-        message="Uses Thread.sleep()"
-        errorLine1="                    @Suppress(&quot;BlockingMethodInNonBlockingContext&quot;) Thread.sleep(100)"
-        errorLine2="                                                                           ~~~~~">
-        <location
-            file="src/commonJvmAndroidTest/kotlin/androidx/paging/SingleRunnerTest.kt"/>
-    </issue>
-
-</issues>
diff --git a/paging/paging-testing/build.gradle b/paging/paging-testing/build.gradle
index 66f3496..434fac4 100644
--- a/paging/paging-testing/build.gradle
+++ b/paging/paging-testing/build.gradle
@@ -23,13 +23,13 @@
  */
 import androidx.build.LibraryType
 import androidx.build.PlatformIdentifier
-import com.android.build.api.dsl.KotlinMultiplatformAndroidTestOnDeviceCompilation
 import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
 import androidx.build.Publish
 import org.jetbrains.kotlin.konan.target.Family
 
 plugins {
     id("AndroidXPlugin")
+    id("com.android.library")
 }
 
 androidXMultiplatform {
@@ -39,14 +39,7 @@
     mac()
     linux()
     ios()
-    androidLibrary {
-        namespace = "androidx.paging.testing"
-        withAndroidTestOnDeviceBuilder {
-            it.compilationName = "instrumentedTest"
-            it.defaultSourceSetName = "androidInstrumentedTest"
-            it.sourceSetTreeName = "test"
-        }
-    }
+    android()
 
     defaultPlatform(PlatformIdentifier.ANDROID)
 
@@ -134,3 +127,6 @@
     description = "Test artifact for Paging implementation"
 }
 
+android {
+    namespace "androidx.paging.testing"
+}
diff --git a/pdf/pdf-viewer/build.gradle b/pdf/pdf-viewer/build.gradle
index 83a9517..787fa02 100644
--- a/pdf/pdf-viewer/build.gradle
+++ b/pdf/pdf-viewer/build.gradle
@@ -40,6 +40,8 @@
     testImplementation(libs.truth)
     testImplementation(libs.guavaTestlib)
     testImplementation(libs.testExtTruth)
+    testImplementation(libs.testExtJunitKtx)
+    testImplementation("androidx.fragment:fragment-testing:1.7.1")
 
     androidTestImplementation(libs.testExtJunit)
     androidTestImplementation(libs.junit)
diff --git a/pdf/pdf-viewer/src/androidTest/java/androidx/pdf/util/GestureTrackingViewTest.java b/pdf/pdf-viewer/src/androidTest/java/androidx/pdf/util/GestureTrackingViewTest.java
index fc73215..95c724a 100644
--- a/pdf/pdf-viewer/src/androidTest/java/androidx/pdf/util/GestureTrackingViewTest.java
+++ b/pdf/pdf-viewer/src/androidTest/java/androidx/pdf/util/GestureTrackingViewTest.java
@@ -91,7 +91,7 @@
             plainView.setBackgroundColor(Color.BLUE);
             plainView.setLayoutParams(params);
 
-            GestureTracker viewTracker = new GestureTracker("View", activity);
+            GestureTracker viewTracker = new GestureTracker(activity);
             viewTracker.setDelegateHandler(mViewGestureHandler);
             plainView.setOnTouchListener(viewTracker);
 
diff --git a/pdf/pdf-viewer/src/main/java/androidx/pdf/PdfViewerFragment.kt b/pdf/pdf-viewer/src/main/java/androidx/pdf/PdfViewerFragment.kt
new file mode 100644
index 0000000..385ab21
--- /dev/null
+++ b/pdf/pdf-viewer/src/main/java/androidx/pdf/PdfViewerFragment.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.pdf
+
+import android.net.Uri
+import androidx.annotation.RestrictTo
+import androidx.fragment.app.Fragment
+
+/**
+ * A Fragment that renders a PDF document.
+ *
+ * <p>A [PdfViewerFragment] that can display paginated PDFs. The viewer includes a FAB for
+ * annotation support and a search menu. Each page is rendered in its own View. Upon creation, this
+ * fragment displays a loading spinner.
+ *
+ * <p>Rendering is done in 2 passes:
+ * <ol>
+ * <li>Layout: Request the page data, get the dimensions and set them as measure for the image view.
+ * <li>Render: Create bitmap(s) at adequate dimensions and attach them to the page view.
+ * </ol>
+ *
+ * <p>The layout pass is progressive: starts with a few first pages of the document, then reach
+ * further as the user scrolls down (and ultimately spans the whole document). The rendering pass is
+ * tightly limited to the currently visible pages. Pages that are scrolled past (become not visible)
+ * have their bitmaps released to free up memory.
+ *
+ * @see documentUri
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+open class PdfViewerFragment : Fragment() {
+
+    /**
+     * The URI of the PDF document to display defaulting to `null`.
+     *
+     * When this property is set, the fragment begins loading the PDF. A loading spinner is
+     * displayed until the document is fully loaded. If an error occurs during loading, an error
+     * message is displayed, and the detailed exception can be captured by overriding
+     * [onLoadDocumentError].
+     */
+    var documentUri: Uri? = null
+
+    /**
+     * Controls the visibility of the "find in file" menu. Defaults to `false`.
+     *
+     * Set to `true` to display the menu, or `false` to hide it.
+     */
+    var isTextSearchActive: Boolean = false
+
+    /**
+     * Callback invoked when an error occurs while loading the PDF document.
+     *
+     * Override this method to handle document loading errors. The default implementation displays a
+     * generic error message in the loading view.
+     *
+     * @param throwable [Throwable] that occurred during document loading.
+     */
+    @Suppress("UNUSED_PARAMETER") fun onLoadDocumentError(throwable: Throwable) {}
+}
diff --git a/pdf/pdf-viewer/src/main/java/androidx/pdf/models/GotoLinkDestination.java b/pdf/pdf-viewer/src/main/java/androidx/pdf/models/GotoLinkDestination.java
index 53c05ec..11c2137 100644
--- a/pdf/pdf-viewer/src/main/java/androidx/pdf/models/GotoLinkDestination.java
+++ b/pdf/pdf-viewer/src/main/java/androidx/pdf/models/GotoLinkDestination.java
@@ -21,6 +21,7 @@
 import android.os.Parcelable;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
 
 import com.google.common.base.Preconditions;
@@ -49,8 +50,8 @@
             };
 
     private final int mPageNumber;
-    private final float mXCoordinate;
-    private final float mYCoordinate;
+    private Float mXCoordinate = null;
+    private Float mYCoordinate = null;
     private final float mZoom;
 
     /**
@@ -82,12 +83,6 @@
         this.mZoom = zoom;
     }
 
-    @Override
-    public String toString() {
-        return "GotoLinkDestination{" + "mPageNumber=" + mPageNumber + ", mXCoordinate="
-                + mXCoordinate + ", mYCoordinate=" + mYCoordinate + ", mZoom=" + mZoom + '}';
-    }
-
     /**
      * Gets the page number of the destination where the {@link GotoLink} is directing.
      *
@@ -104,7 +99,8 @@
      *
      * @return x coordinate of the Destination where the goto link is directing the user.
      */
-    public float getXCoordinate() {
+    @Nullable
+    public Float getXCoordinate() {
         return mXCoordinate;
     }
 
@@ -115,7 +111,8 @@
      *
      * @return y coordinate of the Destination where the goto link is directing the user.
      */
-    public float getYCoordinate() {
+    @Nullable
+    public Float getYCoordinate() {
         return mYCoordinate;
     }
 
diff --git a/pdf/pdf-viewer/src/main/java/androidx/pdf/util/AnnotationUtils.java b/pdf/pdf-viewer/src/main/java/androidx/pdf/util/AnnotationUtils.java
new file mode 100644
index 0000000..a33af08
--- /dev/null
+++ b/pdf/pdf-viewer/src/main/java/androidx/pdf/util/AnnotationUtils.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.pdf.util;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.VisibleForTesting;
+
+import java.util.Objects;
+
+/**
+ * Utility class for enabling the functionality of Edit FAB.
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+public class AnnotationUtils {
+    @VisibleForTesting
+    public static final String ACTION_ANNOTATE_PDF = "android.intent.action.ANNOTATE";
+
+    @VisibleForTesting
+    public static final String PDF_MIME_TYPE = "application/pdf";
+
+    private AnnotationUtils() {}
+
+    /** Launches the annotation intent for a given Uri */
+    public static boolean launchAnnotationIntent(@NonNull Context context, @NonNull Uri uri) {
+        Objects.requireNonNull(context);
+        Objects.requireNonNull(uri);
+        Intent intent = getAnnotationIntent(uri);
+        return intent.resolveActivity(context.getPackageManager()) != null;
+    }
+
+    /** Returns an instance of intent from the annotation action for a given uri. */
+    @NonNull
+    public static Intent getAnnotationIntent(@NonNull Uri uri) {
+        Objects.requireNonNull(uri);
+
+        Intent intent = new Intent(ACTION_ANNOTATE_PDF);
+        intent.addCategory(Intent.CATEGORY_DEFAULT);
+        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        intent.setDataAndType(uri, PDF_MIME_TYPE);
+        return intent;
+    }
+}
diff --git a/pdf/pdf-viewer/src/main/java/androidx/pdf/util/ExternalLinks.java b/pdf/pdf-viewer/src/main/java/androidx/pdf/util/ExternalLinks.java
index e9e1274..7120c6a37 100644
--- a/pdf/pdf-viewer/src/main/java/androidx/pdf/util/ExternalLinks.java
+++ b/pdf/pdf-viewer/src/main/java/androidx/pdf/util/ExternalLinks.java
@@ -16,7 +16,6 @@
 
 package androidx.pdf.util;
 
-import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
@@ -50,20 +49,20 @@
     private static final int SHORTEN_LENGTH = 40;
 
     /** Open the given link in a browser or similar, if it is safe to do so. */
-    public static void open(@NonNull String url, @NonNull Activity activity) {
-        open(Uri.parse(url), activity);
+    public static void open(@NonNull String url, @NonNull Context context) {
+        open(Uri.parse(url), context);
     }
 
     /** Open the given URI. */
-    public static void open(@NonNull Uri uri, @NonNull Activity activity) {
+    public static void open(@NonNull Uri uri, @NonNull Context context) {
         if (TextUtils.isEmpty(uri.getScheme())) {
             uri = uri.buildUpon().scheme("http").build();
         }
         if (ALLOWED_SCHEMES.contains(uri.getScheme())) {
-            PackageManager pm = activity.getPackageManager();
+            PackageManager pm = context.getPackageManager();
             Intent intent = new Intent(Intent.ACTION_VIEW, uri);
             if (!pm.queryIntentActivities(intent, 0).isEmpty()) {
-                Intents.startActivity(activity, TAG, intent);
+                Intents.startActivity(context, TAG, intent);
             }
             // TODO: Track hyperlink click.
         }
diff --git a/pdf/pdf-viewer/src/main/java/androidx/pdf/util/GestureTracker.java b/pdf/pdf-viewer/src/main/java/androidx/pdf/util/GestureTracker.java
index fa953b2..79022f4 100644
--- a/pdf/pdf-viewer/src/main/java/androidx/pdf/util/GestureTracker.java
+++ b/pdf/pdf-viewer/src/main/java/androidx/pdf/util/GestureTracker.java
@@ -165,7 +165,7 @@
 
     private final QuickScaleBypassDecider mQuickScaleBypassDecider;
 
-    public GestureTracker(@NonNull String tag, @NonNull Context context) {
+    public GestureTracker(@NonNull Context context) {
         ViewConfiguration config = ViewConfiguration.get(context);
         mMoveSlop = config.getScaledTouchSlop();
         DetectorListener listener = new DetectorListener();
diff --git a/pdf/pdf-viewer/src/main/java/androidx/pdf/util/GestureTrackingView.java b/pdf/pdf-viewer/src/main/java/androidx/pdf/util/GestureTrackingView.java
index 1df3be7..92e2b0c 100644
--- a/pdf/pdf-viewer/src/main/java/androidx/pdf/util/GestureTrackingView.java
+++ b/pdf/pdf-viewer/src/main/java/androidx/pdf/util/GestureTrackingView.java
@@ -61,7 +61,7 @@
     }
 
     {
-        mGestureTracker = new GestureTracker(getClass().getSimpleName(), getContext());
+        mGestureTracker = new GestureTracker(getContext());
     }
 
     @Override
diff --git a/pdf/pdf-viewer/src/main/java/androidx/pdf/util/TileBoard.java b/pdf/pdf-viewer/src/main/java/androidx/pdf/util/TileBoard.java
index db90fed..b8a421d 100644
--- a/pdf/pdf-viewer/src/main/java/androidx/pdf/util/TileBoard.java
+++ b/pdf/pdf-viewer/src/main/java/androidx/pdf/util/TileBoard.java
@@ -46,7 +46,7 @@
     private static final String TAG_PREFIX = String.format("%s #", TAG);
     private final String mTag;
 
-    static final Dimensions TILE_SIZE = new Dimensions(800, 800);
+    public static final Dimensions TILE_SIZE = new Dimensions(800, 800);
 
     public static final BitmapRecycler DEFAULT_RECYCLER = new BitmapRecycler();
 
diff --git a/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/LoadingView.kt b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/LoadingView.kt
new file mode 100644
index 0000000..15cd00d
--- /dev/null
+++ b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/LoadingView.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package androidx.pdf.viewer
+
+import android.content.Context
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.widget.LinearLayout
+import android.widget.ProgressBar
+import android.widget.TextView
+import androidx.annotation.RestrictTo
+import androidx.pdf.R
+
+/**
+ * A view which displays the loading spinner when the pdf is loading and displays an error messages
+ * if there is a failure when rendering.
+ */
+// TODO(b/344386251): Update the error message and the text view once the mocks are finalised.
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+class LoadingView : LinearLayout {
+    private var progressBar: ProgressBar
+    private var errorMessage: TextView
+
+    constructor(context: Context) : this(context, null)
+
+    constructor(context: Context, attrs: AttributeSet) : this(context, attrs, 0)
+
+    constructor(
+        context: Context,
+        attrs: AttributeSet?,
+        defStyleAttr: Int = 0
+    ) : super(context, attrs, defStyleAttr) {
+
+        // Inflate the layout
+        LayoutInflater.from(context).inflate(R.layout.loading_view, this, true)
+
+        // Find views
+        progressBar = findViewById(R.id.loadingProgressBar)
+        errorMessage = findViewById(R.id.errorTextView)
+    }
+
+    fun showLoadingView() {
+        progressBar.visibility = VISIBLE
+        errorMessage.visibility = GONE
+    }
+
+    fun showErrorView(message: String) {
+        progressBar.visibility = GONE
+        errorMessage.text = message
+        errorMessage.visibility = VISIBLE
+    }
+}
diff --git a/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PageMosaicView.java b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PageMosaicView.java
index e821304..b0f95d3 100644
--- a/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PageMosaicView.java
+++ b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PageMosaicView.java
@@ -25,6 +25,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
+import androidx.annotation.VisibleForTesting;
 import androidx.pdf.models.Dimensions;
 import androidx.pdf.models.GotoLink;
 import androidx.pdf.models.GotoLinkDestination;
@@ -42,7 +43,8 @@
 @SuppressWarnings("UnusedVariable")
 public class PageMosaicView extends MosaicView implements PageViewFactory.PageView {
 
-    private static final String SEARCH_OVERLAY_KEY = "SearchOverlayKey";
+    @VisibleForTesting
+    public static final String SEARCH_OVERLAY_KEY = "SearchOverlayKey";
 
     private final int mPageNum;
     private String mPageText;
@@ -82,15 +84,23 @@
         return mPageText == null && Accessibility.get().isAccessibilityEnabled(getContext());
     }
 
+    @Nullable
+    public String getPageText() {
+        return this.mPageText;
+    }
+
     /** Set page text and content description. */
     public void setPageText(@Nullable String pageText) {
         this.mPageText = pageText;
-        String description =
-                (pageText != null)
-                        ? pageText
-                        : getContext()
-                                .getString(androidx.pdf.R.string.desc_page, (mPageNum + 1));
-        setContentDescription(description);
+        setContentDescription(buildContentDescription(pageText, mPageNum));
+    }
+
+    @NonNull
+    protected String buildContentDescription(@Nullable String pageText, int pageNum) {
+        return (pageText != null)
+                ? pageText
+                : getContext()
+                        .getString(androidx.pdf.R.string.desc_page, (mPageNum + 1));
     }
 
     /** Returns true if we have data about any links on the page. */
diff --git a/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PageTouchListener.java b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PageTouchListener.java
new file mode 100644
index 0000000..0d0730f
--- /dev/null
+++ b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PageTouchListener.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.pdf.viewer;
+
+import android.graphics.Point;
+import android.view.MotionEvent;
+
+import androidx.annotation.NonNull;
+import androidx.pdf.models.SelectionBoundary;
+import androidx.pdf.util.GestureTracker;
+import androidx.pdf.viewer.loader.PdfLoader;
+
+/** Gesture listener for PageView's handling of tap and long press. */
+class PageTouchListener extends GestureTracker.GestureHandler {
+
+    private final PageViewFactory.PageView mPageView;
+
+    private final PdfLoader mPdfLoader;
+
+    private final PdfViewer.PageTouchHandler mPageTouchHandler;
+
+    PageTouchListener(@NonNull PageViewFactory.PageView pageView,
+            @NonNull PdfLoader pdfLoader,
+            @NonNull PdfViewer.PageTouchHandler pageTouchHandler) {
+        this.mPageView = pageView;
+        this.mPdfLoader = pdfLoader;
+        this.mPageTouchHandler = pageTouchHandler;
+    }
+
+    @Override
+    public boolean onDown(@NonNull MotionEvent e) {
+        return true;
+    }
+
+    @Override
+    public boolean onSingleTapConfirmed(@NonNull MotionEvent e) {
+        return mPageTouchHandler.handleSingleTapNoFormFilling(e, mPageView.getPageView());
+    }
+
+    @Override
+    public void onLongPress(MotionEvent e) {
+        SelectionBoundary boundary =
+                SelectionBoundary.atPoint(new Point((int) e.getX(), (int) e.getY()));
+        mPdfLoader.selectPageText(mPageView.getPageNum(), boundary, boundary);
+    }
+}
diff --git a/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PageViewFactory.java b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PageViewFactory.java
index 1174732..efd550f 100644
--- a/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PageViewFactory.java
+++ b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PageViewFactory.java
@@ -17,17 +17,21 @@
 package androidx.pdf.viewer;
 
 import android.content.Context;
+import android.graphics.Color;
 import android.view.View;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
+import androidx.annotation.VisibleForTesting;
 import androidx.pdf.models.Dimensions;
 import androidx.pdf.models.GotoLink;
 import androidx.pdf.models.LinkRects;
 import androidx.pdf.util.Accessibility;
-import androidx.pdf.util.BitmapRecycler;
+import androidx.pdf.util.GestureTracker;
 import androidx.pdf.util.ObservableValue;
+import androidx.pdf.util.TileBoard;
+import androidx.pdf.viewer.loader.PdfLoader;
 import androidx.pdf.widget.MosaicView;
 import androidx.pdf.widget.ZoomView;
 
@@ -46,7 +50,19 @@
  */
 @RestrictTo(RestrictTo.Scope.LIBRARY)
 public class PageViewFactory {
-    private PageViewFactory() {
+    private final Context mContext;
+    private final PdfLoader mPdfLoader;
+    private final PaginatedView mPaginatedView;
+    private final ObservableValue<ZoomView.ZoomScroll> mZoomScroll;
+
+    public PageViewFactory(@NonNull Context context,
+            @NonNull PdfLoader pdfLoader,
+            @NonNull PaginatedView paginatedView,
+            @NonNull ZoomView zoomView) {
+        this.mContext = context;
+        this.mPdfLoader = pdfLoader;
+        this.mPaginatedView = paginatedView;
+        this.mZoomScroll = zoomView.zoomScroll();
     }
 
     /**
@@ -82,28 +98,93 @@
         void clearAll();
     }
 
+    /** Returns an instance of {@link PageView}. If the view is already created and added to the
+     *  {@link PaginatedView} then it will be returned from that list else a new instance will be
+     *  created. */
+    @NonNull
+    public PageView getOrCreatePageView(int pageNum,
+            int pageElevationInPixels,
+            @NonNull Dimensions pageDimensions,
+            @NonNull PdfViewer.PageTouchHandler handler) {
+        PageView pageView = mPaginatedView.getViewAt(pageNum);
+        if (pageView != null) {
+            return pageView;
+        }
+
+        return createAndSetupPageView(pageNum, pageElevationInPixels, pageDimensions, handler);
+    }
+
     /**
      * Returns a {@link PageMosaicView}, bundled together with a {@link PageLinksView} and
-     * optionally a {@link FormAccessibilityView} in a {@link AccessibilityPageWrapper} if TalkBack
-     * is on, otherwise returns a {@link PageMosaicView}.
+     * optionally a {@link AccessibilityPageWrapper} if TalkBack is on, otherwise returns
+     * a {@link PageMosaicView}.
      */
     @NonNull
-    public static PageView createPageView(
-            @NonNull Context context,
+    protected PageView createPageView(
             int pageNum,
-            @NonNull Dimensions pageSize,
-            @NonNull MosaicView.BitmapSource bitmapSource,
-            @Nullable BitmapRecycler bitmapRecycler,
-            @NonNull ObservableValue<ZoomView.ZoomScroll> zoomScroll) {
+            @NonNull Dimensions pageSize) {
+        final MosaicView.BitmapSource bitmapSource = createBitmapSource(pageNum);
         final PageMosaicView pageMosaicView =
-                new PageMosaicView(context, pageNum, pageSize, bitmapSource, bitmapRecycler);
-        if (Accessibility.get().isTouchExplorationEnabled(context)) {
-            final PageLinksView pageLinksView = new PageLinksView(context, zoomScroll);
+                new PageMosaicView(mContext, pageNum, pageSize, bitmapSource,
+                        TileBoard.DEFAULT_RECYCLER);
+        if (isTouchExplorationEnabled(mContext)) {
+            final PageLinksView pageLinksView = new PageLinksView(mContext, mZoomScroll);
 
             return new AccessibilityPageWrapper(
-                    context, pageNum, pageMosaicView, pageLinksView);
+                    mContext, pageNum, pageMosaicView, pageLinksView);
         } else {
             return pageMosaicView;
         }
     }
+
+    @VisibleForTesting
+    protected boolean isTouchExplorationEnabled(@NonNull Context context) {
+        return Accessibility.get().isTouchExplorationEnabled(context);
+    }
+
+    @NonNull
+    protected MosaicView.BitmapSource createBitmapSource(int pageNum) {
+        return new MosaicView.BitmapSource() {
+
+            @Override
+            public void requestPageBitmap(@NonNull Dimensions pageSize,
+                    boolean alsoRequestingTiles) {
+                mPdfLoader.loadPageBitmap(pageNum, pageSize);
+            }
+
+            @Override
+            public void requestNewTiles(@NonNull Dimensions pageSize,
+                    @NonNull Iterable<TileBoard.TileInfo> tiles) {
+                mPdfLoader.loadTileBitmaps(pageNum, pageSize, tiles);
+            }
+
+            @Override
+            public void cancelTiles(@NonNull Iterable<Integer> tileIds) {
+                mPdfLoader.cancelTileBitmaps(pageNum, tileIds);
+            }
+        };
+    }
+
+    @NonNull
+    protected PageView createAndSetupPageView(int pageNum,
+            int pageElevationInPixels,
+            @NonNull Dimensions pageDimensions,
+            @NonNull PdfViewer.PageTouchHandler handler) {
+        PageView pageView =
+                createPageView(
+                        pageNum,
+                        pageDimensions
+                );
+        mPaginatedView.addView(pageView);
+
+        GestureTracker gestureTracker = new GestureTracker(mContext);
+        pageView.asView().setOnTouchListener(gestureTracker);
+        gestureTracker.setDelegateHandler(new PageTouchListener(pageView, mPdfLoader, handler));
+
+        PageMosaicView pageMosaicView = pageView.getPageView();
+        // Setting Elevation only works if there is a background color.
+        pageMosaicView.setBackgroundColor(Color.WHITE);
+        pageMosaicView.setElevation(pageElevationInPixels);
+        return pageView;
+    }
 }
diff --git a/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PdfViewer.java b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PdfViewer.java
index 83e38a3..7d8e888 100644
--- a/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PdfViewer.java
+++ b/pdf/pdf-viewer/src/main/java/androidx/pdf/viewer/PdfViewer.java
@@ -26,7 +26,6 @@
 import android.content.Intent;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
-import android.graphics.Color;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.net.Uri;
@@ -67,11 +66,9 @@
 import androidx.pdf.models.LinkRects;
 import androidx.pdf.models.MatchRects;
 import androidx.pdf.models.PageSelection;
-import androidx.pdf.models.SelectionBoundary;
+import androidx.pdf.util.AnnotationUtils;
 import androidx.pdf.util.CycleRange;
 import androidx.pdf.util.ExternalLinks;
-import androidx.pdf.util.GestureTracker;
-import androidx.pdf.util.GestureTracker.GestureHandler;
 import androidx.pdf.util.ObservableValue;
 import androidx.pdf.util.ObservableValue.ValueObserver;
 import androidx.pdf.util.Preconditions;
@@ -88,7 +85,6 @@
 import androidx.pdf.viewer.loader.PdfLoaderCallbacks;
 import androidx.pdf.widget.FastScrollContentModel;
 import androidx.pdf.widget.FastScrollView;
-import androidx.pdf.widget.MosaicView.BitmapSource;
 import androidx.pdf.widget.ZoomView;
 import androidx.pdf.widget.ZoomView.ContentResizedMode;
 import androidx.pdf.widget.ZoomView.FitMode;
@@ -153,8 +149,6 @@
     private static final String KEY_SPACE_RIGHT = "rightSpace";
     private static final String KEY_QUIT_ON_ERROR = "quitOnError";
     private static final String KEY_EXIT_ON_CANCEL = "exitOnCancel";
-    private static final String ACTION_ANNOTATE_PDF = "android.intent.action.ANNOTATE";
-    private static final String PDF_MIME_TYPE = "application/pdf";
 
     /** Key to save/retrieve {@link #mEditingAuthorized} from Bundle. */
     private static final String KEY_EDITING_AUTHORIZED = "editingAuthorized";
@@ -246,6 +240,8 @@
 
     private FloatingActionButton mAnnotationButton;
 
+    private PageViewFactory mPageViewFactory;
+
     /** Callback is called everytime dimensions for a page have loaded. */
     private interface OnDimensCallback {
         /** Return true to continue receiving callbacks, else false. */
@@ -284,7 +280,7 @@
     }
 
     @Override
-    public void onCreate(@NonNull Bundle savedInstanceState) {
+    public void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         mFetcher = Fetcher.build(getContext(), 1);
         sScreen = new Screen(this.requireActivity().getApplicationContext());
@@ -428,7 +424,7 @@
     }
 
     @Override
-    public void onActivityCreated(@NonNull Bundle savedInstanceState) {
+    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
         mZoomView.zoomScroll().addObserver(mZoomScrollObserver);
         if (mPendingScrollPositionObserver != null) {
@@ -469,6 +465,9 @@
             mPdfLoader.reconnect();
         }
 
+        mPageViewFactory = new PageViewFactory(requireContext(), mPdfLoader,
+                mPaginatedView, mZoomView);
+
         if (mPaginatedView != null && mPaginatedView.getChildCount() > 0) {
             loadPageAssets(mZoomView.zoomScroll().get());
         }
@@ -740,71 +739,14 @@
         if (mPdfLoader == null) {
             return;
         }
-        boolean pushed = false;
         int lastPage = Math.min(untilPage, getPageCount());
         int requestLayoutPage = mPageLayoutReach;
         while (requestLayoutPage < lastPage) {
             mPdfLoader.loadPageDimensions(requestLayoutPage);
             requestLayoutPage++;
-            pushed = true;
         }
     }
 
-    private PageView createPage(final int pageNum) {
-        BitmapSource bitmapSource =
-                new BitmapSource() {
-
-                    @Override
-                    public void requestPageBitmap(@NonNull Dimensions pageSize,
-                            boolean alsoRequestingTiles) {
-                        mPdfLoader.loadPageBitmap(pageNum, pageSize);
-                    }
-
-                    @Override
-                    public void requestNewTiles(@NonNull Dimensions pageSize,
-                            @NonNull Iterable<TileInfo> tiles) {
-                        mPdfLoader.loadTileBitmaps(pageNum, pageSize, tiles);
-                    }
-
-                    @Override
-                    public void cancelTiles(@NonNull Iterable<Integer> tileIds) {
-                        mPdfLoader.cancelTileBitmaps(pageNum, tileIds);
-                    }
-                };
-        Dimensions dimensions = mPaginationModel.getPageSize(pageNum);
-        PageView pageView =
-                PageViewFactory.createPageView(
-                        requireActivity(),
-                        pageNum,
-                        dimensions,
-                        bitmapSource,
-                        TileBoard.DEFAULT_RECYCLER,
-                        mZoomView.zoomScroll());
-        mPaginatedView.addView(pageView);
-
-        GestureTracker gestureTracker = new GestureTracker("PageView", getActivity());
-        pageView.asView().setOnTouchListener(gestureTracker);
-        gestureTracker.setDelegateHandler(new PageTouchListener(pageView));
-
-        PageMosaicView pageMosaicView = pageView.getPageView();
-        // Setting Elevation only works if there is a background color.
-        pageMosaicView.setBackgroundColor(Color.WHITE);
-        pageMosaicView.setElevation(sScreen.pxFromDp(PAGE_ELEVATION_DP));
-        return pageView;
-    }
-
-    /**
-     * Convenience method that always returns a child view. However in the case it's just been
-     * created, that View is not laid out.
-     */
-    private PageView getOrCreatePage(int pageNum) {
-        PageView pageView = mPaginatedView.getViewAt(pageNum);
-        if (pageView != null) {
-            return pageView;
-        }
-        return createPage(pageNum);
-    }
-
     private boolean isPageCreated(int pageNum) {
         return pageNum < mPaginationModel.getSize() && mPaginatedView.getViewAt(pageNum) != null;
     }
@@ -830,7 +772,11 @@
         int y = mPaginationModel.getLookAtY(selection.getPage(), rect.centerY());
         mZoomView.centerAt(x, y);
 
-        PageMosaicView pageView = getOrCreatePage(selection.getPage()).getPageView();
+        PageMosaicView pageView = (PageMosaicView) mPageViewFactory.getOrCreatePageView(
+                selection.getPage(),
+                sScreen.pxFromDp(PAGE_ELEVATION_DP),
+                mPaginationModel.getPageSize(selection.getPage()),
+                new PageTouchHandler());
         pageView.setOverlay(selection.getOverlay());
     }
 
@@ -873,7 +819,10 @@
         boolean requiresLayoutPass = false;
         for (int pageNum : mVisiblePages) {
             if (mPaginatedView.getViewAt(pageNum) == null) {
-                createPage(pageNum);
+                mPageViewFactory.getOrCreatePageView(pageNum,
+                        sScreen.pxFromDp(PAGE_ELEVATION_DP),
+                        mPaginationModel.getPageSize(pageNum),
+                        new PageTouchHandler());
                 requiresLayoutPass = true;
             }
         }
@@ -903,7 +852,11 @@
 
     private void refreshTiles(Range pages) {
         for (int page : pages) {
-            PageMosaicView pageView = getOrCreatePage(page).getPageView();
+            PageMosaicView pageView = (PageMosaicView) mPageViewFactory.getOrCreatePageView(
+                    page,
+                    sScreen.pxFromDp(PAGE_ELEVATION_DP),
+                    mPaginationModel.getPageSize(page),
+                    new PageTouchHandler());
             pageView.requestTiles();
         }
     }
@@ -920,7 +873,11 @@
     private void loadPageOnly(Range pages) {
         for (int page : pages) {
             mPdfLoader.cancelAllTileBitmaps(page);
-            PageMosaicView pageView = getOrCreatePage(page).getPageView();
+            PageMosaicView pageView = (PageMosaicView) mPageViewFactory.getOrCreatePageView(
+                    page,
+                    sScreen.pxFromDp(PAGE_ELEVATION_DP),
+                    mPaginationModel.getPageSize(page),
+                    new PageTouchHandler());
             pageView.clearTiles();
             pageView.requestFastDrawAtZoom(mStableZoom);
             loadVisiblePageText(page);
@@ -930,7 +887,11 @@
 
     private void refreshPages(Range pages) {
         for (int page : pages) {
-            PageMosaicView pageView = getOrCreatePage(page).getPageView();
+            PageMosaicView pageView = (PageMosaicView) mPageViewFactory.getOrCreatePageView(
+                    page,
+                    sScreen.pxFromDp(PAGE_ELEVATION_DP),
+                    mPaginationModel.getPageSize(page),
+                    new PageTouchHandler());
             pageView.requestDrawAtZoom(mStableZoom);
             loadVisiblePageText(page);
             maybeLoadFormAccessibilityInfo(page);
@@ -975,7 +936,11 @@
     }
 
     private void loadVisiblePageText(int page) {
-        PageView pageView = getOrCreatePage(page);
+        PageView pageView = mPageViewFactory.getOrCreatePageView(
+                page,
+                sScreen.pxFromDp(PAGE_ELEVATION_DP),
+                mPaginationModel.getPageSize(page),
+                new PageTouchHandler());
         PageMosaicView pageMosaicView = pageView.getPageView();
         if (pageMosaicView.needsPageText()) {
             mPdfLoader.loadPageText(page);
@@ -1002,7 +967,11 @@
      * required.
      */
     private void maybeLoadFormAccessibilityInfo(int pageNum) {
-        getOrCreatePage(pageNum);
+        mPageViewFactory.getOrCreatePageView(
+                pageNum,
+                sScreen.pxFromDp(PAGE_ELEVATION_DP),
+                mPaginationModel.getPageSize(pageNum),
+                new PageTouchHandler());
     }
 
     /** Computes the range of visible pages in the given position. */
@@ -1040,7 +1009,7 @@
                             showFastScrollView();
                         }
 
-                        if (showEditFab()) {
+                        if (AnnotationUtils.launchAnnotationIntent(requireContext(), mLocalUri)) {
                             if (position.scrollY > 0) {
                                 mAnnotationButton.setVisibility(View.GONE);
                             } else if (position.scrollY == 0
@@ -1113,8 +1082,11 @@
                         }
                         if (newSelection != null && mVisiblePages.contains(
                                 newSelection.getPage())) {
-                            getOrCreatePage(newSelection.getPage())
-                                    .getPageView()
+                            ((PageMosaicView) mPageViewFactory.getOrCreatePageView(
+                                    newSelection.getPage(),
+                                    sScreen.pxFromDp(PAGE_ELEVATION_DP),
+                                    mPaginationModel.getPageSize(newSelection.getPage()),
+                                    new PageTouchHandler()))
                                     .setOverlay(new PdfHighlightOverlay(newSelection));
                         }
                     }
@@ -1184,34 +1156,7 @@
         };
     }
 
-    /** Gesture listener for PageView's handling of tap and long press. */
-    private class PageTouchListener extends GestureHandler {
-
-        private final PageView mPageView;
-
-        PageTouchListener(PageView pageView) {
-            this.mPageView = pageView;
-        }
-
-        @Override
-        public boolean onDown(@NonNull MotionEvent e) {
-            return true;
-        }
-
-        @Override
-        public boolean onSingleTapConfirmed(@NonNull MotionEvent e) {
-            return handleSingleTapNoFormFilling(e);
-        }
-
-        @Override
-        public void onLongPress(MotionEvent e) {
-            SelectionBoundary boundary =
-                    SelectionBoundary.atPoint(new Point((int) e.getX(), (int) e.getY()));
-            mPdfLoader.selectPageText(mPageView.getPageNum(), boundary, boundary);
-        }
-
-        // TODO: Add method to track enter form-filling via widget.
-
+    public class PageTouchHandler {
         /**
          * Handles a tap event for non-formfilling actions.
          *
@@ -1220,8 +1165,9 @@
          * branch
          * statements.
          */
-        private boolean handleSingleTapNoFormFilling(MotionEvent e) {
-            if (showEditFab()) {
+        public boolean handleSingleTapNoFormFilling(@NonNull MotionEvent event,
+                @NonNull PageMosaicView pageMosaicView) {
+            if (AnnotationUtils.launchAnnotationIntent(requireContext(), mLocalUri)) {
                 if (mAnnotationButton.getVisibility() == View.GONE
                         && mFindInFileView.getVisibility() == GONE) {
                     mAnnotationButton.setVisibility(View.VISIBLE);
@@ -1235,13 +1181,13 @@
                 mSelectionModel.setSelection(null);
             }
 
-            Point point = new Point((int) e.getX(), (int) e.getY());
-            String linkUrl = mPageView.getPageView().getLinkUrl(point);
+            Point point = new Point((int) event.getX(), (int) event.getY());
+            String linkUrl = pageMosaicView.getLinkUrl(point);
             if (linkUrl != null) {
-                ExternalLinks.open(linkUrl, getActivity());
+                ExternalLinks.open(linkUrl, requireActivity());
             }
 
-            GotoLinkDestination gotoDest = mPageView.getPageView().getGotoDestination(point);
+            GotoLinkDestination gotoDest = pageMosaicView.getGotoDestination(point);
             if (gotoDest != null) {
                 gotoPageDest(gotoDest);
             }
@@ -1249,7 +1195,8 @@
             return true;
         }
 
-        private void gotoPageDest(GotoLinkDestination destination) {
+        /** */
+        public void gotoPageDest(@NonNull GotoLinkDestination destination) {
 
             if (destination.getPageNumber() >= mPaginationModel.getSize()) {
                 // We have not yet loaded our destination.
@@ -1265,16 +1212,51 @@
                 return;
             }
 
-            int pageY = (int) destination.getYCoordinate();
+            if (destination.getYCoordinate() != null) {
+                int pageY = (int) destination.getYCoordinate().floatValue();
 
-            Rect pageRect = mPaginationModel.getPageLocation(destination.getPageNumber());
+                Rect pageRect = mPaginationModel.getPageLocation(destination.getPageNumber());
+                int x = pageRect.left + (pageRect.width() / 2);
+                int y = mPaginationModel.getLookAtY(destination.getPageNumber(), pageY);
+                // Zoom should match the width of the page.
+                float zoom =
+                        ZoomUtils.calculateZoomToFit(
+                                mZoomView.getViewportWidth(), mZoomView.getViewportHeight(),
+                                pageRect.width(), 1);
+
+                mZoomView.setZoom(zoom);
+                mZoomView.centerAt(x, y);
+            } else {
+                gotoPage(destination.getPageNumber());
+            }
+        }
+
+        /** Goes to the {@code pageNum} and fits the page to the current viewport. */
+        private void gotoPage(int pageNum) {
+            if (pageNum >= mPaginationModel.getSize()) {
+                // We have not yet loaded our destination.
+                layoutPages(pageNum + 1);
+                mDimensCallbackQueue.add(
+                        loadedPageNum -> {
+                            if (pageNum == loadedPageNum) {
+                                gotoPage(pageNum);
+                                return false;
+                            }
+                            return true;
+                        });
+                return;
+            }
+
+            Rect pageRect = mPaginationModel.getPageLocation(pageNum);
+
             int x = pageRect.left + (pageRect.width() / 2);
-            int y = mPaginationModel.getLookAtY(destination.getPageNumber(), pageY);
-            // Zoom should match the width of the page.
+            int y = pageRect.top + (pageRect.height() / 2);
             float zoom =
                     ZoomUtils.calculateZoomToFit(
-                            mZoomView.getViewportWidth(), mZoomView.getViewportHeight(),
-                            pageRect.width(), 1);
+                            mZoomView.getViewportWidth(),
+                            mZoomView.getViewportHeight(),
+                            pageRect.width(),
+                            pageRect.height());
 
             mZoomView.setZoom(zoom);
             mZoomView.centerAt(x, y);
@@ -1283,37 +1265,6 @@
 
     // TODO: Revisit this method for its usage. Currently redundant
 
-    /** Goes to the {@code pageNum} and fits the page to the current viewport. */
-    private void gotoPage(int pageNum) {
-        if (pageNum >= mPaginationModel.getSize()) {
-            // We have not yet loaded our destination.
-            layoutPages(pageNum + 1);
-            mDimensCallbackQueue.add(
-                    loadedPageNum -> {
-                        if (pageNum == loadedPageNum) {
-                            gotoPage(pageNum);
-                            return false;
-                        }
-                        return true;
-                    });
-            return;
-        }
-
-        Rect pageRect = mPaginationModel.getPageLocation(pageNum);
-
-        int x = pageRect.left + (pageRect.width() / 2);
-        int y = pageRect.top + (pageRect.height() / 2);
-        float zoom =
-                ZoomUtils.calculateZoomToFit(
-                        mZoomView.getViewportWidth(),
-                        mZoomView.getViewportHeight(),
-                        pageRect.width(),
-                        pageRect.height());
-
-        mZoomView.setZoom(zoom);
-        mZoomView.centerAt(x, y);
-    }
-
     { // Init pdfLoaderCallbacks
         mPdfLoaderCallbacks =
                 new PdfLoaderCallbacks() {
@@ -1399,7 +1350,7 @@
                             mShouldRedrawOnDocumentLoaded = false;
                         }
 
-                        if (showEditFab()) {
+                        if (AnnotationUtils.launchAnnotationIntent(requireContext(), mLocalUri)) {
                             mAnnotationButton.setVisibility(VISIBLE);
                         }
                     }
@@ -1438,8 +1389,11 @@
                     @Override
                     public void pageBroken(int page) {
                         if (viewState().get() != ViewState.NO_VIEW) {
-                            getOrCreatePage(page)
-                                    .getPageView()
+                            ((PageMosaicView) mPageViewFactory.getOrCreatePageView(
+                                    page,
+                                    sScreen.pxFromDp(PAGE_ELEVATION_DP),
+                                    mPaginationModel.getPageSize(page),
+                                    new PageTouchHandler()))
                                     .setFailure(getString(R.string.error_on_page, page + 1));
                             Toaster.LONG.popToast(getActivity(), R.string.error_on_page, page + 1);
                             // TODO: Track render error.
@@ -1711,7 +1665,7 @@
             queryBox.clearFocus();
             queryBox.setText("");
             parentLayout.setVisibility(GONE);
-            if (showEditFab()) {
+            if (AnnotationUtils.launchAnnotationIntent(requireContext(), mLocalUri)) {
                 mAnnotationButton.setVisibility(VISIBLE);
             }
         });
@@ -1729,21 +1683,8 @@
     }
 
     private void performEdit() {
-        Intent intent = getAnnotationIntent();
+        Intent intent = AnnotationUtils.getAnnotationIntent(mLocalUri);
         intent.setData(mLocalUri);
         startActivity(intent);
     }
-
-    private boolean showEditFab() {
-        Intent intent = getAnnotationIntent();
-        return intent.resolveActivity(getContext().getPackageManager()) != null;
-    }
-
-    private Intent getAnnotationIntent() {
-        Intent intent = new Intent(ACTION_ANNOTATE_PDF);
-        intent.addCategory(Intent.CATEGORY_DEFAULT);
-        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-        intent.setDataAndType(mLocalUri, PDF_MIME_TYPE);
-        return intent;
-    }
 }
diff --git a/pdf/pdf-viewer/src/main/java/androidx/pdf/widget/MosaicView.java b/pdf/pdf-viewer/src/main/java/androidx/pdf/widget/MosaicView.java
index 07f2d10..7696a56 100644
--- a/pdf/pdf-viewer/src/main/java/androidx/pdf/widget/MosaicView.java
+++ b/pdf/pdf-viewer/src/main/java/androidx/pdf/widget/MosaicView.java
@@ -220,6 +220,11 @@
         void cancelTiles(@NonNull Iterable<Integer> tileIds);
     }
 
+    @NonNull
+    public Rect getBounds() {
+        return mBounds;
+    }
+
     @Override
     public boolean onTouchEvent(MotionEvent event) {
         return super.onTouchEvent(event);
@@ -289,11 +294,6 @@
         }
     }
 
-    /** Set value of alwaysRequestPageBitmap to false. */
-    public void setDoNotRequestPageBitmap() {
-        mAlwaysRequestPageBitmap = false;
-    }
-
     /** Creates a new tiling for this view. */
     private void prepareTiles(Dimensions viewSize, float zoom) {
         TileBoard newBoard = createTileBoard(viewSize);
diff --git a/pdf/pdf-viewer/src/main/res/layout/loading_view.xml b/pdf/pdf-viewer/src/main/res/layout/loading_view.xml
new file mode 100644
index 0000000..35c28a2
--- /dev/null
+++ b/pdf/pdf-viewer/src/main/res/layout/loading_view.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  Copyright 2024 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:gravity="center"
+    android:orientation="vertical"
+    android:padding="16dp">
+
+    <ProgressBar
+        android:id="@+id/loadingProgressBar"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:indeterminate="true"/>
+
+    <TextView
+        android:id="@+id/errorTextView"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="16dp"
+        android:textColor="@android:color/holo_red_dark"
+        android:visibility="gone"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/pdf/pdf-viewer/src/main/res/values-fa/strings.xml b/pdf/pdf-viewer/src/main/res/values-fa/strings.xml
index 6481bcf..3541a25 100644
--- a/pdf/pdf-viewer/src/main/res/values-fa/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-fa/strings.xml
@@ -32,7 +32,7 @@
     <string name="desc_goto_link" msgid="2461368384824849714">"رفتن به صفحه <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
     <string name="desc_page" msgid="5684226167093594168">"صفحه <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="message_select_text_to_comment" msgid="5725327644007067522">"نوشتار را برای نظر گذاشتن انتخاب کنید"</string>
-    <string name="message_tap_to_comment" msgid="7820801719181709999">"روی قسمتی که می‌خواهید نظر بگذارید ضربه بزنید"</string>
+    <string name="message_tap_to_comment" msgid="7820801719181709999">"روی قسمتی که می‌خواهید نظر بگذارید تک‌ضرب بزنید"</string>
     <string name="action_cancel" msgid="5494417739210197522">"لغو کردن"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"‏‫PDF نمایش داده نمی‌شود (قالب <xliff:g id="TITLE">%1$s</xliff:g> نامعتبر است)"</string>
     <string name="error_on_page" msgid="1592475819957182385">"صفحه <xliff:g id="PAGE">%1$d</xliff:g> نمایش داده نمی‌شود (خطای فایل)"</string>
diff --git a/pdf/pdf-viewer/src/test/java/androidx/pdf/PdfViewerFragmentTest.kt b/pdf/pdf-viewer/src/test/java/androidx/pdf/PdfViewerFragmentTest.kt
new file mode 100644
index 0000000..eedcc0a
--- /dev/null
+++ b/pdf/pdf-viewer/src/test/java/androidx/pdf/PdfViewerFragmentTest.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.pdf
+
+import androidx.fragment.app.testing.FragmentScenario
+import androidx.fragment.app.testing.launchFragment
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class PdfViewerFragmentTest {
+    private lateinit var scenario: FragmentScenario<PdfViewerFragment>
+    private lateinit var fragment: PdfViewerFragment
+
+    @Before
+    fun setup() {
+        scenario = launchFragment()
+        scenario.onFragment { fragment = it }
+    }
+
+    @Test
+    fun testInitialDocumentUriValue_returnsNull() {
+        assertThat(fragment.documentUri).isEqualTo(null)
+    }
+
+    @Test
+    fun testInitialIsTextSearchActiveValue_isFalse() {
+        assertThat(fragment.isTextSearchActive).isEqualTo(false)
+    }
+}
diff --git a/pdf/pdf-viewer/src/test/java/androidx/pdf/util/AnnotationUtilsTest.java b/pdf/pdf-viewer/src/test/java/androidx/pdf/util/AnnotationUtilsTest.java
new file mode 100644
index 0000000..4b29401
--- /dev/null
+++ b/pdf/pdf-viewer/src/test/java/androidx/pdf/util/AnnotationUtilsTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.pdf.util;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.robolectric.RobolectricTestRunner;
+
+import java.io.File;
+
+@SmallTest
+@RunWith(RobolectricTestRunner.class)
+public class AnnotationUtilsTest {
+    @Test
+    public void getAnnotationIntent_nonNullUri_returnsAnnotateActionIntent() {
+        String fileName = "file:://dummyfile.pdf";
+        Uri uri = Uri.fromFile(new File(fileName));
+        Intent annotateIntent = AnnotationUtils.getAnnotationIntent(uri);
+
+        assertThat(annotateIntent.getAction()).isEqualTo(AnnotationUtils.ACTION_ANNOTATE_PDF);
+        assertThat(annotateIntent.getCategories()).hasSize(1);
+        assertThat(annotateIntent.getCategories()).contains(Intent.CATEGORY_DEFAULT);
+        assertThat(annotateIntent.getFlags()).isEqualTo(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        assertThat(annotateIntent.getData()).isEqualTo(uri);
+        assertThat(annotateIntent.getType()).isEqualTo(AnnotationUtils.PDF_MIME_TYPE);
+    }
+
+    @Test
+    public void getAnnotationIntent_nullUri_throwsNullPointerException() {
+        assertThrows(NullPointerException.class,
+                () -> AnnotationUtils.getAnnotationIntent(null));
+    }
+
+    @Test
+    public void launchAnnotationIntent_nonNullUri_returnsTrue() {
+        String fileName = "file:://dummyfile.pdf";
+        Uri uri = Uri.fromFile(new File(fileName));
+
+        Context mockContext = Mockito.mock(Context.class);
+        PackageManager mockPackageManager = Mockito.mock(PackageManager.class);
+        ResolveInfo mockResolveInfo = Mockito.mock(ResolveInfo.class);
+        ActivityInfo mockActivityInfo = new ActivityInfo();
+        ApplicationInfo mockApplicationInfo = new ApplicationInfo();
+        mockApplicationInfo.packageName = "dummyPackage";
+        mockActivityInfo.applicationInfo = mockApplicationInfo;
+        mockActivityInfo.name = "dummyName";
+        mockResolveInfo.activityInfo = mockActivityInfo;
+
+        when(mockPackageManager.resolveActivity(any(Intent.class),
+                eq(PackageManager.MATCH_DEFAULT_ONLY))).thenReturn(
+                mockResolveInfo);
+        when(mockContext.getPackageManager()).thenReturn(mockPackageManager);
+
+        boolean result = AnnotationUtils.launchAnnotationIntent(mockContext, uri);
+        assertTrue(result);
+    }
+
+    @Test
+    public void launchAnnotationIntent_nullContext_returnsNullPointerException() {
+        assertThrows(NullPointerException.class,
+                () -> AnnotationUtils.launchAnnotationIntent(
+                        ApplicationProvider.getApplicationContext(), null));
+    }
+
+    @Test
+    public void launchAnnotationIntent_nullUri_returnsNullPointerException() {
+        String fileName = "file:://dummyfile.pdf";
+        Uri uri = Uri.fromFile(new File(fileName));
+        assertThrows(NullPointerException.class,
+                () -> AnnotationUtils.launchAnnotationIntent(
+                        null, uri));
+    }
+}
diff --git a/pdf/pdf-viewer/src/test/java/androidx/pdf/util/GestureTrackerTest.java b/pdf/pdf-viewer/src/test/java/androidx/pdf/util/GestureTrackerTest.java
index bf3bfe3..e0a2ce1 100644
--- a/pdf/pdf-viewer/src/test/java/androidx/pdf/util/GestureTrackerTest.java
+++ b/pdf/pdf-viewer/src/test/java/androidx/pdf/util/GestureTrackerTest.java
@@ -48,7 +48,6 @@
 @RunWith(RobolectricTestRunner.class)
 public class GestureTrackerTest {
 
-    private static final String TAG = "GestureTrackerTest";
     private static final int TAP_TIMEOUT = 200;
 
     private GestureTracker mGestureTracker;
@@ -61,7 +60,7 @@
     public void setUp() {
         mOpenMocks = MockitoAnnotations.openMocks(this);
         mGestureTracker =
-                new GestureTracker("GesturesTest", ApplicationProvider.getApplicationContext());
+                new GestureTracker(ApplicationProvider.getApplicationContext());
         mGestureTracker.setDelegateHandler(mGestureHandler);
     }
 
diff --git a/pdf/pdf-viewer/src/test/java/androidx/pdf/util/MockDrawable.java b/pdf/pdf-viewer/src/test/java/androidx/pdf/util/MockDrawable.java
new file mode 100644
index 0000000..76ea416
--- /dev/null
+++ b/pdf/pdf-viewer/src/test/java/androidx/pdf/util/MockDrawable.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.pdf.util;
+
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.Drawable;
+
+@SuppressWarnings("deprecation")
+public class MockDrawable extends Drawable {
+    private final Paint mRedPaint;
+
+    public MockDrawable() {
+        // Set up color and text size
+        mRedPaint = new Paint();
+        mRedPaint.setARGB(255, 255, 0, 0);
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        // Get the drawable's bounds
+        int width = getBounds().width();
+        int height = getBounds().height();
+        float radius = (float) Math.min(width, height) / 2;
+
+        // Draw a red circle in the center
+        canvas.drawCircle((float) width / 2, (float) height / 2, radius, mRedPaint);
+    }
+
+    @Override
+    public void setAlpha(int alpha) {
+        // This method is required
+    }
+
+    @Override
+    public void setColorFilter(ColorFilter colorFilter) {
+        // This method is required
+    }
+
+    @Override
+    public int getOpacity() {
+        // Must be PixelFormat.UNKNOWN, TRANSLUCENT, TRANSPARENT, or OPAQUE
+        return PixelFormat.OPAQUE;
+    }
+}
diff --git a/pdf/pdf-viewer/src/test/java/androidx/pdf/viewer/LoadingViewTest.kt b/pdf/pdf-viewer/src/test/java/androidx/pdf/viewer/LoadingViewTest.kt
new file mode 100644
index 0000000..8a3fc66
--- /dev/null
+++ b/pdf/pdf-viewer/src/test/java/androidx/pdf/viewer/LoadingViewTest.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package androidx.pdf.viewer
+
+import android.content.Context
+import android.view.View
+import android.widget.ProgressBar
+import android.widget.TextView
+import androidx.pdf.R
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth
+import org.junit.Assert
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+
+/** Tests for [LoadingView]. */
+@SmallTest
+@RunWith(RobolectricTestRunner::class)
+class LoadingViewTest {
+    private lateinit var loadingView: LoadingView
+
+    @Before
+    fun setUp() {
+        val context = ApplicationProvider.getApplicationContext<Context>()
+        loadingView = LoadingView(context)
+    }
+
+    @Test
+    fun testLoadingView_isNotNull() {
+        Assert.assertNotNull(loadingView)
+    }
+
+    @Test
+    fun showLoadingView_showsLoadingSpinner() {
+        val progressBar = loadingView.findViewById<ProgressBar>(R.id.loadingProgressBar)
+        val errorMessage = loadingView.findViewById<TextView>(R.id.errorTextView)
+
+        loadingView.showLoadingView()
+
+        Assert.assertEquals(View.VISIBLE.toLong(), progressBar.visibility.toLong())
+        Assert.assertEquals(View.GONE.toLong(), errorMessage.visibility.toLong())
+    }
+
+    @Test
+    fun showErrorView_showsErrorMessage() {
+        val dummyErrorMessage = "testing error"
+        val progressBar = loadingView.findViewById<ProgressBar>(R.id.loadingProgressBar)
+        val errorMessage = loadingView.findViewById<TextView>(R.id.errorTextView)
+
+        loadingView.showErrorView(dummyErrorMessage)
+
+        Assert.assertEquals(View.GONE.toLong(), progressBar.visibility.toLong())
+        Assert.assertEquals(View.VISIBLE.toLong(), errorMessage.visibility.toLong())
+        Truth.assertThat(errorMessage.text).isEqualTo(dummyErrorMessage)
+    }
+}
diff --git a/pdf/pdf-viewer/src/test/java/androidx/pdf/viewer/MockPageViewAccessbilityDisabledFactory.java b/pdf/pdf-viewer/src/test/java/androidx/pdf/viewer/MockPageViewAccessbilityDisabledFactory.java
new file mode 100644
index 0000000..0a45c71
--- /dev/null
+++ b/pdf/pdf-viewer/src/test/java/androidx/pdf/viewer/MockPageViewAccessbilityDisabledFactory.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.pdf.viewer;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+import androidx.pdf.models.Dimensions;
+import androidx.pdf.util.TileBoard;
+import androidx.pdf.viewer.loader.PdfLoader;
+import androidx.pdf.widget.MosaicView;
+import androidx.pdf.widget.ZoomView;
+
+public class MockPageViewAccessbilityDisabledFactory extends PageViewFactory {
+    public MockPageViewAccessbilityDisabledFactory(@NonNull Context context,
+            @NonNull PdfLoader pdfLoader,
+            @NonNull PaginatedView paginatedView,
+            @NonNull ZoomView zoomView) {
+        super(context, pdfLoader, paginatedView, zoomView);
+    }
+
+    @NonNull
+    @Override
+    protected MosaicView.BitmapSource createBitmapSource(int pageNum) {
+        return new MosaicView.BitmapSource() {
+            @Override
+            public void requestPageBitmap(@NonNull Dimensions pageSize,
+                    boolean alsoRequestingTiles) {
+
+            }
+
+            @Override
+            public void requestNewTiles(@NonNull Dimensions pageSize,
+                    @NonNull Iterable<TileBoard.TileInfo> newTiles) {
+
+            }
+
+            @Override
+            public void cancelTiles(@NonNull Iterable<Integer> tileIds) {
+
+            }
+        };
+    }
+
+    @Override
+    protected boolean isTouchExplorationEnabled(@NonNull Context context) {
+        return false;
+    }
+}
diff --git a/pdf/pdf-viewer/src/test/java/androidx/pdf/viewer/MockPageViewAccessbilityEnabledFactory.java b/pdf/pdf-viewer/src/test/java/androidx/pdf/viewer/MockPageViewAccessbilityEnabledFactory.java
new file mode 100644
index 0000000..1dd7e58
--- /dev/null
+++ b/pdf/pdf-viewer/src/test/java/androidx/pdf/viewer/MockPageViewAccessbilityEnabledFactory.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.pdf.viewer;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+import androidx.pdf.models.Dimensions;
+import androidx.pdf.util.TileBoard;
+import androidx.pdf.viewer.loader.PdfLoader;
+import androidx.pdf.widget.MosaicView;
+import androidx.pdf.widget.ZoomView;
+
+public class MockPageViewAccessbilityEnabledFactory extends PageViewFactory {
+
+    public MockPageViewAccessbilityEnabledFactory(
+            @NonNull Context context,
+            @NonNull PdfLoader pdfLoader,
+            @NonNull PaginatedView paginatedView,
+            @NonNull ZoomView zoomView) {
+        super(context, pdfLoader, paginatedView, zoomView);
+    }
+
+    @NonNull
+    @Override
+    protected MosaicView.BitmapSource createBitmapSource(int pageNum) {
+        return new MosaicView.BitmapSource() {
+            @Override
+            public void requestPageBitmap(@NonNull Dimensions pageSize,
+                    boolean alsoRequestingTiles) {
+
+            }
+
+            @Override
+            public void requestNewTiles(@NonNull Dimensions pageSize,
+                    @NonNull Iterable<TileBoard.TileInfo> newTiles) {
+
+            }
+
+            @Override
+            public void cancelTiles(@NonNull Iterable<Integer> tileIds) {
+
+            }
+        };
+    }
+
+    @Override
+    protected boolean isTouchExplorationEnabled(@NonNull Context context) {
+        return true;
+    }
+}
diff --git a/pdf/pdf-viewer/src/test/java/androidx/pdf/viewer/PageMosaicViewTest.java b/pdf/pdf-viewer/src/test/java/androidx/pdf/viewer/PageMosaicViewTest.java
new file mode 100644
index 0000000..0832ad5
--- /dev/null
+++ b/pdf/pdf-viewer/src/test/java/androidx/pdf/viewer/PageMosaicViewTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.pdf.viewer;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.pdf.models.Dimensions;
+import androidx.pdf.util.BitmapRecycler;
+import androidx.pdf.util.MockDrawable;
+import androidx.pdf.widget.MosaicView;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.robolectric.RobolectricTestRunner;
+
+/** Unit tests for {@link PageMosaicView}. */
+@SmallTest
+@RunWith(RobolectricTestRunner.class)
+public class PageMosaicViewTest {
+    @Mock
+    private MosaicView.BitmapSource mMockBitmapSource;
+
+    @Mock
+    private BitmapRecycler mMockBitmapRecycler;
+
+    @Before
+    public void setup() {
+
+    }
+
+    @Test
+    public void newPageMosaicView_pageTextIsNull() {
+        Dimensions dimensions = new Dimensions(800, 800);
+        PageMosaicView pageMosaicView = new PageMosaicView(
+                ApplicationProvider.getApplicationContext(), /* pageNum= */ 0, dimensions,
+                mMockBitmapSource, mMockBitmapRecycler);
+
+        assertThat(pageMosaicView.getPageText() == null).isTrue();
+    }
+
+    @Test
+    public void setOverlay_nonNull_addsNewOverlayForSearchKey() {
+        Dimensions dimensions = new Dimensions(800, 800);
+        PageMosaicView pageMosaicView = new PageMosaicView(
+                ApplicationProvider.getApplicationContext(), /* pageNum= */ 0, dimensions,
+                mMockBitmapSource, mMockBitmapRecycler);
+
+        pageMosaicView.setOverlay(new MockDrawable());
+        assertThat(pageMosaicView.hasOverlay()).isTrue();
+    }
+
+    @Test
+    public void setOverlay_nullOverlay_removesOverlayForSearchKey() {
+        Dimensions dimensions = new Dimensions(800, 800);
+        PageMosaicView pageMosaicView = new PageMosaicView(
+                ApplicationProvider.getApplicationContext(), /* pageNum= */ 0, dimensions,
+                mMockBitmapSource, mMockBitmapRecycler);
+
+        pageMosaicView.setOverlay(new MockDrawable());
+        assertThat(pageMosaicView.hasOverlay()).isTrue();
+
+        pageMosaicView.setOverlay(null);
+        assertThat(pageMosaicView.hasOverlay()).isFalse();
+    }
+
+    @Test
+    public void setPageText_nonNullPageText_setsPageTextAndContentDescription() {
+        Dimensions dimensions = new Dimensions(800, 800);
+        PageMosaicView pageMosaicView = new PageMosaicView(
+                ApplicationProvider.getApplicationContext(), /* pageNum= */ 0, dimensions,
+                mMockBitmapSource, mMockBitmapRecycler) {
+            @Override
+            @NonNull
+            protected String buildContentDescription(@Nullable String pageText, int pageNum) {
+                return (pageText != null) ? pageText : "dummyString";
+            }
+        };
+
+        String pageText = "dummyPageText";
+        pageMosaicView.setPageText(pageText);
+        assertThat(pageMosaicView.getPageText()).isEqualTo(pageText);
+        assertThat(pageMosaicView.getContentDescription()).isEqualTo(pageText);
+    }
+
+    @Test
+    public void setPageText_nullPageText_nullPageTextAndNonNullContentDescription() {
+        String dummyContentDescription = "dummyContentDescription";
+        Dimensions dimensions = new Dimensions(800, 800);
+        PageMosaicView pageMosaicView = new PageMosaicView(
+                ApplicationProvider.getApplicationContext(), /* pageNum= */ 0, dimensions,
+                mMockBitmapSource, mMockBitmapRecycler) {
+            @Override
+            @NonNull
+            protected String buildContentDescription(@Nullable String pageText, int pageNum) {
+                return (pageText != null) ? pageText : dummyContentDescription;
+            }
+        };
+
+        pageMosaicView.setPageText(null);
+        assertThat(pageMosaicView.getPageText() == null).isTrue();
+        assertThat(pageMosaicView.getContentDescription()).isEqualTo(dummyContentDescription);
+    }
+}
diff --git a/pdf/pdf-viewer/src/test/java/androidx/pdf/viewer/PageViewFactoryTest.java b/pdf/pdf-viewer/src/test/java/androidx/pdf/viewer/PageViewFactoryTest.java
new file mode 100644
index 0000000..d14175d
--- /dev/null
+++ b/pdf/pdf-viewer/src/test/java/androidx/pdf/viewer/PageViewFactoryTest.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.pdf.viewer;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
+import android.view.View;
+
+import androidx.pdf.models.Dimensions;
+import androidx.pdf.util.ObservableValue;
+import androidx.pdf.viewer.loader.PdfLoader;
+import androidx.pdf.widget.ZoomView;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.robolectric.RobolectricTestRunner;
+
+@SuppressWarnings("unchecked")
+@SmallTest
+@RunWith(RobolectricTestRunner.class)
+public class PageViewFactoryTest {
+    private final PdfLoader mMockPdfLoader = mock(PdfLoader.class);
+
+    private final PaginatedView mMockPaginatedView = mock(PaginatedView.class);
+
+    private final ZoomView mMockZoomView = mock(ZoomView.class);
+
+    private final PdfViewer.PageTouchHandler mMockPageTouchHandler = mock(
+            PdfViewer.PageTouchHandler.class);
+
+    @Before
+    public void setup() {
+        when(mMockZoomView.zoomScroll()).thenReturn(mock(ObservableValue.class));
+    }
+
+    @Test
+    public void getOrCreatePageView_accessibilityDisabled_newAndSetupPageViewMosaicView() {
+        // Arrange
+        int dummyPageElevation = 100;
+        int dummyWidth = 800;
+        int dummyHeight = 800;
+        Dimensions mockDimensions = new Dimensions(dummyWidth, dummyHeight);
+        ArgumentCaptor<PageViewFactory.PageView> pageViewArgumentCaptor = ArgumentCaptor.forClass(
+                PageViewFactory.PageView.class);
+        PageViewFactory mockPageViewFactory = new MockPageViewAccessbilityDisabledFactory(
+                ApplicationProvider.getApplicationContext(), mMockPdfLoader, mMockPaginatedView,
+                mMockZoomView
+        );
+
+        // Act
+        mockPageViewFactory.getOrCreatePageView(0, dummyPageElevation, mockDimensions,
+                mMockPageTouchHandler);
+
+        // Assert
+        verify(mMockPaginatedView).addView(pageViewArgumentCaptor.capture());
+        assertThat(pageViewArgumentCaptor.getValue().getClass().getSimpleName()).isEqualTo(
+                PageMosaicView.class.getSimpleName());
+        View view = pageViewArgumentCaptor.getValue().asView();
+
+        assertThat(view.getBackground().getClass().getSimpleName()).isEqualTo(
+                ColorDrawable.class.getSimpleName());
+        assertThat(((ColorDrawable) view.getBackground()).getColor()).isEqualTo(Color.WHITE);
+        assertThat(view.getElevation()).isEqualTo(dummyPageElevation);
+        assertThat(((PageMosaicView) pageViewArgumentCaptor.getValue()).getBounds()).isEqualTo(
+                new Rect(0, 0, dummyWidth, dummyHeight));
+    }
+
+    @Test
+    public void getOrCreatePageView_accessibilityEnabled_newAccessibilityAndSetupPageViewWrapper() {
+        // Arrange
+        int dummyPageElevation = 100;
+        int dummyWidth = 800;
+        int dummyHeight = 800;
+        Dimensions mockDimensions = new Dimensions(dummyWidth, dummyHeight);
+        ArgumentCaptor<PageViewFactory.PageView> pageViewArgumentCaptor = ArgumentCaptor.forClass(
+                PageViewFactory.PageView.class);
+        PageViewFactory mockPageViewFactory = new MockPageViewAccessbilityEnabledFactory(
+                ApplicationProvider.getApplicationContext(), mMockPdfLoader, mMockPaginatedView,
+                mMockZoomView
+        );
+
+        // Act
+        mockPageViewFactory.getOrCreatePageView(0, dummyPageElevation, mockDimensions,
+                mMockPageTouchHandler);
+
+        // Assert
+        verify(mMockPaginatedView).addView(pageViewArgumentCaptor.capture());
+        assertThat(pageViewArgumentCaptor.getValue().getClass().getSimpleName()).isEqualTo(
+                AccessibilityPageWrapper.class.getSimpleName());
+
+        PageMosaicView pageMosaicView =
+                pageViewArgumentCaptor.getValue().getPageView();
+        assertThat(pageMosaicView.getBackground().getClass().getSimpleName()).isEqualTo(
+                ColorDrawable.class.getSimpleName());
+        assertThat(((ColorDrawable) pageMosaicView.getBackground()).getColor()).isEqualTo(
+                Color.WHITE);
+        assertThat(pageMosaicView.getElevation()).isEqualTo(dummyPageElevation);
+        assertThat(pageMosaicView.getBounds()).isEqualTo(
+                new Rect(0, 0, dummyWidth, dummyHeight));
+    }
+}
diff --git a/preference/preference/res/values-ne/strings.xml b/preference/preference/res/values-ne/strings.xml
index 12775b4..07559cc 100644
--- a/preference/preference/res/values-ne/strings.xml
+++ b/preference/preference/res/values-ne/strings.xml
@@ -5,7 +5,7 @@
     <string name="v7_preference_off" msgid="3140233346420563315">"निष्क्रिय पार्नुहोस्‌"</string>
     <string name="expand_button_title" msgid="2427401033573778270">"उन्नत"</string>
     <string name="summary_collapsed_preference_list" msgid="9167775378838880170">"<xliff:g id="CURRENT_ITEMS">%1$s</xliff:g>, <xliff:g id="ADDED_ITEMS">%2$s</xliff:g>"</string>
-    <string name="copy" msgid="6083905920877235314">"प्रतिलिपि गर्नुहोस्"</string>
+    <string name="copy" msgid="6083905920877235314">"कपी गर्नुहोस्"</string>
     <string name="preference_copied" msgid="6685851473431805375">"\"<xliff:g id="SUMMARY">%1$s</xliff:g>\" लाई क्लिपबोर्डमा कपी गरियो।"</string>
     <string name="not_set" msgid="6573031135582639649">"सेट गरिएको छैन"</string>
 </resources>
diff --git a/privacysandbox/ads/ads-adservices-java/api/1.1.0-beta09.txt b/privacysandbox/ads/ads-adservices-java/api/1.1.0-beta09.txt
new file mode 100644
index 0000000..d8af6de
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices-java/api/1.1.0-beta09.txt
@@ -0,0 +1,113 @@
+// Signature format: 4.0
+package androidx.privacysandbox.ads.adservices.java.adid {
+
+  public abstract class AdIdManagerFutures {
+    method public static final androidx.privacysandbox.ads.adservices.java.adid.AdIdManagerFutures? from(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_AD_ID) public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.adid.AdId> getAdIdAsync();
+    field public static final androidx.privacysandbox.ads.adservices.java.adid.AdIdManagerFutures.Companion Companion;
+  }
+
+  public static final class AdIdManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.adid.AdIdManagerFutures? from(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.adselection {
+
+  public abstract class AdSelectionManagerFutures {
+    method public static final androidx.privacysandbox.ads.adservices.java.adselection.AdSelectionManagerFutures? from(android.content.Context context);
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.adselection.GetAdSelectionDataOutcome> getAdSelectionDataAsync(androidx.privacysandbox.ads.adservices.adselection.GetAdSelectionDataRequest getAdSelectionDataRequest);
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.adselection.AdSelectionOutcome> persistAdSelectionResultAsync(androidx.privacysandbox.ads.adservices.adselection.PersistAdSelectionResultRequest persistAdSelectionResultRequest);
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext8OptIn public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> reportEventAsync(androidx.privacysandbox.ads.adservices.adselection.ReportEventRequest reportEventRequest);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> reportImpressionAsync(androidx.privacysandbox.ads.adservices.adselection.ReportImpressionRequest reportImpressionRequest);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.adselection.AdSelectionOutcome> selectAdsAsync(androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig);
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.adselection.AdSelectionOutcome> selectAdsAsync(androidx.privacysandbox.ads.adservices.adselection.AdSelectionFromOutcomesConfig adSelectionFromOutcomesConfig);
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext8OptIn public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> updateAdCounterHistogramAsync(androidx.privacysandbox.ads.adservices.adselection.UpdateAdCounterHistogramRequest updateAdCounterHistogramRequest);
+    field public static final androidx.privacysandbox.ads.adservices.java.adselection.AdSelectionManagerFutures.Companion Companion;
+  }
+
+  public static final class AdSelectionManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.adselection.AdSelectionManagerFutures? from(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.appsetid {
+
+  public abstract class AppSetIdManagerFutures {
+    method public static final androidx.privacysandbox.ads.adservices.java.appsetid.AppSetIdManagerFutures? from(android.content.Context context);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.appsetid.AppSetId> getAppSetIdAsync();
+    field public static final androidx.privacysandbox.ads.adservices.java.appsetid.AppSetIdManagerFutures.Companion Companion;
+  }
+
+  public static final class AppSetIdManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.appsetid.AppSetIdManagerFutures? from(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.customaudience {
+
+  public abstract class CustomAudienceManagerFutures {
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> fetchAndJoinCustomAudienceAsync(androidx.privacysandbox.ads.adservices.customaudience.FetchAndJoinCustomAudienceRequest request);
+    method public static final androidx.privacysandbox.ads.adservices.java.customaudience.CustomAudienceManagerFutures? from(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> joinCustomAudienceAsync(androidx.privacysandbox.ads.adservices.customaudience.JoinCustomAudienceRequest request);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> leaveCustomAudienceAsync(androidx.privacysandbox.ads.adservices.customaudience.LeaveCustomAudienceRequest request);
+    field public static final androidx.privacysandbox.ads.adservices.java.customaudience.CustomAudienceManagerFutures.Companion Companion;
+  }
+
+  public static final class CustomAudienceManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.customaudience.CustomAudienceManagerFutures? from(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.measurement {
+
+  public abstract class MeasurementManagerFutures {
+    method public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> deleteRegistrationsAsync(androidx.privacysandbox.ads.adservices.measurement.DeletionRequest deletionRequest);
+    method public static final androidx.privacysandbox.ads.adservices.java.measurement.MeasurementManagerFutures? from(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Integer> getMeasurementApiStatusAsync();
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerSourceAsync(android.net.Uri attributionSource, android.view.InputEvent? inputEvent);
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.RegisterSourceOptIn public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerSourceAsync(androidx.privacysandbox.ads.adservices.measurement.SourceRegistrationRequest request);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerTriggerAsync(android.net.Uri trigger);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerWebSourceAsync(androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest request);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerWebTriggerAsync(androidx.privacysandbox.ads.adservices.measurement.WebTriggerRegistrationRequest request);
+    field public static final androidx.privacysandbox.ads.adservices.java.measurement.MeasurementManagerFutures.Companion Companion;
+  }
+
+  public static final class MeasurementManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.measurement.MeasurementManagerFutures? from(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.signals {
+
+  public abstract class ProtectedSignalsManagerFutures {
+    method public static final androidx.privacysandbox.ads.adservices.java.signals.ProtectedSignalsManagerFutures? from(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_PROTECTED_SIGNALS) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> updateSignalsAsync(androidx.privacysandbox.ads.adservices.signals.UpdateSignalsRequest request);
+    field public static final androidx.privacysandbox.ads.adservices.java.signals.ProtectedSignalsManagerFutures.Companion Companion;
+  }
+
+  public static final class ProtectedSignalsManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.signals.ProtectedSignalsManagerFutures? from(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.topics {
+
+  public abstract class TopicsManagerFutures {
+    method public static final androidx.privacysandbox.ads.adservices.java.topics.TopicsManagerFutures? from(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_TOPICS) public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.topics.GetTopicsResponse> getTopicsAsync(androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest request);
+    field public static final androidx.privacysandbox.ads.adservices.java.topics.TopicsManagerFutures.Companion Companion;
+  }
+
+  public static final class TopicsManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.topics.TopicsManagerFutures? from(android.content.Context context);
+  }
+
+}
+
diff --git a/privacysandbox/ads/ads-adservices-java/api/res-1.1.0-beta09.txt b/privacysandbox/ads/ads-adservices-java/api/res-1.1.0-beta09.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices-java/api/res-1.1.0-beta09.txt
diff --git a/privacysandbox/ads/ads-adservices-java/api/restricted_1.1.0-beta09.txt b/privacysandbox/ads/ads-adservices-java/api/restricted_1.1.0-beta09.txt
new file mode 100644
index 0000000..d8af6de
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices-java/api/restricted_1.1.0-beta09.txt
@@ -0,0 +1,113 @@
+// Signature format: 4.0
+package androidx.privacysandbox.ads.adservices.java.adid {
+
+  public abstract class AdIdManagerFutures {
+    method public static final androidx.privacysandbox.ads.adservices.java.adid.AdIdManagerFutures? from(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_AD_ID) public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.adid.AdId> getAdIdAsync();
+    field public static final androidx.privacysandbox.ads.adservices.java.adid.AdIdManagerFutures.Companion Companion;
+  }
+
+  public static final class AdIdManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.adid.AdIdManagerFutures? from(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.adselection {
+
+  public abstract class AdSelectionManagerFutures {
+    method public static final androidx.privacysandbox.ads.adservices.java.adselection.AdSelectionManagerFutures? from(android.content.Context context);
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.adselection.GetAdSelectionDataOutcome> getAdSelectionDataAsync(androidx.privacysandbox.ads.adservices.adselection.GetAdSelectionDataRequest getAdSelectionDataRequest);
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.adselection.AdSelectionOutcome> persistAdSelectionResultAsync(androidx.privacysandbox.ads.adservices.adselection.PersistAdSelectionResultRequest persistAdSelectionResultRequest);
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext8OptIn public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> reportEventAsync(androidx.privacysandbox.ads.adservices.adselection.ReportEventRequest reportEventRequest);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> reportImpressionAsync(androidx.privacysandbox.ads.adservices.adselection.ReportImpressionRequest reportImpressionRequest);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.adselection.AdSelectionOutcome> selectAdsAsync(androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig);
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.adselection.AdSelectionOutcome> selectAdsAsync(androidx.privacysandbox.ads.adservices.adselection.AdSelectionFromOutcomesConfig adSelectionFromOutcomesConfig);
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext8OptIn public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> updateAdCounterHistogramAsync(androidx.privacysandbox.ads.adservices.adselection.UpdateAdCounterHistogramRequest updateAdCounterHistogramRequest);
+    field public static final androidx.privacysandbox.ads.adservices.java.adselection.AdSelectionManagerFutures.Companion Companion;
+  }
+
+  public static final class AdSelectionManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.adselection.AdSelectionManagerFutures? from(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.appsetid {
+
+  public abstract class AppSetIdManagerFutures {
+    method public static final androidx.privacysandbox.ads.adservices.java.appsetid.AppSetIdManagerFutures? from(android.content.Context context);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.appsetid.AppSetId> getAppSetIdAsync();
+    field public static final androidx.privacysandbox.ads.adservices.java.appsetid.AppSetIdManagerFutures.Companion Companion;
+  }
+
+  public static final class AppSetIdManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.appsetid.AppSetIdManagerFutures? from(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.customaudience {
+
+  public abstract class CustomAudienceManagerFutures {
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> fetchAndJoinCustomAudienceAsync(androidx.privacysandbox.ads.adservices.customaudience.FetchAndJoinCustomAudienceRequest request);
+    method public static final androidx.privacysandbox.ads.adservices.java.customaudience.CustomAudienceManagerFutures? from(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> joinCustomAudienceAsync(androidx.privacysandbox.ads.adservices.customaudience.JoinCustomAudienceRequest request);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> leaveCustomAudienceAsync(androidx.privacysandbox.ads.adservices.customaudience.LeaveCustomAudienceRequest request);
+    field public static final androidx.privacysandbox.ads.adservices.java.customaudience.CustomAudienceManagerFutures.Companion Companion;
+  }
+
+  public static final class CustomAudienceManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.customaudience.CustomAudienceManagerFutures? from(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.measurement {
+
+  public abstract class MeasurementManagerFutures {
+    method public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> deleteRegistrationsAsync(androidx.privacysandbox.ads.adservices.measurement.DeletionRequest deletionRequest);
+    method public static final androidx.privacysandbox.ads.adservices.java.measurement.MeasurementManagerFutures? from(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Integer> getMeasurementApiStatusAsync();
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerSourceAsync(android.net.Uri attributionSource, android.view.InputEvent? inputEvent);
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.RegisterSourceOptIn public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerSourceAsync(androidx.privacysandbox.ads.adservices.measurement.SourceRegistrationRequest request);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerTriggerAsync(android.net.Uri trigger);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerWebSourceAsync(androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest request);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerWebTriggerAsync(androidx.privacysandbox.ads.adservices.measurement.WebTriggerRegistrationRequest request);
+    field public static final androidx.privacysandbox.ads.adservices.java.measurement.MeasurementManagerFutures.Companion Companion;
+  }
+
+  public static final class MeasurementManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.measurement.MeasurementManagerFutures? from(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.signals {
+
+  public abstract class ProtectedSignalsManagerFutures {
+    method public static final androidx.privacysandbox.ads.adservices.java.signals.ProtectedSignalsManagerFutures? from(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_PROTECTED_SIGNALS) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> updateSignalsAsync(androidx.privacysandbox.ads.adservices.signals.UpdateSignalsRequest request);
+    field public static final androidx.privacysandbox.ads.adservices.java.signals.ProtectedSignalsManagerFutures.Companion Companion;
+  }
+
+  public static final class ProtectedSignalsManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.signals.ProtectedSignalsManagerFutures? from(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.topics {
+
+  public abstract class TopicsManagerFutures {
+    method public static final androidx.privacysandbox.ads.adservices.java.topics.TopicsManagerFutures? from(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_TOPICS) public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.topics.GetTopicsResponse> getTopicsAsync(androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest request);
+    field public static final androidx.privacysandbox.ads.adservices.java.topics.TopicsManagerFutures.Companion Companion;
+  }
+
+  public static final class TopicsManagerFutures.Companion {
+    method public androidx.privacysandbox.ads.adservices.java.topics.TopicsManagerFutures? from(android.content.Context context);
+  }
+
+}
+
diff --git a/privacysandbox/ads/ads-adservices/api/1.1.0-beta09.txt b/privacysandbox/ads/ads-adservices/api/1.1.0-beta09.txt
new file mode 100644
index 0000000..020b263
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices/api/1.1.0-beta09.txt
@@ -0,0 +1,556 @@
+// Signature format: 4.0
+package androidx.privacysandbox.ads.adservices.adid {
+
+  public final class AdId {
+    method public String getAdId();
+    method public boolean isLimitAdTrackingEnabled();
+    property public final String adId;
+    property public final boolean isLimitAdTrackingEnabled;
+  }
+
+  public abstract class AdIdManager {
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_AD_ID) public abstract suspend Object? getAdId(kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.adid.AdId>);
+    method public static final androidx.privacysandbox.ads.adservices.adid.AdIdManager? obtain(android.content.Context context);
+    field public static final androidx.privacysandbox.ads.adservices.adid.AdIdManager.Companion Companion;
+  }
+
+  public static final class AdIdManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.adid.AdIdManager? obtain(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.adselection {
+
+  public final class AdSelectionConfig {
+    ctor public AdSelectionConfig(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller, android.net.Uri decisionLogicUri, java.util.List<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier> customAudienceBuyers, androidx.privacysandbox.ads.adservices.common.AdSelectionSignals adSelectionSignals, androidx.privacysandbox.ads.adservices.common.AdSelectionSignals sellerSignals, java.util.Map<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier,androidx.privacysandbox.ads.adservices.common.AdSelectionSignals> perBuyerSignals, android.net.Uri trustedScoringSignalsUri);
+    method public androidx.privacysandbox.ads.adservices.common.AdSelectionSignals getAdSelectionSignals();
+    method public java.util.List<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier> getCustomAudienceBuyers();
+    method public android.net.Uri getDecisionLogicUri();
+    method public java.util.Map<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier,androidx.privacysandbox.ads.adservices.common.AdSelectionSignals> getPerBuyerSignals();
+    method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getSeller();
+    method public androidx.privacysandbox.ads.adservices.common.AdSelectionSignals getSellerSignals();
+    method public android.net.Uri getTrustedScoringSignalsUri();
+    property public final androidx.privacysandbox.ads.adservices.common.AdSelectionSignals adSelectionSignals;
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier> customAudienceBuyers;
+    property public final android.net.Uri decisionLogicUri;
+    property public final java.util.Map<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier,androidx.privacysandbox.ads.adservices.common.AdSelectionSignals> perBuyerSignals;
+    property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller;
+    property public final androidx.privacysandbox.ads.adservices.common.AdSelectionSignals sellerSignals;
+    property public final android.net.Uri trustedScoringSignalsUri;
+  }
+
+  @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public final class AdSelectionFromOutcomesConfig {
+    ctor public AdSelectionFromOutcomesConfig(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller, java.util.List<java.lang.Long> adSelectionIds, androidx.privacysandbox.ads.adservices.common.AdSelectionSignals adSelectionSignals, android.net.Uri selectionLogicUri);
+    method public java.util.List<java.lang.Long> getAdSelectionIds();
+    method public androidx.privacysandbox.ads.adservices.common.AdSelectionSignals getAdSelectionSignals();
+    method public android.net.Uri getSelectionLogicUri();
+    method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getSeller();
+    method public void setSelectionLogicUri(android.net.Uri);
+    property public final java.util.List<java.lang.Long> adSelectionIds;
+    property public final androidx.privacysandbox.ads.adservices.common.AdSelectionSignals adSelectionSignals;
+    property public final android.net.Uri selectionLogicUri;
+    property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller;
+  }
+
+  public abstract class AdSelectionManager {
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public abstract suspend Object? getAdSelectionData(androidx.privacysandbox.ads.adservices.adselection.GetAdSelectionDataRequest getAdSelectionDataRequest, kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.adselection.GetAdSelectionDataOutcome>);
+    method public static final androidx.privacysandbox.ads.adservices.adselection.AdSelectionManager? obtain(android.content.Context context);
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public abstract suspend Object? persistAdSelectionResult(androidx.privacysandbox.ads.adservices.adselection.PersistAdSelectionResultRequest persistAdSelectionResultRequest, kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.adselection.AdSelectionOutcome>);
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext8OptIn public abstract suspend Object? reportEvent(androidx.privacysandbox.ads.adservices.adselection.ReportEventRequest reportEventRequest, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? reportImpression(androidx.privacysandbox.ads.adservices.adselection.ReportImpressionRequest reportImpressionRequest, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? selectAds(androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig, kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.adselection.AdSelectionOutcome>);
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public abstract suspend Object? selectAds(androidx.privacysandbox.ads.adservices.adselection.AdSelectionFromOutcomesConfig adSelectionFromOutcomesConfig, kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.adselection.AdSelectionOutcome>);
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext8OptIn public abstract suspend Object? updateAdCounterHistogram(androidx.privacysandbox.ads.adservices.adselection.UpdateAdCounterHistogramRequest updateAdCounterHistogramRequest, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    field public static final androidx.privacysandbox.ads.adservices.adselection.AdSelectionManager.Companion Companion;
+  }
+
+  public static final class AdSelectionManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.adselection.AdSelectionManager? obtain(android.content.Context context);
+  }
+
+  public final class AdSelectionOutcome {
+    ctor public AdSelectionOutcome(long adSelectionId, android.net.Uri renderUri);
+    method public long getAdSelectionId();
+    method public android.net.Uri getRenderUri();
+    method @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public boolean hasOutcome();
+    property public final long adSelectionId;
+    property public final android.net.Uri renderUri;
+    field public static final androidx.privacysandbox.ads.adservices.adselection.AdSelectionOutcome.Companion Companion;
+    field @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public static final androidx.privacysandbox.ads.adservices.adselection.AdSelectionOutcome NO_OUTCOME;
+  }
+
+  @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public static final class AdSelectionOutcome.Companion {
+  }
+
+  @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public final class GetAdSelectionDataOutcome {
+    ctor public GetAdSelectionDataOutcome(long adSelectionId, optional byte[]? adSelectionData);
+    method public byte[]? getAdSelectionData();
+    method public long getAdSelectionId();
+    property public final byte[]? adSelectionData;
+    property public final long adSelectionId;
+  }
+
+  @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public final class GetAdSelectionDataRequest {
+    ctor public GetAdSelectionDataRequest(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller);
+    ctor public GetAdSelectionDataRequest(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller, optional android.net.Uri? coordinatorOriginUri);
+    method public android.net.Uri? getCoordinatorOriginUri();
+    method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getSeller();
+    property public final android.net.Uri? coordinatorOriginUri;
+    property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller;
+  }
+
+  @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public final class PersistAdSelectionResultRequest {
+    ctor public PersistAdSelectionResultRequest(long adSelectionId, optional androidx.privacysandbox.ads.adservices.common.AdTechIdentifier? seller, optional byte[]? adSelectionResult);
+    method public long getAdSelectionId();
+    method public byte[]? getAdSelectionResult();
+    method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier? getSeller();
+    property public final long adSelectionId;
+    property public final byte[]? adSelectionResult;
+    property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier? seller;
+  }
+
+  @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext8OptIn public final class ReportEventRequest {
+    ctor public ReportEventRequest(long adSelectionId, String eventKey, String eventData, int reportingDestinations, optional android.view.InputEvent? inputEvent);
+    method public long getAdSelectionId();
+    method public String getEventData();
+    method public String getEventKey();
+    method public android.view.InputEvent? getInputEvent();
+    method public int getReportingDestinations();
+    property public final long adSelectionId;
+    property public final String eventData;
+    property public final String eventKey;
+    property public final android.view.InputEvent? inputEvent;
+    property public final int reportingDestinations;
+    field public static final androidx.privacysandbox.ads.adservices.adselection.ReportEventRequest.Companion Companion;
+    field public static final int FLAG_REPORTING_DESTINATION_BUYER = 2; // 0x2
+    field public static final int FLAG_REPORTING_DESTINATION_SELLER = 1; // 0x1
+  }
+
+  public static final class ReportEventRequest.Companion {
+  }
+
+  public final class ReportImpressionRequest {
+    ctor @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext8OptIn public ReportImpressionRequest(long adSelectionId);
+    ctor public ReportImpressionRequest(long adSelectionId, androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig);
+    method public androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig getAdSelectionConfig();
+    method public long getAdSelectionId();
+    property public final androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig;
+    property public final long adSelectionId;
+  }
+
+  @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext8OptIn public final class UpdateAdCounterHistogramRequest {
+    ctor public UpdateAdCounterHistogramRequest(long adSelectionId, int adEventType, androidx.privacysandbox.ads.adservices.common.AdTechIdentifier callerAdTech);
+    method public int getAdEventType();
+    method public long getAdSelectionId();
+    method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getCallerAdTech();
+    property public final int adEventType;
+    property public final long adSelectionId;
+    property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier callerAdTech;
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.appsetid {
+
+  public final class AppSetId {
+    ctor public AppSetId(String id, int scope);
+    method public String getId();
+    method public int getScope();
+    property public final String id;
+    property public final int scope;
+    field public static final androidx.privacysandbox.ads.adservices.appsetid.AppSetId.Companion Companion;
+    field public static final int SCOPE_APP = 1; // 0x1
+    field public static final int SCOPE_DEVELOPER = 2; // 0x2
+  }
+
+  public static final class AppSetId.Companion {
+  }
+
+  public abstract class AppSetIdManager {
+    method public abstract suspend Object? getAppSetId(kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.appsetid.AppSetId>);
+    method public static final androidx.privacysandbox.ads.adservices.appsetid.AppSetIdManager? obtain(android.content.Context context);
+    field public static final androidx.privacysandbox.ads.adservices.appsetid.AppSetIdManager.Companion Companion;
+  }
+
+  public static final class AppSetIdManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.appsetid.AppSetIdManager? obtain(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.common {
+
+  public final class AdData {
+    ctor public AdData(android.net.Uri renderUri, String metadata);
+    ctor @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext8OptIn public AdData(android.net.Uri renderUri, String metadata, optional java.util.Set<java.lang.Integer> adCounterKeys, optional androidx.privacysandbox.ads.adservices.common.AdFilters? adFilters);
+    ctor @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public AdData(android.net.Uri renderUri, String metadata, optional java.util.Set<java.lang.Integer> adCounterKeys, optional androidx.privacysandbox.ads.adservices.common.AdFilters? adFilters, optional String? adRenderId);
+    method public java.util.Set<java.lang.Integer> getAdCounterKeys();
+    method public androidx.privacysandbox.ads.adservices.common.AdFilters? getAdFilters();
+    method public String? getAdRenderId();
+    method public String getMetadata();
+    method public android.net.Uri getRenderUri();
+    property public final java.util.Set<java.lang.Integer> adCounterKeys;
+    property public final androidx.privacysandbox.ads.adservices.common.AdFilters? adFilters;
+    property public final String? adRenderId;
+    property public final String metadata;
+    property public final android.net.Uri renderUri;
+  }
+
+  @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext8OptIn public final class AdFilters {
+    ctor public AdFilters(androidx.privacysandbox.ads.adservices.common.FrequencyCapFilters? frequencyCapFilters);
+    method public androidx.privacysandbox.ads.adservices.common.FrequencyCapFilters? getFrequencyCapFilters();
+    property public final androidx.privacysandbox.ads.adservices.common.FrequencyCapFilters? frequencyCapFilters;
+  }
+
+  public final class AdSelectionSignals {
+    ctor public AdSelectionSignals(String signals);
+    method public String getSignals();
+    property public final String signals;
+  }
+
+  public final class AdTechIdentifier {
+    ctor public AdTechIdentifier(String identifier);
+    method public String getIdentifier();
+    property public final String identifier;
+  }
+
+  public sealed interface ExperimentalFeatures {
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn(message="The Ext10 API is experimental.", level=kotlin.RequiresOptIn.Level.WARNING) public static @interface ExperimentalFeatures.Ext10OptIn {
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn(message="The Ext11 API is experimental.", level=kotlin.RequiresOptIn.Level.WARNING) public static @interface ExperimentalFeatures.Ext11OptIn {
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn(message="The Ext12 API is experimental.", level=kotlin.RequiresOptIn.Level.WARNING) public static @interface ExperimentalFeatures.Ext12OptIn {
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn(message="The Ext8 API is experimental.", level=kotlin.RequiresOptIn.Level.WARNING) public static @interface ExperimentalFeatures.Ext8OptIn {
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn(message="This API is experimental.", level=kotlin.RequiresOptIn.Level.WARNING) public static @interface ExperimentalFeatures.RegisterSourceOptIn {
+  }
+
+  @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext8OptIn public final class FrequencyCapFilters {
+    ctor public FrequencyCapFilters();
+    ctor public FrequencyCapFilters(optional java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> keyedFrequencyCapsForWinEvents);
+    ctor public FrequencyCapFilters(optional java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> keyedFrequencyCapsForWinEvents, optional java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> keyedFrequencyCapsForImpressionEvents);
+    ctor public FrequencyCapFilters(optional java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> keyedFrequencyCapsForWinEvents, optional java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> keyedFrequencyCapsForImpressionEvents, optional java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> keyedFrequencyCapsForViewEvents);
+    ctor public FrequencyCapFilters(optional java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> keyedFrequencyCapsForWinEvents, optional java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> keyedFrequencyCapsForImpressionEvents, optional java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> keyedFrequencyCapsForViewEvents, optional java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> keyedFrequencyCapsForClickEvents);
+    method public java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> getKeyedFrequencyCapsForClickEvents();
+    method public java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> getKeyedFrequencyCapsForImpressionEvents();
+    method public java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> getKeyedFrequencyCapsForViewEvents();
+    method public java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> getKeyedFrequencyCapsForWinEvents();
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> keyedFrequencyCapsForClickEvents;
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> keyedFrequencyCapsForImpressionEvents;
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> keyedFrequencyCapsForViewEvents;
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> keyedFrequencyCapsForWinEvents;
+    field public static final int AD_EVENT_TYPE_CLICK = 3; // 0x3
+    field public static final int AD_EVENT_TYPE_IMPRESSION = 1; // 0x1
+    field public static final int AD_EVENT_TYPE_VIEW = 2; // 0x2
+    field public static final int AD_EVENT_TYPE_WIN = 0; // 0x0
+    field public static final androidx.privacysandbox.ads.adservices.common.FrequencyCapFilters.Companion Companion;
+  }
+
+  public static final class FrequencyCapFilters.Companion {
+  }
+
+  @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext8OptIn public final class KeyedFrequencyCap {
+    ctor public KeyedFrequencyCap(int adCounterKey, int maxCount, java.time.Duration interval);
+    method public int getAdCounterKey();
+    method public java.time.Duration getInterval();
+    method public int getMaxCount();
+    property public final int adCounterKey;
+    property public final java.time.Duration interval;
+    property public final int maxCount;
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.customaudience {
+
+  public final class CustomAudience {
+    ctor public CustomAudience(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer, String name, android.net.Uri dailyUpdateUri, android.net.Uri biddingLogicUri, java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads, optional java.time.Instant? activationTime, optional java.time.Instant? expirationTime, optional androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? userBiddingSignals, optional androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData? trustedBiddingSignals);
+    method public java.time.Instant? getActivationTime();
+    method public java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> getAds();
+    method public android.net.Uri getBiddingLogicUri();
+    method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getBuyer();
+    method public android.net.Uri getDailyUpdateUri();
+    method public java.time.Instant? getExpirationTime();
+    method public String getName();
+    method public androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData? getTrustedBiddingSignals();
+    method public androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? getUserBiddingSignals();
+    property public final java.time.Instant? activationTime;
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads;
+    property public final android.net.Uri biddingLogicUri;
+    property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer;
+    property public final android.net.Uri dailyUpdateUri;
+    property public final java.time.Instant? expirationTime;
+    property public final String name;
+    property public final androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData? trustedBiddingSignals;
+    property public final androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? userBiddingSignals;
+  }
+
+  public static final class CustomAudience.Builder {
+    ctor public CustomAudience.Builder(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer, String name, android.net.Uri dailyUpdateUri, android.net.Uri biddingLogicUri, java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience build();
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setActivationTime(java.time.Instant activationTime);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setAds(java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setBiddingLogicUri(android.net.Uri biddingLogicUri);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setBuyer(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setDailyUpdateUri(android.net.Uri dailyUpdateUri);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setExpirationTime(java.time.Instant expirationTime);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setName(String name);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setTrustedBiddingData(androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData trustedBiddingSignals);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setUserBiddingSignals(androidx.privacysandbox.ads.adservices.common.AdSelectionSignals userBiddingSignals);
+  }
+
+  public abstract class CustomAudienceManager {
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public abstract suspend Object? fetchAndJoinCustomAudience(androidx.privacysandbox.ads.adservices.customaudience.FetchAndJoinCustomAudienceRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? joinCustomAudience(androidx.privacysandbox.ads.adservices.customaudience.JoinCustomAudienceRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? leaveCustomAudience(androidx.privacysandbox.ads.adservices.customaudience.LeaveCustomAudienceRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public static final androidx.privacysandbox.ads.adservices.customaudience.CustomAudienceManager? obtain(android.content.Context context);
+    field public static final androidx.privacysandbox.ads.adservices.customaudience.CustomAudienceManager.Companion Companion;
+  }
+
+  public static final class CustomAudienceManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudienceManager? obtain(android.content.Context context);
+  }
+
+  @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public final class FetchAndJoinCustomAudienceRequest {
+    ctor public FetchAndJoinCustomAudienceRequest(android.net.Uri fetchUri, optional String? name, optional java.time.Instant? activationTime, optional java.time.Instant? expirationTime, optional androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? userBiddingSignals);
+    method public java.time.Instant? getActivationTime();
+    method public java.time.Instant? getExpirationTime();
+    method public android.net.Uri getFetchUri();
+    method public String? getName();
+    method public androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? getUserBiddingSignals();
+    property public final java.time.Instant? activationTime;
+    property public final java.time.Instant? expirationTime;
+    property public final android.net.Uri fetchUri;
+    property public final String? name;
+    property public final androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? userBiddingSignals;
+  }
+
+  public final class JoinCustomAudienceRequest {
+    ctor public JoinCustomAudienceRequest(androidx.privacysandbox.ads.adservices.customaudience.CustomAudience customAudience);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience getCustomAudience();
+    property public final androidx.privacysandbox.ads.adservices.customaudience.CustomAudience customAudience;
+  }
+
+  public final class LeaveCustomAudienceRequest {
+    ctor public LeaveCustomAudienceRequest(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer, String name);
+    method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getBuyer();
+    method public String getName();
+    property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer;
+    property public final String name;
+  }
+
+  public final class TrustedBiddingData {
+    ctor public TrustedBiddingData(android.net.Uri trustedBiddingUri, java.util.List<java.lang.String> trustedBiddingKeys);
+    method public java.util.List<java.lang.String> getTrustedBiddingKeys();
+    method public android.net.Uri getTrustedBiddingUri();
+    property public final java.util.List<java.lang.String> trustedBiddingKeys;
+    property public final android.net.Uri trustedBiddingUri;
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.measurement {
+
+  @RequiresApi(android.os.Build.VERSION_CODES.O) public final class DeletionRequest {
+    ctor public DeletionRequest(int deletionMode, int matchBehavior, optional java.time.Instant start, optional java.time.Instant end, optional java.util.List<? extends android.net.Uri> domainUris, optional java.util.List<? extends android.net.Uri> originUris);
+    method public int getDeletionMode();
+    method public java.util.List<android.net.Uri> getDomainUris();
+    method public java.time.Instant getEnd();
+    method public int getMatchBehavior();
+    method public java.util.List<android.net.Uri> getOriginUris();
+    method public java.time.Instant getStart();
+    property public final int deletionMode;
+    property public final java.util.List<android.net.Uri> domainUris;
+    property public final java.time.Instant end;
+    property public final int matchBehavior;
+    property public final java.util.List<android.net.Uri> originUris;
+    property public final java.time.Instant start;
+    field public static final androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Companion Companion;
+    field public static final int DELETION_MODE_ALL = 0; // 0x0
+    field public static final int DELETION_MODE_EXCLUDE_INTERNAL_DATA = 1; // 0x1
+    field public static final int MATCH_BEHAVIOR_DELETE = 0; // 0x0
+    field public static final int MATCH_BEHAVIOR_PRESERVE = 1; // 0x1
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.O) public static final class DeletionRequest.Builder {
+    ctor public DeletionRequest.Builder(int deletionMode, int matchBehavior);
+    method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest build();
+    method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setDomainUris(java.util.List<? extends android.net.Uri> domainUris);
+    method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setEnd(java.time.Instant end);
+    method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setOriginUris(java.util.List<? extends android.net.Uri> originUris);
+    method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setStart(java.time.Instant start);
+  }
+
+  public static final class DeletionRequest.Companion {
+  }
+
+  public abstract class MeasurementManager {
+    ctor public MeasurementManager();
+    method public abstract suspend Object? deleteRegistrations(androidx.privacysandbox.ads.adservices.measurement.DeletionRequest deletionRequest, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? getMeasurementApiStatus(kotlin.coroutines.Continuation<? super java.lang.Integer>);
+    method public static final androidx.privacysandbox.ads.adservices.measurement.MeasurementManager? obtain(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerSource(android.net.Uri attributionSource, android.view.InputEvent? inputEvent, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.RegisterSourceOptIn public abstract suspend Object? registerSource(androidx.privacysandbox.ads.adservices.measurement.SourceRegistrationRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerTrigger(android.net.Uri trigger, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerWebSource(androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerWebTrigger(androidx.privacysandbox.ads.adservices.measurement.WebTriggerRegistrationRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    field public static final androidx.privacysandbox.ads.adservices.measurement.MeasurementManager.Companion Companion;
+    field public static final int MEASUREMENT_API_STATE_DISABLED = 0; // 0x0
+    field public static final int MEASUREMENT_API_STATE_ENABLED = 1; // 0x1
+  }
+
+  public static final class MeasurementManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.measurement.MeasurementManager? obtain(android.content.Context context);
+  }
+
+  @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.RegisterSourceOptIn public final class SourceRegistrationRequest {
+    ctor public SourceRegistrationRequest(java.util.List<? extends android.net.Uri> registrationUris, optional android.view.InputEvent? inputEvent);
+    method public android.view.InputEvent? getInputEvent();
+    method public java.util.List<android.net.Uri> getRegistrationUris();
+    property public final android.view.InputEvent? inputEvent;
+    property public final java.util.List<android.net.Uri> registrationUris;
+  }
+
+  public static final class SourceRegistrationRequest.Builder {
+    ctor public SourceRegistrationRequest.Builder(java.util.List<? extends android.net.Uri> registrationUris);
+    method public androidx.privacysandbox.ads.adservices.measurement.SourceRegistrationRequest build();
+    method public androidx.privacysandbox.ads.adservices.measurement.SourceRegistrationRequest.Builder setInputEvent(android.view.InputEvent inputEvent);
+  }
+
+  public final class WebSourceParams {
+    ctor public WebSourceParams(android.net.Uri registrationUri, boolean debugKeyAllowed);
+    method public boolean getDebugKeyAllowed();
+    method public android.net.Uri getRegistrationUri();
+    property public final boolean debugKeyAllowed;
+    property public final android.net.Uri registrationUri;
+  }
+
+  public final class WebSourceRegistrationRequest {
+    ctor public WebSourceRegistrationRequest(java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> webSourceParams, android.net.Uri topOriginUri, optional android.view.InputEvent? inputEvent, optional android.net.Uri? appDestination, optional android.net.Uri? webDestination, optional android.net.Uri? verifiedDestination);
+    method public android.net.Uri? getAppDestination();
+    method public android.view.InputEvent? getInputEvent();
+    method public android.net.Uri getTopOriginUri();
+    method public android.net.Uri? getVerifiedDestination();
+    method public android.net.Uri? getWebDestination();
+    method public java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> getWebSourceParams();
+    property public final android.net.Uri? appDestination;
+    property public final android.view.InputEvent? inputEvent;
+    property public final android.net.Uri topOriginUri;
+    property public final android.net.Uri? verifiedDestination;
+    property public final android.net.Uri? webDestination;
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> webSourceParams;
+  }
+
+  public static final class WebSourceRegistrationRequest.Builder {
+    ctor public WebSourceRegistrationRequest.Builder(java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> webSourceParams, android.net.Uri topOriginUri);
+    method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest build();
+    method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setAppDestination(android.net.Uri? appDestination);
+    method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setInputEvent(android.view.InputEvent inputEvent);
+    method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setVerifiedDestination(android.net.Uri? verifiedDestination);
+    method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setWebDestination(android.net.Uri? webDestination);
+  }
+
+  public final class WebTriggerParams {
+    ctor public WebTriggerParams(android.net.Uri registrationUri, boolean debugKeyAllowed);
+    method public boolean getDebugKeyAllowed();
+    method public android.net.Uri getRegistrationUri();
+    property public final boolean debugKeyAllowed;
+    property public final android.net.Uri registrationUri;
+  }
+
+  public final class WebTriggerRegistrationRequest {
+    ctor public WebTriggerRegistrationRequest(java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebTriggerParams> webTriggerParams, android.net.Uri destination);
+    method public android.net.Uri getDestination();
+    method public java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebTriggerParams> getWebTriggerParams();
+    property public final android.net.Uri destination;
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebTriggerParams> webTriggerParams;
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.signals {
+
+  public abstract class ProtectedSignalsManager {
+    method @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext12OptIn public static final androidx.privacysandbox.ads.adservices.signals.ProtectedSignalsManager? obtain(android.content.Context context);
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_PROTECTED_SIGNALS) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext12OptIn public abstract suspend Object? updateSignals(androidx.privacysandbox.ads.adservices.signals.UpdateSignalsRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    field public static final androidx.privacysandbox.ads.adservices.signals.ProtectedSignalsManager.Companion Companion;
+  }
+
+  public static final class ProtectedSignalsManager.Companion {
+    method @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext12OptIn public androidx.privacysandbox.ads.adservices.signals.ProtectedSignalsManager? obtain(android.content.Context context);
+  }
+
+  @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext12OptIn public final class UpdateSignalsRequest {
+    ctor public UpdateSignalsRequest(android.net.Uri updateUri);
+    method public android.net.Uri getUpdateUri();
+    property public final android.net.Uri updateUri;
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.topics {
+
+  @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext11OptIn public final class EncryptedTopic {
+    ctor public EncryptedTopic(byte[] encryptedTopic, String keyIdentifier, byte[] encapsulatedKey);
+    method public byte[] getEncapsulatedKey();
+    method public byte[] getEncryptedTopic();
+    method public String getKeyIdentifier();
+    property public final byte[] encapsulatedKey;
+    property public final byte[] encryptedTopic;
+    property public final String keyIdentifier;
+  }
+
+  public final class GetTopicsRequest {
+    ctor public GetTopicsRequest(optional String adsSdkName, optional boolean shouldRecordObservation);
+    method public String getAdsSdkName();
+    method public boolean shouldRecordObservation();
+    property public final String adsSdkName;
+    property public final boolean shouldRecordObservation;
+  }
+
+  public static final class GetTopicsRequest.Builder {
+    ctor public GetTopicsRequest.Builder();
+    method public androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest build();
+    method public androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest.Builder setAdsSdkName(String adsSdkName);
+    method public androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest.Builder setShouldRecordObservation(boolean shouldRecordObservation);
+  }
+
+  public final class GetTopicsResponse {
+    ctor public GetTopicsResponse(java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> topics);
+    ctor @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext11OptIn public GetTopicsResponse(java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> topics, java.util.List<androidx.privacysandbox.ads.adservices.topics.EncryptedTopic> encryptedTopics);
+    method public java.util.List<androidx.privacysandbox.ads.adservices.topics.EncryptedTopic> getEncryptedTopics();
+    method public java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> getTopics();
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.topics.EncryptedTopic> encryptedTopics;
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> topics;
+  }
+
+  public final class Topic {
+    ctor public Topic(long taxonomyVersion, long modelVersion, int topicId);
+    method public long getModelVersion();
+    method public long getTaxonomyVersion();
+    method public int getTopicId();
+    property public final long modelVersion;
+    property public final long taxonomyVersion;
+    property public final int topicId;
+  }
+
+  public abstract class TopicsManager {
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_TOPICS) public abstract suspend Object? getTopics(androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest request, kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.topics.GetTopicsResponse>);
+    method public static final androidx.privacysandbox.ads.adservices.topics.TopicsManager? obtain(android.content.Context context);
+    field public static final androidx.privacysandbox.ads.adservices.topics.TopicsManager.Companion Companion;
+  }
+
+  public static final class TopicsManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.topics.TopicsManager? obtain(android.content.Context context);
+  }
+
+}
+
diff --git a/privacysandbox/ads/ads-adservices/api/current.txt b/privacysandbox/ads/ads-adservices/api/current.txt
index dca5235..020b263 100644
--- a/privacysandbox/ads/ads-adservices/api/current.txt
+++ b/privacysandbox/ads/ads-adservices/api/current.txt
@@ -92,6 +92,7 @@
   }
 
   @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public final class GetAdSelectionDataRequest {
+    ctor public GetAdSelectionDataRequest(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller);
     ctor public GetAdSelectionDataRequest(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller, optional android.net.Uri? coordinatorOriginUri);
     method public android.net.Uri? getCoordinatorOriginUri();
     method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getSeller();
diff --git a/privacysandbox/ads/ads-adservices/api/res-1.1.0-beta09.txt b/privacysandbox/ads/ads-adservices/api/res-1.1.0-beta09.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices/api/res-1.1.0-beta09.txt
diff --git a/privacysandbox/ads/ads-adservices/api/restricted_1.1.0-beta09.txt b/privacysandbox/ads/ads-adservices/api/restricted_1.1.0-beta09.txt
new file mode 100644
index 0000000..020b263
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices/api/restricted_1.1.0-beta09.txt
@@ -0,0 +1,556 @@
+// Signature format: 4.0
+package androidx.privacysandbox.ads.adservices.adid {
+
+  public final class AdId {
+    method public String getAdId();
+    method public boolean isLimitAdTrackingEnabled();
+    property public final String adId;
+    property public final boolean isLimitAdTrackingEnabled;
+  }
+
+  public abstract class AdIdManager {
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_AD_ID) public abstract suspend Object? getAdId(kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.adid.AdId>);
+    method public static final androidx.privacysandbox.ads.adservices.adid.AdIdManager? obtain(android.content.Context context);
+    field public static final androidx.privacysandbox.ads.adservices.adid.AdIdManager.Companion Companion;
+  }
+
+  public static final class AdIdManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.adid.AdIdManager? obtain(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.adselection {
+
+  public final class AdSelectionConfig {
+    ctor public AdSelectionConfig(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller, android.net.Uri decisionLogicUri, java.util.List<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier> customAudienceBuyers, androidx.privacysandbox.ads.adservices.common.AdSelectionSignals adSelectionSignals, androidx.privacysandbox.ads.adservices.common.AdSelectionSignals sellerSignals, java.util.Map<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier,androidx.privacysandbox.ads.adservices.common.AdSelectionSignals> perBuyerSignals, android.net.Uri trustedScoringSignalsUri);
+    method public androidx.privacysandbox.ads.adservices.common.AdSelectionSignals getAdSelectionSignals();
+    method public java.util.List<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier> getCustomAudienceBuyers();
+    method public android.net.Uri getDecisionLogicUri();
+    method public java.util.Map<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier,androidx.privacysandbox.ads.adservices.common.AdSelectionSignals> getPerBuyerSignals();
+    method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getSeller();
+    method public androidx.privacysandbox.ads.adservices.common.AdSelectionSignals getSellerSignals();
+    method public android.net.Uri getTrustedScoringSignalsUri();
+    property public final androidx.privacysandbox.ads.adservices.common.AdSelectionSignals adSelectionSignals;
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier> customAudienceBuyers;
+    property public final android.net.Uri decisionLogicUri;
+    property public final java.util.Map<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier,androidx.privacysandbox.ads.adservices.common.AdSelectionSignals> perBuyerSignals;
+    property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller;
+    property public final androidx.privacysandbox.ads.adservices.common.AdSelectionSignals sellerSignals;
+    property public final android.net.Uri trustedScoringSignalsUri;
+  }
+
+  @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public final class AdSelectionFromOutcomesConfig {
+    ctor public AdSelectionFromOutcomesConfig(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller, java.util.List<java.lang.Long> adSelectionIds, androidx.privacysandbox.ads.adservices.common.AdSelectionSignals adSelectionSignals, android.net.Uri selectionLogicUri);
+    method public java.util.List<java.lang.Long> getAdSelectionIds();
+    method public androidx.privacysandbox.ads.adservices.common.AdSelectionSignals getAdSelectionSignals();
+    method public android.net.Uri getSelectionLogicUri();
+    method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getSeller();
+    method public void setSelectionLogicUri(android.net.Uri);
+    property public final java.util.List<java.lang.Long> adSelectionIds;
+    property public final androidx.privacysandbox.ads.adservices.common.AdSelectionSignals adSelectionSignals;
+    property public final android.net.Uri selectionLogicUri;
+    property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller;
+  }
+
+  public abstract class AdSelectionManager {
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public abstract suspend Object? getAdSelectionData(androidx.privacysandbox.ads.adservices.adselection.GetAdSelectionDataRequest getAdSelectionDataRequest, kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.adselection.GetAdSelectionDataOutcome>);
+    method public static final androidx.privacysandbox.ads.adservices.adselection.AdSelectionManager? obtain(android.content.Context context);
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public abstract suspend Object? persistAdSelectionResult(androidx.privacysandbox.ads.adservices.adselection.PersistAdSelectionResultRequest persistAdSelectionResultRequest, kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.adselection.AdSelectionOutcome>);
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext8OptIn public abstract suspend Object? reportEvent(androidx.privacysandbox.ads.adservices.adselection.ReportEventRequest reportEventRequest, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? reportImpression(androidx.privacysandbox.ads.adservices.adselection.ReportImpressionRequest reportImpressionRequest, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? selectAds(androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig, kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.adselection.AdSelectionOutcome>);
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public abstract suspend Object? selectAds(androidx.privacysandbox.ads.adservices.adselection.AdSelectionFromOutcomesConfig adSelectionFromOutcomesConfig, kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.adselection.AdSelectionOutcome>);
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext8OptIn public abstract suspend Object? updateAdCounterHistogram(androidx.privacysandbox.ads.adservices.adselection.UpdateAdCounterHistogramRequest updateAdCounterHistogramRequest, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    field public static final androidx.privacysandbox.ads.adservices.adselection.AdSelectionManager.Companion Companion;
+  }
+
+  public static final class AdSelectionManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.adselection.AdSelectionManager? obtain(android.content.Context context);
+  }
+
+  public final class AdSelectionOutcome {
+    ctor public AdSelectionOutcome(long adSelectionId, android.net.Uri renderUri);
+    method public long getAdSelectionId();
+    method public android.net.Uri getRenderUri();
+    method @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public boolean hasOutcome();
+    property public final long adSelectionId;
+    property public final android.net.Uri renderUri;
+    field public static final androidx.privacysandbox.ads.adservices.adselection.AdSelectionOutcome.Companion Companion;
+    field @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public static final androidx.privacysandbox.ads.adservices.adselection.AdSelectionOutcome NO_OUTCOME;
+  }
+
+  @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public static final class AdSelectionOutcome.Companion {
+  }
+
+  @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public final class GetAdSelectionDataOutcome {
+    ctor public GetAdSelectionDataOutcome(long adSelectionId, optional byte[]? adSelectionData);
+    method public byte[]? getAdSelectionData();
+    method public long getAdSelectionId();
+    property public final byte[]? adSelectionData;
+    property public final long adSelectionId;
+  }
+
+  @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public final class GetAdSelectionDataRequest {
+    ctor public GetAdSelectionDataRequest(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller);
+    ctor public GetAdSelectionDataRequest(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller, optional android.net.Uri? coordinatorOriginUri);
+    method public android.net.Uri? getCoordinatorOriginUri();
+    method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getSeller();
+    property public final android.net.Uri? coordinatorOriginUri;
+    property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller;
+  }
+
+  @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public final class PersistAdSelectionResultRequest {
+    ctor public PersistAdSelectionResultRequest(long adSelectionId, optional androidx.privacysandbox.ads.adservices.common.AdTechIdentifier? seller, optional byte[]? adSelectionResult);
+    method public long getAdSelectionId();
+    method public byte[]? getAdSelectionResult();
+    method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier? getSeller();
+    property public final long adSelectionId;
+    property public final byte[]? adSelectionResult;
+    property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier? seller;
+  }
+
+  @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext8OptIn public final class ReportEventRequest {
+    ctor public ReportEventRequest(long adSelectionId, String eventKey, String eventData, int reportingDestinations, optional android.view.InputEvent? inputEvent);
+    method public long getAdSelectionId();
+    method public String getEventData();
+    method public String getEventKey();
+    method public android.view.InputEvent? getInputEvent();
+    method public int getReportingDestinations();
+    property public final long adSelectionId;
+    property public final String eventData;
+    property public final String eventKey;
+    property public final android.view.InputEvent? inputEvent;
+    property public final int reportingDestinations;
+    field public static final androidx.privacysandbox.ads.adservices.adselection.ReportEventRequest.Companion Companion;
+    field public static final int FLAG_REPORTING_DESTINATION_BUYER = 2; // 0x2
+    field public static final int FLAG_REPORTING_DESTINATION_SELLER = 1; // 0x1
+  }
+
+  public static final class ReportEventRequest.Companion {
+  }
+
+  public final class ReportImpressionRequest {
+    ctor @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext8OptIn public ReportImpressionRequest(long adSelectionId);
+    ctor public ReportImpressionRequest(long adSelectionId, androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig);
+    method public androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig getAdSelectionConfig();
+    method public long getAdSelectionId();
+    property public final androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig;
+    property public final long adSelectionId;
+  }
+
+  @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext8OptIn public final class UpdateAdCounterHistogramRequest {
+    ctor public UpdateAdCounterHistogramRequest(long adSelectionId, int adEventType, androidx.privacysandbox.ads.adservices.common.AdTechIdentifier callerAdTech);
+    method public int getAdEventType();
+    method public long getAdSelectionId();
+    method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getCallerAdTech();
+    property public final int adEventType;
+    property public final long adSelectionId;
+    property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier callerAdTech;
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.appsetid {
+
+  public final class AppSetId {
+    ctor public AppSetId(String id, int scope);
+    method public String getId();
+    method public int getScope();
+    property public final String id;
+    property public final int scope;
+    field public static final androidx.privacysandbox.ads.adservices.appsetid.AppSetId.Companion Companion;
+    field public static final int SCOPE_APP = 1; // 0x1
+    field public static final int SCOPE_DEVELOPER = 2; // 0x2
+  }
+
+  public static final class AppSetId.Companion {
+  }
+
+  public abstract class AppSetIdManager {
+    method public abstract suspend Object? getAppSetId(kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.appsetid.AppSetId>);
+    method public static final androidx.privacysandbox.ads.adservices.appsetid.AppSetIdManager? obtain(android.content.Context context);
+    field public static final androidx.privacysandbox.ads.adservices.appsetid.AppSetIdManager.Companion Companion;
+  }
+
+  public static final class AppSetIdManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.appsetid.AppSetIdManager? obtain(android.content.Context context);
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.common {
+
+  public final class AdData {
+    ctor public AdData(android.net.Uri renderUri, String metadata);
+    ctor @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext8OptIn public AdData(android.net.Uri renderUri, String metadata, optional java.util.Set<java.lang.Integer> adCounterKeys, optional androidx.privacysandbox.ads.adservices.common.AdFilters? adFilters);
+    ctor @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public AdData(android.net.Uri renderUri, String metadata, optional java.util.Set<java.lang.Integer> adCounterKeys, optional androidx.privacysandbox.ads.adservices.common.AdFilters? adFilters, optional String? adRenderId);
+    method public java.util.Set<java.lang.Integer> getAdCounterKeys();
+    method public androidx.privacysandbox.ads.adservices.common.AdFilters? getAdFilters();
+    method public String? getAdRenderId();
+    method public String getMetadata();
+    method public android.net.Uri getRenderUri();
+    property public final java.util.Set<java.lang.Integer> adCounterKeys;
+    property public final androidx.privacysandbox.ads.adservices.common.AdFilters? adFilters;
+    property public final String? adRenderId;
+    property public final String metadata;
+    property public final android.net.Uri renderUri;
+  }
+
+  @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext8OptIn public final class AdFilters {
+    ctor public AdFilters(androidx.privacysandbox.ads.adservices.common.FrequencyCapFilters? frequencyCapFilters);
+    method public androidx.privacysandbox.ads.adservices.common.FrequencyCapFilters? getFrequencyCapFilters();
+    property public final androidx.privacysandbox.ads.adservices.common.FrequencyCapFilters? frequencyCapFilters;
+  }
+
+  public final class AdSelectionSignals {
+    ctor public AdSelectionSignals(String signals);
+    method public String getSignals();
+    property public final String signals;
+  }
+
+  public final class AdTechIdentifier {
+    ctor public AdTechIdentifier(String identifier);
+    method public String getIdentifier();
+    property public final String identifier;
+  }
+
+  public sealed interface ExperimentalFeatures {
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn(message="The Ext10 API is experimental.", level=kotlin.RequiresOptIn.Level.WARNING) public static @interface ExperimentalFeatures.Ext10OptIn {
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn(message="The Ext11 API is experimental.", level=kotlin.RequiresOptIn.Level.WARNING) public static @interface ExperimentalFeatures.Ext11OptIn {
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn(message="The Ext12 API is experimental.", level=kotlin.RequiresOptIn.Level.WARNING) public static @interface ExperimentalFeatures.Ext12OptIn {
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn(message="The Ext8 API is experimental.", level=kotlin.RequiresOptIn.Level.WARNING) public static @interface ExperimentalFeatures.Ext8OptIn {
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn(message="This API is experimental.", level=kotlin.RequiresOptIn.Level.WARNING) public static @interface ExperimentalFeatures.RegisterSourceOptIn {
+  }
+
+  @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext8OptIn public final class FrequencyCapFilters {
+    ctor public FrequencyCapFilters();
+    ctor public FrequencyCapFilters(optional java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> keyedFrequencyCapsForWinEvents);
+    ctor public FrequencyCapFilters(optional java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> keyedFrequencyCapsForWinEvents, optional java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> keyedFrequencyCapsForImpressionEvents);
+    ctor public FrequencyCapFilters(optional java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> keyedFrequencyCapsForWinEvents, optional java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> keyedFrequencyCapsForImpressionEvents, optional java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> keyedFrequencyCapsForViewEvents);
+    ctor public FrequencyCapFilters(optional java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> keyedFrequencyCapsForWinEvents, optional java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> keyedFrequencyCapsForImpressionEvents, optional java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> keyedFrequencyCapsForViewEvents, optional java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> keyedFrequencyCapsForClickEvents);
+    method public java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> getKeyedFrequencyCapsForClickEvents();
+    method public java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> getKeyedFrequencyCapsForImpressionEvents();
+    method public java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> getKeyedFrequencyCapsForViewEvents();
+    method public java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> getKeyedFrequencyCapsForWinEvents();
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> keyedFrequencyCapsForClickEvents;
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> keyedFrequencyCapsForImpressionEvents;
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> keyedFrequencyCapsForViewEvents;
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.common.KeyedFrequencyCap> keyedFrequencyCapsForWinEvents;
+    field public static final int AD_EVENT_TYPE_CLICK = 3; // 0x3
+    field public static final int AD_EVENT_TYPE_IMPRESSION = 1; // 0x1
+    field public static final int AD_EVENT_TYPE_VIEW = 2; // 0x2
+    field public static final int AD_EVENT_TYPE_WIN = 0; // 0x0
+    field public static final androidx.privacysandbox.ads.adservices.common.FrequencyCapFilters.Companion Companion;
+  }
+
+  public static final class FrequencyCapFilters.Companion {
+  }
+
+  @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext8OptIn public final class KeyedFrequencyCap {
+    ctor public KeyedFrequencyCap(int adCounterKey, int maxCount, java.time.Duration interval);
+    method public int getAdCounterKey();
+    method public java.time.Duration getInterval();
+    method public int getMaxCount();
+    property public final int adCounterKey;
+    property public final java.time.Duration interval;
+    property public final int maxCount;
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.customaudience {
+
+  public final class CustomAudience {
+    ctor public CustomAudience(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer, String name, android.net.Uri dailyUpdateUri, android.net.Uri biddingLogicUri, java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads, optional java.time.Instant? activationTime, optional java.time.Instant? expirationTime, optional androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? userBiddingSignals, optional androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData? trustedBiddingSignals);
+    method public java.time.Instant? getActivationTime();
+    method public java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> getAds();
+    method public android.net.Uri getBiddingLogicUri();
+    method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getBuyer();
+    method public android.net.Uri getDailyUpdateUri();
+    method public java.time.Instant? getExpirationTime();
+    method public String getName();
+    method public androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData? getTrustedBiddingSignals();
+    method public androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? getUserBiddingSignals();
+    property public final java.time.Instant? activationTime;
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads;
+    property public final android.net.Uri biddingLogicUri;
+    property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer;
+    property public final android.net.Uri dailyUpdateUri;
+    property public final java.time.Instant? expirationTime;
+    property public final String name;
+    property public final androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData? trustedBiddingSignals;
+    property public final androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? userBiddingSignals;
+  }
+
+  public static final class CustomAudience.Builder {
+    ctor public CustomAudience.Builder(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer, String name, android.net.Uri dailyUpdateUri, android.net.Uri biddingLogicUri, java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience build();
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setActivationTime(java.time.Instant activationTime);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setAds(java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setBiddingLogicUri(android.net.Uri biddingLogicUri);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setBuyer(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setDailyUpdateUri(android.net.Uri dailyUpdateUri);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setExpirationTime(java.time.Instant expirationTime);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setName(String name);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setTrustedBiddingData(androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData trustedBiddingSignals);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setUserBiddingSignals(androidx.privacysandbox.ads.adservices.common.AdSelectionSignals userBiddingSignals);
+  }
+
+  public abstract class CustomAudienceManager {
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public abstract suspend Object? fetchAndJoinCustomAudience(androidx.privacysandbox.ads.adservices.customaudience.FetchAndJoinCustomAudienceRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? joinCustomAudience(androidx.privacysandbox.ads.adservices.customaudience.JoinCustomAudienceRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? leaveCustomAudience(androidx.privacysandbox.ads.adservices.customaudience.LeaveCustomAudienceRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public static final androidx.privacysandbox.ads.adservices.customaudience.CustomAudienceManager? obtain(android.content.Context context);
+    field public static final androidx.privacysandbox.ads.adservices.customaudience.CustomAudienceManager.Companion Companion;
+  }
+
+  public static final class CustomAudienceManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudienceManager? obtain(android.content.Context context);
+  }
+
+  @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public final class FetchAndJoinCustomAudienceRequest {
+    ctor public FetchAndJoinCustomAudienceRequest(android.net.Uri fetchUri, optional String? name, optional java.time.Instant? activationTime, optional java.time.Instant? expirationTime, optional androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? userBiddingSignals);
+    method public java.time.Instant? getActivationTime();
+    method public java.time.Instant? getExpirationTime();
+    method public android.net.Uri getFetchUri();
+    method public String? getName();
+    method public androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? getUserBiddingSignals();
+    property public final java.time.Instant? activationTime;
+    property public final java.time.Instant? expirationTime;
+    property public final android.net.Uri fetchUri;
+    property public final String? name;
+    property public final androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? userBiddingSignals;
+  }
+
+  public final class JoinCustomAudienceRequest {
+    ctor public JoinCustomAudienceRequest(androidx.privacysandbox.ads.adservices.customaudience.CustomAudience customAudience);
+    method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience getCustomAudience();
+    property public final androidx.privacysandbox.ads.adservices.customaudience.CustomAudience customAudience;
+  }
+
+  public final class LeaveCustomAudienceRequest {
+    ctor public LeaveCustomAudienceRequest(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer, String name);
+    method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getBuyer();
+    method public String getName();
+    property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer;
+    property public final String name;
+  }
+
+  public final class TrustedBiddingData {
+    ctor public TrustedBiddingData(android.net.Uri trustedBiddingUri, java.util.List<java.lang.String> trustedBiddingKeys);
+    method public java.util.List<java.lang.String> getTrustedBiddingKeys();
+    method public android.net.Uri getTrustedBiddingUri();
+    property public final java.util.List<java.lang.String> trustedBiddingKeys;
+    property public final android.net.Uri trustedBiddingUri;
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.measurement {
+
+  @RequiresApi(android.os.Build.VERSION_CODES.O) public final class DeletionRequest {
+    ctor public DeletionRequest(int deletionMode, int matchBehavior, optional java.time.Instant start, optional java.time.Instant end, optional java.util.List<? extends android.net.Uri> domainUris, optional java.util.List<? extends android.net.Uri> originUris);
+    method public int getDeletionMode();
+    method public java.util.List<android.net.Uri> getDomainUris();
+    method public java.time.Instant getEnd();
+    method public int getMatchBehavior();
+    method public java.util.List<android.net.Uri> getOriginUris();
+    method public java.time.Instant getStart();
+    property public final int deletionMode;
+    property public final java.util.List<android.net.Uri> domainUris;
+    property public final java.time.Instant end;
+    property public final int matchBehavior;
+    property public final java.util.List<android.net.Uri> originUris;
+    property public final java.time.Instant start;
+    field public static final androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Companion Companion;
+    field public static final int DELETION_MODE_ALL = 0; // 0x0
+    field public static final int DELETION_MODE_EXCLUDE_INTERNAL_DATA = 1; // 0x1
+    field public static final int MATCH_BEHAVIOR_DELETE = 0; // 0x0
+    field public static final int MATCH_BEHAVIOR_PRESERVE = 1; // 0x1
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.O) public static final class DeletionRequest.Builder {
+    ctor public DeletionRequest.Builder(int deletionMode, int matchBehavior);
+    method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest build();
+    method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setDomainUris(java.util.List<? extends android.net.Uri> domainUris);
+    method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setEnd(java.time.Instant end);
+    method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setOriginUris(java.util.List<? extends android.net.Uri> originUris);
+    method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setStart(java.time.Instant start);
+  }
+
+  public static final class DeletionRequest.Companion {
+  }
+
+  public abstract class MeasurementManager {
+    ctor public MeasurementManager();
+    method public abstract suspend Object? deleteRegistrations(androidx.privacysandbox.ads.adservices.measurement.DeletionRequest deletionRequest, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? getMeasurementApiStatus(kotlin.coroutines.Continuation<? super java.lang.Integer>);
+    method public static final androidx.privacysandbox.ads.adservices.measurement.MeasurementManager? obtain(android.content.Context context);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerSource(android.net.Uri attributionSource, android.view.InputEvent? inputEvent, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.RegisterSourceOptIn public abstract suspend Object? registerSource(androidx.privacysandbox.ads.adservices.measurement.SourceRegistrationRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerTrigger(android.net.Uri trigger, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerWebSource(androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerWebTrigger(androidx.privacysandbox.ads.adservices.measurement.WebTriggerRegistrationRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    field public static final androidx.privacysandbox.ads.adservices.measurement.MeasurementManager.Companion Companion;
+    field public static final int MEASUREMENT_API_STATE_DISABLED = 0; // 0x0
+    field public static final int MEASUREMENT_API_STATE_ENABLED = 1; // 0x1
+  }
+
+  public static final class MeasurementManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.measurement.MeasurementManager? obtain(android.content.Context context);
+  }
+
+  @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.RegisterSourceOptIn public final class SourceRegistrationRequest {
+    ctor public SourceRegistrationRequest(java.util.List<? extends android.net.Uri> registrationUris, optional android.view.InputEvent? inputEvent);
+    method public android.view.InputEvent? getInputEvent();
+    method public java.util.List<android.net.Uri> getRegistrationUris();
+    property public final android.view.InputEvent? inputEvent;
+    property public final java.util.List<android.net.Uri> registrationUris;
+  }
+
+  public static final class SourceRegistrationRequest.Builder {
+    ctor public SourceRegistrationRequest.Builder(java.util.List<? extends android.net.Uri> registrationUris);
+    method public androidx.privacysandbox.ads.adservices.measurement.SourceRegistrationRequest build();
+    method public androidx.privacysandbox.ads.adservices.measurement.SourceRegistrationRequest.Builder setInputEvent(android.view.InputEvent inputEvent);
+  }
+
+  public final class WebSourceParams {
+    ctor public WebSourceParams(android.net.Uri registrationUri, boolean debugKeyAllowed);
+    method public boolean getDebugKeyAllowed();
+    method public android.net.Uri getRegistrationUri();
+    property public final boolean debugKeyAllowed;
+    property public final android.net.Uri registrationUri;
+  }
+
+  public final class WebSourceRegistrationRequest {
+    ctor public WebSourceRegistrationRequest(java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> webSourceParams, android.net.Uri topOriginUri, optional android.view.InputEvent? inputEvent, optional android.net.Uri? appDestination, optional android.net.Uri? webDestination, optional android.net.Uri? verifiedDestination);
+    method public android.net.Uri? getAppDestination();
+    method public android.view.InputEvent? getInputEvent();
+    method public android.net.Uri getTopOriginUri();
+    method public android.net.Uri? getVerifiedDestination();
+    method public android.net.Uri? getWebDestination();
+    method public java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> getWebSourceParams();
+    property public final android.net.Uri? appDestination;
+    property public final android.view.InputEvent? inputEvent;
+    property public final android.net.Uri topOriginUri;
+    property public final android.net.Uri? verifiedDestination;
+    property public final android.net.Uri? webDestination;
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> webSourceParams;
+  }
+
+  public static final class WebSourceRegistrationRequest.Builder {
+    ctor public WebSourceRegistrationRequest.Builder(java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> webSourceParams, android.net.Uri topOriginUri);
+    method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest build();
+    method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setAppDestination(android.net.Uri? appDestination);
+    method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setInputEvent(android.view.InputEvent inputEvent);
+    method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setVerifiedDestination(android.net.Uri? verifiedDestination);
+    method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setWebDestination(android.net.Uri? webDestination);
+  }
+
+  public final class WebTriggerParams {
+    ctor public WebTriggerParams(android.net.Uri registrationUri, boolean debugKeyAllowed);
+    method public boolean getDebugKeyAllowed();
+    method public android.net.Uri getRegistrationUri();
+    property public final boolean debugKeyAllowed;
+    property public final android.net.Uri registrationUri;
+  }
+
+  public final class WebTriggerRegistrationRequest {
+    ctor public WebTriggerRegistrationRequest(java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebTriggerParams> webTriggerParams, android.net.Uri destination);
+    method public android.net.Uri getDestination();
+    method public java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebTriggerParams> getWebTriggerParams();
+    property public final android.net.Uri destination;
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebTriggerParams> webTriggerParams;
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.signals {
+
+  public abstract class ProtectedSignalsManager {
+    method @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext12OptIn public static final androidx.privacysandbox.ads.adservices.signals.ProtectedSignalsManager? obtain(android.content.Context context);
+    method @SuppressCompatibility @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_PROTECTED_SIGNALS) @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext12OptIn public abstract suspend Object? updateSignals(androidx.privacysandbox.ads.adservices.signals.UpdateSignalsRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    field public static final androidx.privacysandbox.ads.adservices.signals.ProtectedSignalsManager.Companion Companion;
+  }
+
+  public static final class ProtectedSignalsManager.Companion {
+    method @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext12OptIn public androidx.privacysandbox.ads.adservices.signals.ProtectedSignalsManager? obtain(android.content.Context context);
+  }
+
+  @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext12OptIn public final class UpdateSignalsRequest {
+    ctor public UpdateSignalsRequest(android.net.Uri updateUri);
+    method public android.net.Uri getUpdateUri();
+    property public final android.net.Uri updateUri;
+  }
+
+}
+
+package androidx.privacysandbox.ads.adservices.topics {
+
+  @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext11OptIn public final class EncryptedTopic {
+    ctor public EncryptedTopic(byte[] encryptedTopic, String keyIdentifier, byte[] encapsulatedKey);
+    method public byte[] getEncapsulatedKey();
+    method public byte[] getEncryptedTopic();
+    method public String getKeyIdentifier();
+    property public final byte[] encapsulatedKey;
+    property public final byte[] encryptedTopic;
+    property public final String keyIdentifier;
+  }
+
+  public final class GetTopicsRequest {
+    ctor public GetTopicsRequest(optional String adsSdkName, optional boolean shouldRecordObservation);
+    method public String getAdsSdkName();
+    method public boolean shouldRecordObservation();
+    property public final String adsSdkName;
+    property public final boolean shouldRecordObservation;
+  }
+
+  public static final class GetTopicsRequest.Builder {
+    ctor public GetTopicsRequest.Builder();
+    method public androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest build();
+    method public androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest.Builder setAdsSdkName(String adsSdkName);
+    method public androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest.Builder setShouldRecordObservation(boolean shouldRecordObservation);
+  }
+
+  public final class GetTopicsResponse {
+    ctor public GetTopicsResponse(java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> topics);
+    ctor @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext11OptIn public GetTopicsResponse(java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> topics, java.util.List<androidx.privacysandbox.ads.adservices.topics.EncryptedTopic> encryptedTopics);
+    method public java.util.List<androidx.privacysandbox.ads.adservices.topics.EncryptedTopic> getEncryptedTopics();
+    method public java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> getTopics();
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.topics.EncryptedTopic> encryptedTopics;
+    property public final java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> topics;
+  }
+
+  public final class Topic {
+    ctor public Topic(long taxonomyVersion, long modelVersion, int topicId);
+    method public long getModelVersion();
+    method public long getTaxonomyVersion();
+    method public int getTopicId();
+    property public final long modelVersion;
+    property public final long taxonomyVersion;
+    property public final int topicId;
+  }
+
+  public abstract class TopicsManager {
+    method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_TOPICS) public abstract suspend Object? getTopics(androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest request, kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.topics.GetTopicsResponse>);
+    method public static final androidx.privacysandbox.ads.adservices.topics.TopicsManager? obtain(android.content.Context context);
+    field public static final androidx.privacysandbox.ads.adservices.topics.TopicsManager.Companion Companion;
+  }
+
+  public static final class TopicsManager.Companion {
+    method public androidx.privacysandbox.ads.adservices.topics.TopicsManager? obtain(android.content.Context context);
+  }
+
+}
+
diff --git a/privacysandbox/ads/ads-adservices/api/restricted_current.txt b/privacysandbox/ads/ads-adservices/api/restricted_current.txt
index dca5235..020b263 100644
--- a/privacysandbox/ads/ads-adservices/api/restricted_current.txt
+++ b/privacysandbox/ads/ads-adservices/api/restricted_current.txt
@@ -92,6 +92,7 @@
   }
 
   @SuppressCompatibility @androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures.Ext10OptIn public final class GetAdSelectionDataRequest {
+    ctor public GetAdSelectionDataRequest(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller);
     ctor public GetAdSelectionDataRequest(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller, optional android.net.Uri? coordinatorOriginUri);
     method public android.net.Uri? getCoordinatorOriginUri();
     method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getSeller();
diff --git a/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/adselection/GetAdSelectionDataRequest.kt b/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/adselection/GetAdSelectionDataRequest.kt
index e84646b..97c95c6 100644
--- a/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/adselection/GetAdSelectionDataRequest.kt
+++ b/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/adselection/GetAdSelectionDataRequest.kt
@@ -42,6 +42,7 @@
 @OptIn(ExperimentalFeatures.Ext12OptIn::class)
 @ExperimentalFeatures.Ext10OptIn
 class GetAdSelectionDataRequest
+@JvmOverloads
 public constructor(
     val seller: AdTechIdentifier,
     @property:ExperimentalFeatures.Ext12OptIn val coordinatorOriginUri: Uri? = null
diff --git a/privacysandbox/ui/integration-tests/mediateesdkprovider/src/main/java/androidx/privacysandbox/ui/integration/mediateesdkprovider/MediateeSdkApi.kt b/privacysandbox/ui/integration-tests/mediateesdkprovider/src/main/java/androidx/privacysandbox/ui/integration/mediateesdkprovider/MediateeSdkApi.kt
index 392039f..96e38f2 100644
--- a/privacysandbox/ui/integration-tests/mediateesdkprovider/src/main/java/androidx/privacysandbox/ui/integration/mediateesdkprovider/MediateeSdkApi.kt
+++ b/privacysandbox/ui/integration-tests/mediateesdkprovider/src/main/java/androidx/privacysandbox/ui/integration/mediateesdkprovider/MediateeSdkApi.kt
@@ -18,31 +18,43 @@
 
 import android.content.Context
 import android.os.Bundle
+import androidx.privacysandbox.ui.core.SandboxedUiAdapter
 import androidx.privacysandbox.ui.integration.sdkproviderutils.SdkApiConstants.Companion.AdType
 import androidx.privacysandbox.ui.integration.sdkproviderutils.TestAdapters
+import androidx.privacysandbox.ui.integration.sdkproviderutils.ViewabilityHandler
 import androidx.privacysandbox.ui.integration.testaidl.IMediateeSdkApi
 import androidx.privacysandbox.ui.provider.toCoreLibInfo
 
 class MediateeSdkApi(private val sdkContext: Context) : IMediateeSdkApi.Stub() {
     private val testAdapters = TestAdapters(sdkContext)
 
-    override fun loadBannerAd(@AdType adType: Int, withSlowDraw: Boolean): Bundle {
-        return when (adType) {
-            AdType.WEBVIEW -> loadWebViewBannerAd()
-            AdType.WEBVIEW_FROM_LOCAL_ASSETS -> loadWebViewBannerAdFromLocalAssets()
-            else -> loadNonWebViewBannerAd("Mediation", withSlowDraw)
-        }
+    override fun loadBannerAd(
+        @AdType adType: Int,
+        withSlowDraw: Boolean,
+        drawViewability: Boolean
+    ): Bundle {
+        val adapter: SandboxedUiAdapter =
+            when (adType) {
+                AdType.WEBVIEW -> loadWebViewBannerAd()
+                AdType.WEBVIEW_FROM_LOCAL_ASSETS -> loadWebViewBannerAdFromLocalAssets()
+                else -> loadNonWebViewBannerAd("Mediation", withSlowDraw)
+            }
+        ViewabilityHandler.addObserverFactoryToAdapter(adapter, drawViewability)
+        return adapter.toCoreLibInfo(sdkContext)
     }
 
-    private fun loadWebViewBannerAd(): Bundle {
-        return testAdapters.WebViewBannerAd().toCoreLibInfo(sdkContext)
+    private fun loadWebViewBannerAd(): SandboxedUiAdapter {
+        return testAdapters.WebViewBannerAd()
     }
 
-    private fun loadWebViewBannerAdFromLocalAssets(): Bundle {
-        return testAdapters.WebViewAdFromLocalAssets().toCoreLibInfo(sdkContext)
+    private fun loadWebViewBannerAdFromLocalAssets(): SandboxedUiAdapter {
+        return testAdapters.WebViewAdFromLocalAssets()
     }
 
-    private fun loadNonWebViewBannerAd(text: String, waitInsideOnDraw: Boolean): Bundle {
-        return testAdapters.TestBannerAd(text, waitInsideOnDraw).toCoreLibInfo(sdkContext)
+    private fun loadNonWebViewBannerAd(
+        text: String,
+        waitInsideOnDraw: Boolean
+    ): SandboxedUiAdapter {
+        return testAdapters.TestBannerAd(text, waitInsideOnDraw)
     }
 }
diff --git a/privacysandbox/ui/integration-tests/sdkproviderutils/src/main/java/androidx/privacysandbox/ui/integration/sdkproviderutils/ViewabilityHandler.kt b/privacysandbox/ui/integration-tests/sdkproviderutils/src/main/java/androidx/privacysandbox/ui/integration/sdkproviderutils/ViewabilityHandler.kt
new file mode 100644
index 0000000..b03960d
--- /dev/null
+++ b/privacysandbox/ui/integration-tests/sdkproviderutils/src/main/java/androidx/privacysandbox/ui/integration/sdkproviderutils/ViewabilityHandler.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.privacysandbox.ui.integration.sdkproviderutils
+
+import android.graphics.Color
+import android.graphics.Rect
+import android.graphics.drawable.GradientDrawable
+import android.os.Bundle
+import android.util.Log
+import android.view.View
+import androidx.privacysandbox.ui.core.SandboxedSdkViewUiInfo
+import androidx.privacysandbox.ui.core.SandboxedUiAdapter
+import androidx.privacysandbox.ui.core.SessionObserver
+import androidx.privacysandbox.ui.core.SessionObserverContext
+import androidx.privacysandbox.ui.core.SessionObserverFactory
+
+class ViewabilityHandler {
+    companion object {
+
+        private const val TAG = "ViewabilityHandler"
+
+        fun addObserverFactoryToAdapter(adapter: SandboxedUiAdapter, drawViewability: Boolean) {
+            adapter.addObserverFactory(SessionObserverFactoryImpl(drawViewability))
+        }
+
+        private class SessionObserverFactoryImpl(val drawViewability: Boolean) :
+            SessionObserverFactory {
+
+            override fun create(): SessionObserver {
+                return SessionObserverImpl()
+            }
+
+            private inner class SessionObserverImpl : SessionObserver {
+                lateinit var view: View
+
+                override fun onSessionOpened(sessionObserverContext: SessionObserverContext) {
+                    Log.i(TAG, "onSessionOpened $sessionObserverContext")
+                    view = checkNotNull(sessionObserverContext.view)
+                }
+
+                override fun onUiContainerChanged(uiContainerInfo: Bundle) {
+                    val sandboxedSdkViewUiInfo = SandboxedSdkViewUiInfo.fromBundle(uiContainerInfo)
+                    if (drawViewability) {
+                        // draw a red rectangle over the received onScreenGeometry of the view
+                        drawRedRectangle(sandboxedSdkViewUiInfo.onScreenGeometry)
+                    }
+                    Log.i(TAG, "onUiContainerChanged $sandboxedSdkViewUiInfo")
+                }
+
+                override fun onSessionClosed() {
+                    Log.i(TAG, "session closed")
+                }
+
+                private fun drawRedRectangle(bounds: Rect) {
+                    view.overlay.clear()
+                    val viewabilityRect =
+                        GradientDrawable().apply {
+                            shape = GradientDrawable.RECTANGLE
+                            setStroke(10, Color.RED)
+                        }
+                    viewabilityRect.bounds = bounds
+                    view.overlay.add(viewabilityRect)
+                }
+            }
+        }
+    }
+}
diff --git a/privacysandbox/ui/integration-tests/testaidl/src/main/aidl/androidx/privacysandbox/ui/integration/testaidl/IAppOwnedMediateeSdkApi.aidl b/privacysandbox/ui/integration-tests/testaidl/src/main/aidl/androidx/privacysandbox/ui/integration/testaidl/IAppOwnedMediateeSdkApi.aidl
index 0ec900e5..4174096 100644
--- a/privacysandbox/ui/integration-tests/testaidl/src/main/aidl/androidx/privacysandbox/ui/integration/testaidl/IAppOwnedMediateeSdkApi.aidl
+++ b/privacysandbox/ui/integration-tests/testaidl/src/main/aidl/androidx/privacysandbox/ui/integration/testaidl/IAppOwnedMediateeSdkApi.aidl
@@ -19,5 +19,5 @@
 import android.os.Bundle;
 
 interface IAppOwnedMediateeSdkApi {
-    Bundle loadBannerAd(int adType, boolean withSlowDraw);
+    Bundle loadBannerAd(int adType, boolean withSlowDraw, boolean drawViewability);
 }
diff --git a/privacysandbox/ui/integration-tests/testaidl/src/main/aidl/androidx/privacysandbox/ui/integration/testaidl/IMediateeSdkApi.aidl b/privacysandbox/ui/integration-tests/testaidl/src/main/aidl/androidx/privacysandbox/ui/integration/testaidl/IMediateeSdkApi.aidl
index e91b821..68995c1 100644
--- a/privacysandbox/ui/integration-tests/testaidl/src/main/aidl/androidx/privacysandbox/ui/integration/testaidl/IMediateeSdkApi.aidl
+++ b/privacysandbox/ui/integration-tests/testaidl/src/main/aidl/androidx/privacysandbox/ui/integration/testaidl/IMediateeSdkApi.aidl
@@ -19,5 +19,5 @@
 import android.os.Bundle;
 
 interface IMediateeSdkApi {
-    Bundle loadBannerAd(int adType, boolean withSlowDraw);
+    Bundle loadBannerAd(int adType, boolean withSlowDraw, boolean drawViewability);
 }
diff --git a/privacysandbox/ui/integration-tests/testapp/src/main/java/androidx/privacysandbox/ui/integration/testapp/AppOwnedMediateeSdkApi.kt b/privacysandbox/ui/integration-tests/testapp/src/main/java/androidx/privacysandbox/ui/integration/testapp/AppOwnedMediateeSdkApi.kt
index f663049..0abd0aa 100644
--- a/privacysandbox/ui/integration-tests/testapp/src/main/java/androidx/privacysandbox/ui/integration/testapp/AppOwnedMediateeSdkApi.kt
+++ b/privacysandbox/ui/integration-tests/testapp/src/main/java/androidx/privacysandbox/ui/integration/testapp/AppOwnedMediateeSdkApi.kt
@@ -18,31 +18,43 @@
 
 import android.content.Context
 import android.os.Bundle
+import androidx.privacysandbox.ui.core.SandboxedUiAdapter
 import androidx.privacysandbox.ui.integration.sdkproviderutils.SdkApiConstants.Companion.AdType
 import androidx.privacysandbox.ui.integration.sdkproviderutils.TestAdapters
+import androidx.privacysandbox.ui.integration.sdkproviderutils.ViewabilityHandler
 import androidx.privacysandbox.ui.integration.testaidl.IAppOwnedMediateeSdkApi
 import androidx.privacysandbox.ui.provider.toCoreLibInfo
 
-class AppOwnedMediateeSdkApi(val sdkContext: Context) : IAppOwnedMediateeSdkApi.Stub() {
+class AppOwnedMediateeSdkApi(private val sdkContext: Context) : IAppOwnedMediateeSdkApi.Stub() {
     private val testAdapters = TestAdapters(sdkContext)
 
-    override fun loadBannerAd(@AdType adType: Int, waitInsideOnDraw: Boolean): Bundle {
-        return when (adType) {
-            AdType.WEBVIEW -> loadWebViewBannerAd()
-            AdType.WEBVIEW_FROM_LOCAL_ASSETS -> loadWebViewBannerAdFromLocalAssets()
-            else -> loadNonWebViewBannerAd("AppOwnedMediation", waitInsideOnDraw)
-        }
+    override fun loadBannerAd(
+        @AdType adType: Int,
+        waitInsideOnDraw: Boolean,
+        drawViewability: Boolean
+    ): Bundle {
+        val adapter: SandboxedUiAdapter =
+            when (adType) {
+                AdType.WEBVIEW -> loadWebViewBannerAd()
+                AdType.WEBVIEW_FROM_LOCAL_ASSETS -> loadWebViewBannerAdFromLocalAssets()
+                else -> loadNonWebViewBannerAd("AppOwnedMediation", waitInsideOnDraw)
+            }
+        ViewabilityHandler.addObserverFactoryToAdapter(adapter, drawViewability)
+        return adapter.toCoreLibInfo(sdkContext)
     }
 
-    private fun loadWebViewBannerAd(): Bundle {
-        return testAdapters.WebViewBannerAd().toCoreLibInfo(sdkContext)
+    private fun loadWebViewBannerAd(): SandboxedUiAdapter {
+        return testAdapters.WebViewBannerAd()
     }
 
-    private fun loadWebViewBannerAdFromLocalAssets(): Bundle {
-        return testAdapters.WebViewAdFromLocalAssets().toCoreLibInfo(sdkContext)
+    private fun loadWebViewBannerAdFromLocalAssets(): SandboxedUiAdapter {
+        return testAdapters.WebViewAdFromLocalAssets()
     }
 
-    private fun loadNonWebViewBannerAd(text: String, waitInsideOnDraw: Boolean): Bundle {
-        return testAdapters.TestBannerAd(text, waitInsideOnDraw).toCoreLibInfo(sdkContext)
+    private fun loadNonWebViewBannerAd(
+        text: String,
+        waitInsideOnDraw: Boolean
+    ): SandboxedUiAdapter {
+        return testAdapters.TestBannerAd(text, waitInsideOnDraw)
     }
 }
diff --git a/privacysandbox/ui/integration-tests/testapp/src/main/java/androidx/privacysandbox/ui/integration/testapp/BaseFragment.kt b/privacysandbox/ui/integration-tests/testapp/src/main/java/androidx/privacysandbox/ui/integration/testapp/BaseFragment.kt
index b9eaa1c..47a3592 100644
--- a/privacysandbox/ui/integration-tests/testapp/src/main/java/androidx/privacysandbox/ui/integration/testapp/BaseFragment.kt
+++ b/privacysandbox/ui/integration-tests/testapp/src/main/java/androidx/privacysandbox/ui/integration/testapp/BaseFragment.kt
@@ -104,8 +104,10 @@
         sandboxedSdkView.setAdapter(SandboxedUiAdapterFactory.createFromCoreLibInfo(sdkBundle))
     }
 
-    fun handleDrawerStateChange(isDrawerOpen: Boolean) {
-        getSandboxedSdkViews().forEach { it.orderProviderUiAboveClientUi(!isDrawerOpen) }
+    open fun handleDrawerStateChange(isDrawerOpen: Boolean) {
+        getSandboxedSdkViews().forEach {
+            it.orderProviderUiAboveClientUi(!isDrawerOpen && isZOrderOnTop)
+        }
     }
 
     private inner class StateChangeListener(val view: SandboxedSdkView) :
@@ -132,6 +134,7 @@
         private const val MEDIATEE_SDK_NAME =
             "androidx.privacysandbox.ui.integration.mediateesdkprovider"
         const val TAG = "TestSandboxClient"
+        var isZOrderOnTop = true
         @AdType var currentAdType = AdType.NON_WEBVIEW
         @MediationOption var currentMediationOption = MediationOption.NON_MEDIATED
         var shouldDrawViewabilityLayer = false
diff --git a/privacysandbox/ui/integration-tests/testapp/src/main/java/androidx/privacysandbox/ui/integration/testapp/MainActivity.kt b/privacysandbox/ui/integration-tests/testapp/src/main/java/androidx/privacysandbox/ui/integration/testapp/MainActivity.kt
index 766e5ec..24a5562 100644
--- a/privacysandbox/ui/integration-tests/testapp/src/main/java/androidx/privacysandbox/ui/integration/testapp/MainActivity.kt
+++ b/privacysandbox/ui/integration-tests/testapp/src/main/java/androidx/privacysandbox/ui/integration/testapp/MainActivity.kt
@@ -16,6 +16,7 @@
 
 package androidx.privacysandbox.ui.integration.testapp
 
+import android.os.Build
 import android.os.Bundle
 import android.os.ext.SdkExtensions
 import android.util.Log
@@ -48,6 +49,7 @@
     private lateinit var currentFragment: BaseFragment
     private lateinit var triggerSandboxDeathButton: Button
     private lateinit var webViewToggleButton: SwitchMaterial
+    private lateinit var zOrderToggleButton: SwitchMaterial
     private lateinit var contentFromAssetsToggleButton: SwitchMaterial
     private lateinit var viewabilityToggleButton: SwitchMaterial
     private lateinit var mediationDropDownMenu: Spinner
@@ -63,14 +65,20 @@
         drawerLayout = findViewById(R.id.drawer)
         navigationView = findViewById(R.id.navigation_view)
         contentFromAssetsToggleButton = findViewById(R.id.content_from_assets_switch)
+        zOrderToggleButton = findViewById(R.id.zorder_below_switch)
         webViewToggleButton = findViewById(R.id.load_webview)
         viewabilityToggleButton = findViewById(R.id.display_viewability_switch)
         triggerSandboxDeathButton = findViewById(R.id.trigger_sandbox_death)
         mediationDropDownMenu = findViewById(R.id.mediation_dropdown_menu)
 
-        triggerSandboxDeathButton.setOnClickListener {
-            triggerSandboxDeath()
-            disableAllControls()
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
+            // there is no sandbox to kill on T-
+            triggerSandboxDeathButton.visibility = View.GONE
+        } else {
+            triggerSandboxDeathButton.setOnClickListener {
+                triggerSandboxDeath()
+                disableAllControls()
+            }
         }
 
         sdkSandboxManager = SdkSandboxManagerCompat.from(applicationContext)
@@ -107,10 +115,7 @@
                 )
             }
         }
-        initializeWebViewToggleSwitch()
-        initializeContentFromAssetsToggleButton()
-        initializeViewabilityToggleButton()
-        initializeMediationDropDown()
+        initializeToggles()
     }
 
     override fun onDestroy() {
@@ -132,11 +137,20 @@
         currentFragment.getSdkApi().triggerProcessDeath()
     }
 
+    private fun initializeToggles() {
+        initializeWebViewToggleSwitch()
+        initializeContentFromAssetsToggleButton()
+        initializeViewabilityToggleButton()
+        initializeMediationDropDown()
+        initializeZOrderToggleButton()
+    }
+
     private fun disableAllControls() {
         webViewToggleButton.isEnabled = false
         contentFromAssetsToggleButton.isEnabled = false
         mediationDropDownMenu.isEnabled = false
         viewabilityToggleButton.isEnabled = false
+        zOrderToggleButton.isEnabled = false
     }
 
     private fun enableAllControls() {
@@ -144,6 +158,7 @@
         contentFromAssetsToggleButton.isEnabled = webViewToggleButton.isChecked
         mediationDropDownMenu.isEnabled = true
         viewabilityToggleButton.isEnabled = true
+        zOrderToggleButton.isEnabled = true
     }
 
     private fun initializeWebViewToggleSwitch() {
@@ -236,6 +251,12 @@
             }
     }
 
+    private fun initializeZOrderToggleButton() {
+        zOrderToggleButton.setOnCheckedChangeListener { _, isChecked ->
+            BaseFragment.isZOrderOnTop = !isChecked
+        }
+    }
+
     private fun initializeOptionsButton() {
         val button: Button = findViewById(R.id.toggle_drawer_button)
         button.setOnClickListener {
diff --git a/privacysandbox/ui/integration-tests/testapp/src/main/java/androidx/privacysandbox/ui/integration/testapp/PoolingContainerFragment.kt b/privacysandbox/ui/integration-tests/testapp/src/main/java/androidx/privacysandbox/ui/integration/testapp/PoolingContainerFragment.kt
index 3a08217..4a9ccf7 100644
--- a/privacysandbox/ui/integration-tests/testapp/src/main/java/androidx/privacysandbox/ui/integration/testapp/PoolingContainerFragment.kt
+++ b/privacysandbox/ui/integration-tests/testapp/src/main/java/androidx/privacysandbox/ui/integration/testapp/PoolingContainerFragment.kt
@@ -36,6 +36,11 @@
         return (recyclerView.adapter as CustomAdapter).sandboxedSdkViewSet.toList()
     }
 
+    override fun handleDrawerStateChange(isDrawerOpen: Boolean) {
+        super.handleDrawerStateChange(isDrawerOpen)
+        (recyclerView.adapter as CustomAdapter).zOrderOnTop = !isDrawerOpen && isZOrderOnTop
+    }
+
     override fun handleLoadAdFromDrawer(
         @AdType adType: Int,
         @MediationOption mediationOption: Int,
@@ -44,7 +49,7 @@
         currentAdType = adType
         currentMediationOption = mediationOption
         shouldDrawViewabilityLayer = drawViewabilityLayer
-        val recyclerViewAdapter = CustomAdapter(adType, mediationOption, zOrder = false)
+        val recyclerViewAdapter = CustomAdapter(adType, mediationOption, zOrderOnTop = false)
         recyclerView.adapter = recyclerViewAdapter
     }
 
@@ -68,12 +73,11 @@
     private inner class CustomAdapter(
         @AdType val adType: Int,
         @MediationOption val mediationOption: Int,
-        zOrder: Boolean = true
+        var zOrderOnTop: Boolean = true
     ) : RecyclerView.Adapter<CustomAdapter.ViewHolder>() {
 
         val sandboxedSdkViewSet = mutableSetOf<SandboxedSdkView>()
         private val childCount = 3
-        private var zOrderOnTop = zOrder
 
         inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
             val sandboxedSdkView: SandboxedSdkView = view.findViewById(R.id.recyclerview_ad_view)
diff --git a/privacysandbox/ui/integration-tests/testapp/src/main/res/layout/activity_main.xml b/privacysandbox/ui/integration-tests/testapp/src/main/res/layout/activity_main.xml
index 1dfd210..0779727 100644
--- a/privacysandbox/ui/integration-tests/testapp/src/main/res/layout/activity_main.xml
+++ b/privacysandbox/ui/integration-tests/testapp/src/main/res/layout/activity_main.xml
@@ -74,11 +74,19 @@
             android:layout_gravity="center"
             android:text="@string/display_viewability_switch"
             android:checked="false"/>
-        <Button
+        <com.google.android.material.switchmaterial.SwitchMaterial
+            android:id="@+id/zorder_below_switch"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_marginTop="200dp"
             android:layout_gravity="center"
+            android:text="@string/zorder_below_switch"
+            android:checked="false" />
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="250dp"
+            android:layout_gravity="center"
             android:id="@+id/trigger_sandbox_death"
             android:text="@string/trigger_sandbox_death_button"/>
     </com.google.android.material.navigation.NavigationView>
diff --git a/privacysandbox/ui/integration-tests/testapp/src/main/res/values/strings.xml b/privacysandbox/ui/integration-tests/testapp/src/main/res/values/strings.xml
index 7f38063..ff7300f 100644
--- a/privacysandbox/ui/integration-tests/testapp/src/main/res/values/strings.xml
+++ b/privacysandbox/ui/integration-tests/testapp/src/main/res/values/strings.xml
@@ -22,9 +22,10 @@
     <string name="long_text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean sit amet lacus dignissim, sollicitudin nisl sed, egestas leo. Sed congue vitae nulla vel mattis. Sed porttitor lobortis felis id sollicitudin. Maecenas a venenatis mi. Etiam sapien ipsum, bibendum at congue eget, venenatis laoreet erat. Integer dapibus varius lectus, eu gravida arcu pharetra in. Suspendisse volutpat sit amet ex non rutrum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed quis dui eros. Ut sed magna sit amet nulla iaculis ultrices. Pellentesque fermentum, nibh vel fermentum lacinia, urna nibh dictum risus, id feugiat sapien dolor nec erat. Maecenas augue nibh, sodales eu iaculis ut, volutpat non magna. Donec eget laoreet odio.Sed eget purus id mauris euismod lobortis. Vestibulum suscipit hendrerit rhoncus. Etiam et porttitor justo. Vivamus sodales velit in risus convallis tempor vitae non nunc. Integer lacinia consectetur ipsum, sit amet semper mi posuere eget. Etiam non quam nec sem malesuada viverra. Donec sollicitudin quam metus, at suscipit nisi mattis nec. Nam eu vehicula mauris. Cras nibh massa, interdum eget ante ut, molestie efficitur leo. In aliquet sodales mi vel bibendum. In iaculis neque in laoreet vestibulum. Nullam non interdum lectus. Etiam non ante elit. Vivamus luctus nisi ex, quis facilisis dui pellentesque porttitor. Etiam arcu nisl, porta eu hendrerit vel, porttitor vel turpis. Vestibulum in venenatis elit. Nunc in nisl congue, suscipit massa eu, luctus enim. Donec a fermentum magna, nec commodo purus. Quisque ac nisi et mi pretium porta ut eget nibh. Nulla consequat enim a congue porta. Donec odio magna, elementum in felis sit amet, posuere laoreet urna. Suspendisse ultricies in libero nec volutpat. Vivamus at magna lectus. Sed id metus et tellus suscipit aliquam in at lacus. Ut gravida ultrices augue, quis ultrices lacus ullamcorper ac. Ut fringilla ac quam sit amet pharetra. In non ante consectetur, dapibus ante eu, interdum risus. Nam lobortis blandit nisl ac dapibus. Maecenas vitae est ac odio sollicitudin varius eget quis orci. Mauris vitae ex eget neque tempor faucibus eget vel orci. Morbi eu feugiat lorem. Donec id sem et magna ullamcorper congue. Interdum et malesuada fames ac ante ipsum primis in faucibus. Sed laoreet ultrices quam, quis eleifend libero malesuada id. Sed ac sollicitudin diam. Integer sit amet ex ac purus malesuada iaculis at in mauris. Vestibulum egestas velit et sapien volutpat, vel varius augue fringilla. Duis efficitur blandit arcu in suscipit. Maecenas neque purus, finibus vel rhoncus at, pretium ut ipsum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean sit amet lacus dignissim, sollicitudin nisl sed, egestas leo. Sed congue vitae nulla vel mattis. Sed porttitor lobortis felis id sollicitudin. Maecenas a venenatis mi. Etiam sapien ipsum, bibendum at congue eget, venenatis laoreet erat. Integer dapibus varius lectus, eu gravida arcu pharetra in. Suspendisse volutpat sit amet ex non rutrum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed quis dui eros. Ut sed magna sit amet nulla iaculis ultrices. Pellentesque fermentum, nibh vel fermentum lacinia, urna nibh dictum risus, id feugiat sapien dolor nec erat. Maecenas augue nibh, sodales eu iaculis ut, volutpat non magna. Donec eget laoreet odio.Sed eget purus id mauris euismod lobortis. Vestibulum suscipit hendrerit rhoncus. Etiam et porttitor justo. Vivamus sodales velit in risus convallis tempor vitae non nunc. Integer lacinia consectetur ipsum, sit amet semper mi posuere eget. Etiam non quam nec sem malesuada viverra. Donec sollicitudin quam metus, at suscipit nisi mattis nec. Nam eu vehicula mauris. Cras nibh massa, interdum eget ante ut, molestie efficitur leo. In aliquet sodales mi vel bibendum. In iaculis neque in laoreet vestibulum. Nullam non interdum lectus. Etiam non ante elit. Vivamus luctus nisi ex, quis facilisis dui pellentesque porttitor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean sit amet lacus dignissim, sollicitudin nisl sed, egestas leo. Sed congue vitae nulla vel mattis. Sed porttitor lobortis felis id sollicitudin. Maecenas a venenatis mi. Etiam sapien ipsum, bibendum at congue eget, venenatis laoreet erat. Integer dapibus varius lectus, eu gravida arcu pharetra in. Suspendisse volutpat sit amet ex non rutrum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed quis dui eros. Ut sed magna sit amet nulla iaculis ultrices. Pellentesque fermentum, nibh vel fermentum lacinia, urna nibh dictum risus, id feugiat sapien dolor nec erat. Maecenas augue nibh, sodales eu iaculis ut, volutpat non magna. Donec eget laoreet odio.Sed eget purus id mauris euismod lobortis. Vestibulum suscipit hendrerit rhoncus. Etiam et porttitor justo. Vivamus sodales velit in risus convallis tempor vitae non nunc. Integer lacinia consectetur ipsum, sit amet semper mi posuere eget. Etiam non quam nec sem malesuada viverra. Donec sollicitudin quam metus, at suscipit nisi mattis nec. Nam eu vehicula mauris. Cras nibh massa, interdum eget ante ut, molestie efficitur leo. In aliquet sodales mi vel bibendum. In iaculis neque in laoreet vestibulum. Nullam non interdum lectus. Etiam non ante elit. Vivamus luctus nisi ex, quis facilisis dui pellentesque porttitor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean sit amet lacus dignissim, sollicitudin nisl sed, egestas leo. Sed congue vitae nulla vel mattis. Sed porttitor lobortis felis id sollicitudin. Maecenas a venenatis mi. Etiam sapien ipsum, bibendum at congue eget, venenatis laoreet erat. Integer dapibus varius lectus, eu gravida arcu pharetra in. Suspendisse volutpat sit amet ex non rutrum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed quis dui eros. Ut sed magna sit amet nulla iaculis ultrices. Pellentesque fermentum, nibh vel fermentum lacinia, urna nibh dictum risus, id feugiat sapien dolor nec erat. Maecenas augue nibh, sodales eu iaculis ut, volutpat non magna. Donec eget laoreet odio.Sed eget purus id mauris euismod lobortis. Vestibulum suscipit hendrerit rhoncus. Etiam et porttitor justo. Vivamus sodales velit in risus convallis tempor vitae non nunc. Integer lacinia consectetur ipsum, sit amet semper mi posuere eget. Etiam non quam nec sem malesuada viverra. Donec sollicitudin quam metus, at suscipit nisi mattis nec. Nam eu vehicula mauris. Cras nibh massa, interdum eget ante ut, molestie efficitur leo. In aliquet sodales mi vel bibendum. In iaculis neque in laoreet vestibulum. Nullam non interdum lectus. Etiam non ante elit. Vivamus luctus nisi ex, quis facilisis dui pellentesque porttitor.</string>
     <string name="resizeFromSdk">resize from sdk</string>
     <string name="content_from_assets_switch">Content from assets</string>
+    <string name="zorder_below_switch">Z Order Below</string>
     <string name="mediation_switch">Mediation</string>
     <string name="app_owned_mediatee_switch">AppOwnedMediatee</string>
     <string name="webview_switch">Webview</string>
     <string name="trigger_sandbox_death_button">Trigger Sandbox Death</string>
     <string name="display_viewability_switch">Display Viewability Geometry</string>
-</resources>
\ No newline at end of file
+</resources>
diff --git a/privacysandbox/ui/integration-tests/testsdkprovider/build.gradle b/privacysandbox/ui/integration-tests/testsdkprovider/build.gradle
index 040cefa..8519843 100644
--- a/privacysandbox/ui/integration-tests/testsdkprovider/build.gradle
+++ b/privacysandbox/ui/integration-tests/testsdkprovider/build.gradle
@@ -43,6 +43,5 @@
     implementation project(':privacysandbox:ui:ui-core')
     implementation project(':privacysandbox:ui:ui-provider')
     implementation project(':privacysandbox:sdkruntime:sdkruntime-client')
-    implementation project(':privacysandbox:ui:ui-client')
     implementation project(':webkit:webkit')
 }
diff --git a/privacysandbox/ui/integration-tests/testsdkprovider/src/main/java/androidx/privacysandbox/ui/integration/testsdkprovider/SdkApi.kt b/privacysandbox/ui/integration-tests/testsdkprovider/src/main/java/androidx/privacysandbox/ui/integration/testsdkprovider/SdkApi.kt
index 5eaac6d..ed223c4 100644
--- a/privacysandbox/ui/integration-tests/testsdkprovider/src/main/java/androidx/privacysandbox/ui/integration/testsdkprovider/SdkApi.kt
+++ b/privacysandbox/ui/integration-tests/testsdkprovider/src/main/java/androidx/privacysandbox/ui/integration/testsdkprovider/SdkApi.kt
@@ -17,24 +17,14 @@
 package androidx.privacysandbox.ui.integration.testsdkprovider
 
 import android.content.Context
-import android.graphics.Color
-import android.graphics.Rect
-import android.graphics.drawable.GradientDrawable
 import android.os.Bundle
 import android.os.Process
-import android.util.Log
-import android.view.View
 import androidx.privacysandbox.sdkruntime.core.controller.SdkSandboxControllerCompat
-import androidx.privacysandbox.ui.client.SandboxedUiAdapterFactory
-import androidx.privacysandbox.ui.client.view.SandboxedSdkView
-import androidx.privacysandbox.ui.core.SandboxedSdkViewUiInfo
 import androidx.privacysandbox.ui.core.SandboxedUiAdapter
-import androidx.privacysandbox.ui.core.SessionObserver
-import androidx.privacysandbox.ui.core.SessionObserverContext
-import androidx.privacysandbox.ui.core.SessionObserverFactory
 import androidx.privacysandbox.ui.integration.sdkproviderutils.SdkApiConstants.Companion.AdType
 import androidx.privacysandbox.ui.integration.sdkproviderutils.SdkApiConstants.Companion.MediationOption
 import androidx.privacysandbox.ui.integration.sdkproviderutils.TestAdapters
+import androidx.privacysandbox.ui.integration.sdkproviderutils.ViewabilityHandler
 import androidx.privacysandbox.ui.integration.testaidl.IAppOwnedMediateeSdkApi
 import androidx.privacysandbox.ui.integration.testaidl.IMediateeSdkApi
 import androidx.privacysandbox.ui.integration.testaidl.ISdkApi
@@ -42,7 +32,6 @@
 
 class SdkApi(private val sdkContext: Context) : ISdkApi.Stub() {
     private val testAdapters = TestAdapters(sdkContext)
-    private val measurementManager = MeasurementManager()
 
     override fun loadBannerAd(
         @AdType adType: Int,
@@ -54,26 +43,29 @@
             (mediationOption == MediationOption.SDK_RUNTIME_MEDIATEE ||
                 mediationOption == MediationOption.IN_APP_MEDIATEE)
         val isAppOwnedMediation = (mediationOption == MediationOption.IN_APP_MEDIATEE)
+        if (isMediation) {
+            return maybeGetMediateeBannerAdBundle(
+                isAppOwnedMediation,
+                adType,
+                waitInsideOnDraw,
+                drawViewability
+            )
+        }
         val adapter: SandboxedUiAdapter =
-            if (isMediation) {
-                loadMediatedTestAd(isAppOwnedMediation, adType, waitInsideOnDraw)
-            } else {
-                when (adType) {
-                    AdType.NON_WEBVIEW -> {
-                        loadNonWebViewBannerAd("Simple Ad", waitInsideOnDraw)
-                    }
-                    AdType.WEBVIEW -> {
-                        loadWebViewBannerAd()
-                    }
-                    AdType.WEBVIEW_FROM_LOCAL_ASSETS -> {
-                        loadWebViewBannerAdFromLocalAssets()
-                    }
-                    else -> {
-                        loadNonWebViewBannerAd("Ad type not present", waitInsideOnDraw)
-                    }
+            when (adType) {
+                AdType.NON_WEBVIEW -> {
+                    loadNonWebViewBannerAd("Simple Ad", waitInsideOnDraw)
                 }
-            }
-        measurementManager.startObserving(adapter, drawViewability)
+                AdType.WEBVIEW -> {
+                    loadWebViewBannerAd()
+                }
+                AdType.WEBVIEW_FROM_LOCAL_ASSETS -> {
+                    loadWebViewBannerAdFromLocalAssets()
+                }
+                else -> {
+                    loadNonWebViewBannerAd("Ad type not present", waitInsideOnDraw)
+                }
+            }.also { ViewabilityHandler.addObserverFactoryToAdapter(it, drawViewability) }
         return adapter.toCoreLibInfo(sdkContext)
     }
 
@@ -97,39 +89,14 @@
         return testAdapters.TestBannerAd(text, waitInsideOnDraw)
     }
 
-    private fun loadMediatedTestAd(
-        isAppMediatee: Boolean,
-        @AdType adType: Int,
-        waitInsideOnDraw: Boolean = false
-    ): SandboxedUiAdapter {
-        val mediateeBannerAdBundle =
-            getMediateeBannerAdBundle(isAppMediatee, adType, waitInsideOnDraw)
-        return MediatedBannerAd(mediateeBannerAdBundle)
-    }
-
     override fun requestResize(width: Int, height: Int) {}
 
-    private inner class MediatedBannerAd(private val mediateeBannerAdBundle: Bundle?) :
-        TestAdapters.BannerAd() {
-        override fun buildAdView(sessionContext: Context): View {
-            if (mediateeBannerAdBundle == null) {
-                return testAdapters
-                    .TestBannerAd("Mediated SDK is not loaded, this is a mediator Ad!", true)
-                    .buildAdView(sdkContext)
-            }
-
-            val view = SandboxedSdkView(sdkContext)
-            val adapter = SandboxedUiAdapterFactory.createFromCoreLibInfo(mediateeBannerAdBundle)
-            view.setAdapter(adapter)
-            return view
-        }
-    }
-
-    private fun getMediateeBannerAdBundle(
+    private fun maybeGetMediateeBannerAdBundle(
         isAppMediatee: Boolean,
         adType: Int,
-        withSlowDraw: Boolean
-    ): Bundle? {
+        withSlowDraw: Boolean,
+        drawViewability: Boolean
+    ): Bundle {
         val sdkSandboxControllerCompat = SdkSandboxControllerCompat.from(sdkContext)
         if (isAppMediatee) {
             val appOwnedSdkSandboxInterfaces =
@@ -140,7 +107,11 @@
                         IAppOwnedMediateeSdkApi.Stub.asInterface(
                             appOwnedSdkSandboxInterfaceCompat.getInterface()
                         )
-                    return appOwnedMediateeSdkApi.loadBannerAd(adType, withSlowDraw)
+                    return appOwnedMediateeSdkApi.loadBannerAd(
+                        adType,
+                        withSlowDraw,
+                        drawViewability
+                    )
                 }
             }
         } else {
@@ -149,58 +120,14 @@
                 if (sandboxedSdkCompat.getSdkInfo()?.name == MEDIATEE_SDK) {
                     val mediateeSdkApi =
                         IMediateeSdkApi.Stub.asInterface(sandboxedSdkCompat.getInterface())
-                    return mediateeSdkApi.loadBannerAd(adType, withSlowDraw)
+                    return mediateeSdkApi.loadBannerAd(adType, withSlowDraw, drawViewability)
                 }
             }
         }
-        return null
-    }
-
-    class MeasurementManager {
-        fun startObserving(adapter: SandboxedUiAdapter, drawViewability: Boolean) {
-            adapter.addObserverFactory(SessionObserverFactoryImpl(drawViewability))
-        }
-
-        private inner class SessionObserverFactoryImpl(val drawViewability: Boolean) :
-            SessionObserverFactory {
-
-            override fun create(): SessionObserver {
-                return SessionObserverImpl()
-            }
-
-            private inner class SessionObserverImpl : SessionObserver {
-                lateinit var view: View
-
-                override fun onSessionOpened(sessionObserverContext: SessionObserverContext) {
-                    Log.i(TAG, "onSessionOpened $sessionObserverContext")
-                    view = checkNotNull(sessionObserverContext.view)
-                }
-
-                override fun onUiContainerChanged(uiContainerInfo: Bundle) {
-                    val sandboxedSdkViewUiInfo = SandboxedSdkViewUiInfo.fromBundle(uiContainerInfo)
-                    if (drawViewability) {
-                        // draw a red rectangle over the received onScreenGeometry of the view
-                        drawRedRectangle(sandboxedSdkViewUiInfo.onScreenGeometry)
-                    }
-                    Log.i(TAG, "onUiContainerChanged $sandboxedSdkViewUiInfo")
-                }
-
-                override fun onSessionClosed() {
-                    Log.i(TAG, "session closed")
-                }
-
-                private fun drawRedRectangle(bounds: Rect) {
-                    view.overlay.clear()
-                    val viewabilityRect =
-                        GradientDrawable().apply {
-                            shape = GradientDrawable.RECTANGLE
-                            setStroke(10, Color.RED)
-                        }
-                    viewabilityRect.bounds = bounds
-                    view.overlay.add(viewabilityRect)
-                }
-            }
-        }
+        // Show a non-mediated ad if no mediatee can be found.
+        return testAdapters
+            .TestBannerAd("Mediated SDK is not loaded, this is a mediator Ad!", true)
+            .toCoreLibInfo(sdkContext)
     }
 
     companion object {
diff --git a/privacysandbox/ui/ui-client/src/main/java/androidx/privacysandbox/ui/client/view/SandboxedSdkView.kt b/privacysandbox/ui/ui-client/src/main/java/androidx/privacysandbox/ui/client/view/SandboxedSdkView.kt
index 2b481c0..ffdafcc 100644
--- a/privacysandbox/ui/ui-client/src/main/java/androidx/privacysandbox/ui/client/view/SandboxedSdkView.kt
+++ b/privacysandbox/ui/ui-client/src/main/java/androidx/privacysandbox/ui/client/view/SandboxedSdkView.kt
@@ -106,7 +106,6 @@
             override fun surfaceCreated(p0: SurfaceHolder) {
                 updateAndSetClippingBounds(true)
                 viewTreeObserver.addOnGlobalLayoutListener(globalLayoutChangeListener)
-                viewTreeObserver.addOnScrollChangedListener(scrollChangedListener)
             }
 
             override fun surfaceChanged(p0: SurfaceHolder, p1: Int, p2: Int, p3: Int) {}
@@ -236,11 +235,22 @@
         }
     }
 
+    /**
+     * Adds callbacks and listeners that are only valid while this view is attached to a window. All
+     * callbacks and listeners added here will be removed in [removeCallbacksOnWindowDetachment].
+     */
+    private fun addCallbacksOnWindowAttachment() {
+        viewTreeObserver.addOnScrollChangedListener(scrollChangedListener)
+    }
+
+    private fun removeCallbacksOnWindowDetachment() {
+        viewTreeObserver.removeOnScrollChangedListener(scrollChangedListener)
+    }
+
     private fun removeCallbacks() {
-        // TODO(b/3131677): Handle leak of listeners when this is called.
+        // TODO(b/339377737): Handle leak of listeners when this is called.
         (contentView as? SurfaceView)?.holder?.removeCallback(surfaceChangedCallback)
         viewTreeObserver.removeOnGlobalLayoutListener(globalLayoutChangeListener)
-        viewTreeObserver.removeOnScrollChangedListener(scrollChangedListener)
     }
 
     internal fun setContentView(contentView: View) {
@@ -395,6 +405,7 @@
 
     override fun onAttachedToWindow() {
         super.onAttachedToWindow()
+        addCallbacksOnWindowAttachment()
         if (client == null || viewContainingPoolingContainerListener == null) {
             if (this.isWithinPoolingContainer) {
                 attachPoolingContainerListener()
@@ -407,6 +418,7 @@
         if (!this.isWithinPoolingContainer) {
             closeClient()
         }
+        removeCallbacksOnWindowDetachment()
         super.onDetachedFromWindow()
     }
 
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/SyncTriggersConcurrencyTest.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/SyncTriggersConcurrencyTest.kt
index 337a025..952c29b 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/SyncTriggersConcurrencyTest.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/SyncTriggersConcurrencyTest.kt
@@ -21,7 +21,6 @@
 import androidx.room.Database
 import androidx.room.Delete
 import androidx.room.Entity
-import androidx.room.Ignore
 import androidx.room.Insert
 import androidx.room.InvalidationTracker
 import androidx.room.OnConflictStrategy
@@ -38,6 +37,7 @@
 import java.util.concurrent.TimeUnit
 import java.util.concurrent.atomic.AtomicBoolean
 import java.util.concurrent.atomic.AtomicInteger
+import kotlin.test.Ignore
 import kotlin.test.assertTrue
 import org.junit.After
 import org.junit.Before
diff --git a/room/integration-tests/multiplatformtestapp/src/androidInstrumentedTest/kotlin/androidx/room/integration/multiplatformtestapp/test/QueryTest.kt b/room/integration-tests/multiplatformtestapp/src/androidInstrumentedTest/kotlin/androidx/room/integration/multiplatformtestapp/test/QueryTest.kt
index c9ca150..9c8eca8 100644
--- a/room/integration-tests/multiplatformtestapp/src/androidInstrumentedTest/kotlin/androidx/room/integration/multiplatformtestapp/test/QueryTest.kt
+++ b/room/integration-tests/multiplatformtestapp/src/androidInstrumentedTest/kotlin/androidx/room/integration/multiplatformtestapp/test/QueryTest.kt
@@ -17,18 +17,30 @@
 package androidx.room.integration.multiplatformtestapp.test
 
 import androidx.room.Room
+import androidx.sqlite.SQLiteDriver
+import androidx.sqlite.driver.AndroidSQLiteDriver
 import androidx.sqlite.driver.bundled.BundledSQLiteDriver
 import androidx.test.platform.app.InstrumentationRegistry
 import kotlinx.coroutines.Dispatchers
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+import org.junit.runners.Parameterized.Parameters
 
-class QueryTest : BaseQueryTest() {
+@RunWith(Parameterized::class)
+class QueryTest(private val driver: SQLiteDriver) : BaseQueryTest() {
 
     private val instrumentation = InstrumentationRegistry.getInstrumentation()
 
     override fun getRoomDatabase(): SampleDatabase {
         return Room.inMemoryDatabaseBuilder<SampleDatabase>(context = instrumentation.targetContext)
-            .setDriver(BundledSQLiteDriver())
+            .setDriver(driver)
             .setQueryCoroutineContext(Dispatchers.IO)
             .build()
     }
+
+    companion object {
+        @JvmStatic
+        @Parameters(name = "driver={0}")
+        fun drivers() = arrayOf(BundledSQLiteDriver(), AndroidSQLiteDriver())
+    }
 }
diff --git a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/CompilationResultSubject.kt b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/CompilationResultSubject.kt
index cfaae4b..8a862b0 100644
--- a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/CompilationResultSubject.kt
+++ b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/CompilationResultSubject.kt
@@ -24,6 +24,7 @@
 import com.google.common.truth.Fact.fact
 import com.google.common.truth.Fact.simpleFact
 import com.google.common.truth.FailureMetadata
+import com.google.common.truth.PrimitiveByteArraySubject
 import com.google.common.truth.StringSubject
 import com.google.common.truth.Subject
 import com.google.common.truth.Subject.Factory
@@ -50,6 +51,8 @@
 
     internal abstract val generatedSources: List<Source>
 
+    internal abstract val generatedResources: List<Resource>
+
     val diagnostics = diagnostics.mapValues { it.value.filterNot { it.isIgnored() } }
 
     fun diagnosticsOfKind(kind: Diagnostic.Kind) = diagnostics[kind].orEmpty()
@@ -65,7 +68,7 @@
     override fun toString(): String {
         return buildString {
             appendLine("CompilationResult (with $testRunnerName)")
-            Diagnostic.Kind.values().forEach { kind ->
+            Diagnostic.Kind.entries.forEach { kind ->
                 val messages = diagnosticsOfKind(kind)
                 appendLine("${kind.name}: ${messages.size}")
                 messages.forEach { appendLine(it) }
@@ -302,7 +305,7 @@
     }
 
     /**
-     * Asserts that a file with the given [relativePath] was generated.
+     * Asserts that a source file with the given [relativePath] was generated.
      *
      * @see generatedSource
      */
@@ -345,6 +348,16 @@
         }
     }
 
+    /** Asserts that a resource file with the given [relativePath] was generated. */
+    fun generatedResourceFileWithPath(relativePath: String): PrimitiveByteArraySubject {
+        val match =
+            compilationResult.generatedResources.firstOrNull { it.relativePath == relativePath }
+        if (match == null) {
+            failWithActual(simpleFact("Didn't generate file with path: $relativePath"))
+        }
+        return Truth.assertThat(match!!.openInputStream().readAllBytes())
+    }
+
     /**
      * Called after handler is invoked to check its compilation failure assertion against the
      * compilation result.
@@ -461,10 +474,11 @@
 @ExperimentalProcessingApi
 internal class JavaCompileTestingCompilationResult(
     testRunner: CompilationTestRunner,
-    @Suppress("unused") private val delegate: Compilation,
+    private val delegate: Compilation,
     processor: SyntheticJavacProcessor,
     diagnostics: Map<Diagnostic.Kind, List<DiagnosticMessage>>,
-    override val generatedSources: List<Source>
+    override val generatedSources: List<Source>,
+    override val generatedResources: List<Resource>
 ) :
     CompilationResult(
         testRunnerName = testRunner.name,
@@ -480,8 +494,7 @@
 }
 
 @ExperimentalProcessingApi
-internal class KotlinCompilationResult
-constructor(
+internal class KotlinCompilationResult(
     testRunner: CompilationTestRunner,
     processor: SyntheticProcessor,
     private val delegate: TestCompilationResult
@@ -495,6 +508,9 @@
     override val generatedSources: List<Source>
         get() = delegate.generatedSources
 
+    override val generatedResources: List<Resource>
+        get() = delegate.generatedResources
+
     override fun rawOutput(): String {
         return delegate.diagnostics
             .flatMap { it.value }
diff --git a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/Resource.kt b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/Resource.kt
new file mode 100644
index 0000000..7fdc4779
--- /dev/null
+++ b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/Resource.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.room.compiler.processing.util
+
+import java.io.File
+import java.io.InputStream
+import javax.tools.JavaFileObject
+
+/** Abstraction for a generated resource file. */
+sealed class Resource(
+    val relativePath: String,
+) {
+    abstract fun openInputStream(): InputStream
+}
+
+internal class JavaFileObjectResource(
+    relativePath: String,
+    private val fileObject: JavaFileObject
+) : Resource(relativePath) {
+    override fun openInputStream(): InputStream {
+        return fileObject.openInputStream()
+    }
+}
+
+internal class FileResource(relativePath: String, private val fileObject: File) :
+    Resource(relativePath) {
+    override fun openInputStream(): InputStream {
+        return fileObject.inputStream()
+    }
+}
diff --git a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/compiler/TestKotlinCompiler.kt b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/compiler/TestKotlinCompiler.kt
index 7519733..8913ac9 100644
--- a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/compiler/TestKotlinCompiler.kt
+++ b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/compiler/TestKotlinCompiler.kt
@@ -17,6 +17,7 @@
 package androidx.room.compiler.processing.util.compiler
 
 import androidx.room.compiler.processing.util.DiagnosticMessage
+import androidx.room.compiler.processing.util.Resource
 import androidx.room.compiler.processing.util.Source
 import androidx.room.compiler.processing.util.compiler.steps.CompilationStepArguments
 import androidx.room.compiler.processing.util.compiler.steps.CompilationStepResult
@@ -64,7 +65,9 @@
     /** Diagnostic messages that were reported during compilation. */
     val diagnostics: Map<Diagnostic.Kind, List<DiagnosticMessage>>,
     /** List of classpath folders that contain the produced .class files. */
-    val outputClasspath: List<File>
+    val outputClasspath: List<File>,
+    /** List of generated resource files by the compilation. */
+    val generatedResources: List<Resource>,
 )
 
 /** Ensures the list of sources has at least 1 kotlin file, if not, adds one. */
@@ -143,7 +146,8 @@
                 generatedSourceRoots = emptyList(),
                 diagnostics = emptyList(),
                 nextCompilerArguments = initialArgs,
-                outputClasspath = emptyList()
+                outputClasspath = emptyList(),
+                generatedResources = emptyList()
             )
         )
     val resultFromEachStep =
@@ -169,7 +173,8 @@
         success = resultFromEachStep.all { it.success },
         generatedSources = resultFromEachStep.flatMap { it.generatedSources },
         diagnostics = combinedDiagnostics,
-        outputClasspath = resultFromEachStep.flatMap { it.outputClasspath }
+        outputClasspath = resultFromEachStep.flatMap { it.outputClasspath },
+        generatedResources = resultFromEachStep.flatMap { it.generatedResources }
     )
 }
 
diff --git a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/compiler/steps/JavaSourceCompilationStep.kt b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/compiler/steps/JavaSourceCompilationStep.kt
index ce1d1c3..bf807f6 100644
--- a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/compiler/steps/JavaSourceCompilationStep.kt
+++ b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/compiler/steps/JavaSourceCompilationStep.kt
@@ -86,7 +86,8 @@
                     // steps so we skip unnecessary work
                     sourceSets = arguments.sourceSets
                 ),
-            outputClasspath = generatedClasses
+            outputClasspath = generatedClasses,
+            generatedResources = emptyList()
         )
     }
 
diff --git a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/compiler/steps/KaptCompilationStep.kt b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/compiler/steps/KaptCompilationStep.kt
index 609ca64a..ae6d781 100644
--- a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/compiler/steps/KaptCompilationStep.kt
+++ b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/compiler/steps/KaptCompilationStep.kt
@@ -16,6 +16,7 @@
 
 package androidx.room.compiler.processing.util.compiler.steps
 
+import androidx.room.compiler.processing.util.FileResource
 import androidx.room.compiler.processing.util.compiler.DiagnosticsMessageCollector
 import androidx.room.compiler.processing.util.compiler.KotlinCliRunner
 import androidx.room.compiler.processing.util.compiler.TestKapt3Registrar
@@ -108,15 +109,22 @@
                 diagnostics = result.diagnostics + kaptMessages.getDiagnostics(),
                 sourceSets = arguments.sourceSets + generatedSources
             )
-        val outputClasspath =
-            listOf(result.compiledClasspath) + workingDir.resolve(RESOURCES_OUT_FOLDER_NAME)
+        val outputResources = workingDir.resolve(RESOURCES_OUT_FOLDER_NAME)
+        val outputClasspath = listOf(result.compiledClasspath) + outputResources
+        val generatedResources =
+            outputResources
+                .walkTopDown()
+                .filter { it.isFile }
+                .map { FileResource(it.relativeTo(outputResources).path, it) }
+                .toList()
         return CompilationStepResult(
             success = result.exitCode == ExitCode.OK,
             generatedSourceRoots = generatedSources,
             diagnostics = diagnostics,
             nextCompilerArguments =
                 arguments.copy(sourceSets = arguments.sourceSets + generatedSources),
-            outputClasspath = outputClasspath
+            outputClasspath = outputClasspath,
+            generatedResources = generatedResources
         )
     }
 
diff --git a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/compiler/steps/KotlinCompilationStep.kt b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/compiler/steps/KotlinCompilationStep.kt
index 85525fc..1017983 100644
--- a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/compiler/steps/KotlinCompilationStep.kt
+++ b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/compiler/steps/KotlinCompilationStep.kt
@@ -18,6 +18,7 @@
 
 import androidx.room.compiler.processing.util.DiagnosticLocation
 import androidx.room.compiler.processing.util.DiagnosticMessage
+import androidx.room.compiler.processing.util.Resource
 import androidx.room.compiler.processing.util.Source
 import androidx.room.compiler.processing.util.compiler.SourceSet
 import java.io.File
@@ -89,7 +90,9 @@
      */
     val nextCompilerArguments: CompilationStepArguments,
     /** If the step compiled sources, this field includes the list of Files for each classpath. */
-    val outputClasspath: List<File>
+    val outputClasspath: List<File>,
+    /** List of resource files generated by this step */
+    val generatedResources: List<Resource>
 ) {
     val generatedSources: List<Source> by lazy { generatedSourceRoots.flatMap { it.sources } }
 
@@ -104,7 +107,8 @@
                 generatedSourceRoots = emptyList(),
                 diagnostics = emptyList(),
                 nextCompilerArguments = arguments,
-                outputClasspath = emptyList()
+                outputClasspath = emptyList(),
+                generatedResources = emptyList()
             )
     }
 }
diff --git a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/compiler/steps/KotlinSourceCompilationStep.kt b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/compiler/steps/KotlinSourceCompilationStep.kt
index 136c89f..779070e 100644
--- a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/compiler/steps/KotlinSourceCompilationStep.kt
+++ b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/compiler/steps/KotlinSourceCompilationStep.kt
@@ -55,11 +55,11 @@
                         listOf(workingDir.resolve(CLASS_OUT_FOLDER_NAME)) +
                             arguments.additionalClasspaths,
                     // NOTE: ideally, we should remove kotlin sources but we know that there are no
-                    // more
-                    // kotlin steps so we skip unnecessary work
+                    // more kotlin steps so we skip unnecessary work
                     sourceSets = arguments.sourceSets
                 ),
-            outputClasspath = listOf(result.compiledClasspath)
+            outputClasspath = listOf(result.compiledClasspath),
+            generatedResources = emptyList()
         )
     }
 
diff --git a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/compiler/steps/KspCompilationStep.kt b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/compiler/steps/KspCompilationStep.kt
index 5e7e92c..1f77c72 100644
--- a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/compiler/steps/KspCompilationStep.kt
+++ b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/compiler/steps/KspCompilationStep.kt
@@ -16,6 +16,7 @@
 
 package androidx.room.compiler.processing.util.compiler.steps
 
+import androidx.room.compiler.processing.util.FileResource
 import androidx.room.compiler.processing.util.compiler.DiagnosticsMessageCollector
 import androidx.room.compiler.processing.util.compiler.KotlinCliRunner
 import androidx.room.compiler.processing.util.compiler.TestKspRegistrar
@@ -78,13 +79,22 @@
                 diagnostics = result.diagnostics + kspMessages.getDiagnostics(),
                 sourceSets = arguments.sourceSets + generatedSources
             )
+        val outputResources = workingDir.resolve(RESOURCES_OUT_FOLDER_NAME)
+        val outputClasspath = listOf(result.compiledClasspath) + outputResources
+        val generatedResources =
+            outputResources
+                .walkTopDown()
+                .filter { it.isFile }
+                .map { FileResource(it.relativeTo(outputResources).path, it) }
+                .toList()
         return CompilationStepResult(
             success = result.exitCode == ExitCode.OK && !failureDueToWarnings,
             generatedSourceRoots = generatedSources,
             diagnostics = diagnostics,
             nextCompilerArguments =
                 arguments.copy(sourceSets = arguments.sourceSets + generatedSources),
-            outputClasspath = listOf(result.compiledClasspath)
+            outputClasspath = outputClasspath,
+            generatedResources = generatedResources
         )
     }
 
@@ -92,5 +102,6 @@
         private const val JAVA_OUT_DIR = "generatedJava"
         private const val KOTLIN_OUT_DIR = "generatedKotlin"
         private const val CLASS_OUT_FOLDER_NAME = "class-out"
+        private const val RESOURCES_OUT_FOLDER_NAME = "ksp-compiler/resourceOutputDir"
     }
 }
diff --git a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/JavacCompilationTestRunner.kt b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/JavacCompilationTestRunner.kt
index ef94495..268a1fd 100644
--- a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/JavacCompilationTestRunner.kt
+++ b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/JavacCompilationTestRunner.kt
@@ -21,12 +21,15 @@
 import androidx.room.compiler.processing.util.CompilationResult
 import androidx.room.compiler.processing.util.DiagnosticMessage
 import androidx.room.compiler.processing.util.JavaCompileTestingCompilationResult
+import androidx.room.compiler.processing.util.JavaFileObjectResource
+import androidx.room.compiler.processing.util.Resource
 import androidx.room.compiler.processing.util.Source
 import androidx.room.compiler.processing.util.toDiagnosticMessages
 import com.google.testing.compile.Compilation
 import com.google.testing.compile.Compiler
 import java.io.File
 import javax.annotation.processing.Processor
+import javax.tools.JavaFileObject
 
 @ExperimentalProcessingApi
 internal class JavacCompilationTestRunner(
@@ -43,21 +46,19 @@
         val syntheticJavacProcessor = SyntheticJavacProcessor(params.config, params.handlers)
         val processors = testProcessors + syntheticJavacProcessor
         val sources =
-            if (params.sources.isEmpty()) {
+            params.sources.ifEmpty {
                 // synthesize a source to trigger compilation
                 listOf(
                     Source.java(
                         qName = "xprocessing.generated.SyntheticSource",
                         code =
                             """
-                    package xprocessing.generated;
-                    public class SyntheticSource {}
-                    """
+                            package xprocessing.generated;
+                            public class SyntheticSource {}
+                            """
                                 .trimIndent()
                     )
                 )
-            } else {
-                params.sources
             }
 
         val optionsArg = params.options.entries.map { "-A${it.key}=${it.value}" }
@@ -76,12 +77,23 @@
         val compilation = compiler.compile(javaFileObjects.keys)
         val generatedSources =
             if (compilation.status() == Compilation.Status.SUCCESS) {
-                compilation.generatedSourceFiles().associate { it to Source.fromJavaFileObject(it) }
+                compilation.generatedSourceFiles().associateWith { Source.fromJavaFileObject(it) }
             } else {
                 compilation
                     .diagnostics()
                     .mapNotNull { it.source }
-                    .associate { it to Source.fromJavaFileObject(it) }
+                    .associateWith { Source.fromJavaFileObject(it) }
+            }
+        val generatedResources: List<Resource> =
+            if (compilation.status() == Compilation.Status.SUCCESS) {
+                compilation
+                    .generatedFiles()
+                    .filter { it.kind == JavaFileObject.Kind.OTHER }
+                    .map {
+                        JavaFileObjectResource(it.toUri().path.substringAfter("CLASS_OUTPUT/"), it)
+                    }
+            } else {
+                emptyList()
             }
 
         val diagnostics: List<DiagnosticMessage> =
@@ -92,7 +104,8 @@
             delegate = compilation,
             processor = syntheticJavacProcessor,
             diagnostics = diagnostics.groupBy { it.kind },
-            generatedSources = generatedSources.values.toList()
+            generatedSources = generatedSources.values.toList(),
+            generatedResources = generatedResources
         )
     }
 }
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/AnnotationMirrorExt.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/AnnotationMirrorExt.kt
index 4a4fffc..8ddf5a7 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/AnnotationMirrorExt.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/AnnotationMirrorExt.kt
@@ -25,40 +25,31 @@
 
 /** Returns true if the given [AnnotationMirror] represents a repeatable annotation. */
 internal fun AnnotationMirror.isRepeatable(): Boolean {
-    try {
-        val valueType =
-            ElementFilter.methodsIn(MoreTypes.asTypeElement(annotationType).enclosedElements)
-                .singleOrNull { it.simpleName.toString() == "value" }
-                ?.returnType
+    val valueType =
+        ElementFilter.methodsIn(MoreTypes.asTypeElement(annotationType).enclosedElements)
+            .singleOrNull { it.simpleName.toString() == "value" }
+            ?.returnType
 
-        // The contract of a repeatable annotation requires that the container annotation have a
-        // single "default" method that returns an array typed with the repeatable annotation type.
-        if (valueType == null || valueType.kind != TypeKind.ARRAY) {
-            return false
-        }
-        val componentType = MoreTypes.asArray(valueType).componentType
-        if (componentType.kind != TypeKind.DECLARED) {
-            return false
-        }
-        val componentElement = MoreTypes.asDeclared(componentType).asElement()
-
-        // Ideally we would read the value of the Repeatable annotation to get the container class
-        // type and check that it matches "this" type. However, there seems to be a KSP bug where
-        // the value of Repeatable is not present so the best we can do is check that all the nested
-        // members are annotated with repeatable.
-        // https://github.com/google/ksp/issues/358
-        return MoreElements.isAnnotationPresent(componentElement, Repeatable::class.java) ||
-            // The java and kotlin versions of Repeatable are not interchangeable.
-            // https://github.com/google/ksp/issues/459 asks whether the built in type
-            // mapper should convert them, but it may not be possible because there are
-            // differences to how they work (eg different parameters).
-            MoreElements.isAnnotationPresent(
-                componentElement,
-                kotlin.annotation.Repeatable::class.java
-            )
-    } catch (t: Throwable) {
-        // TODO(b/314160063): Turbine can throw when getting enclosed elements. Remove this once
-        // we have a better way to work around Turbine exception.
+    // The contract of a repeatable annotation requires that the container annotation have a
+    // single "default" method that returns an array typed with the repeatable annotation type.
+    if (valueType == null || valueType.kind != TypeKind.ARRAY) {
         return false
     }
+    val componentType = MoreTypes.asArray(valueType).componentType
+    if (componentType.kind != TypeKind.DECLARED) {
+        return false
+    }
+    val componentElement = MoreTypes.asDeclared(componentType).asElement()
+
+    // Ideally we would read the value of the Repeatable annotation to get the container class
+    // type and check that it matches "this" type. However, there seems to be a KSP bug where
+    // the value of Repeatable is not present so the best we can do is check that all the nested
+    // members are annotated with repeatable.
+    // https://github.com/google/ksp/issues/358
+    return MoreElements.isAnnotationPresent(componentElement, Repeatable::class.java) ||
+        // The java and kotlin versions of Repeatable are not interchangeable.
+        // https://github.com/google/ksp/issues/459 asks whether the built in type
+        // mapper should convert them, but it may not be possible because there are
+        // differences to how they work (eg different parameters).
+        MoreElements.isAnnotationPresent(componentElement, kotlin.annotation.Repeatable::class.java)
 }
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFiler.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFiler.kt
index ea62157..f3c059f 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFiler.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFiler.kt
@@ -33,7 +33,6 @@
 import javax.lang.model.element.Element
 import javax.tools.Diagnostic
 import kotlin.io.path.extension
-import kotlin.io.path.nameWithoutExtension
 
 internal class KspFiler(
     private val delegate: CodeGenerator,
@@ -107,8 +106,8 @@
             originatingElements.map { it.originatingElementForPoet() }.toOriginatingElements()
         return createNewFile(
             originatingElements = kspFilerOriginatingElements,
-            packageName = filePath.parent?.toString() ?: "",
-            fileName = filePath.nameWithoutExtension,
+            packageName = "",
+            fileName = filePath.toString().substringBeforeLast("."),
             extensionName = filePath.extension,
             aggregating = mode == XFiler.Mode.Aggregating
         )
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspProcessingEnv.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspProcessingEnv.kt
index 83f4a51..5b9002f 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspProcessingEnv.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspProcessingEnv.kt
@@ -277,10 +277,11 @@
                 allowPrimitives = false
             )
         }
-        return KspTypeArgumentType(
-            env = this,
-            typeArg = ksTypeArgument,
-        )
+        return if (ksTypeArgument.variance == Variance.STAR) {
+            KspStarTypeArgumentType(env = this, typeArg = ksTypeArgument)
+        } else {
+            KspTypeArgumentType(env = this, typeArg = ksTypeArgument)
+        }
     }
 
     /**
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspStarTypeArgumentType.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspStarTypeArgumentType.kt
new file mode 100644
index 0000000..7b538f6
--- /dev/null
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspStarTypeArgumentType.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.room.compiler.processing.ksp
+
+import com.google.devtools.ksp.symbol.KSAnnotation
+import com.google.devtools.ksp.symbol.KSType
+import com.google.devtools.ksp.symbol.KSTypeArgument
+import com.squareup.kotlinpoet.STAR
+import com.squareup.kotlinpoet.javapoet.JTypeName
+import com.squareup.kotlinpoet.javapoet.JWildcardTypeName
+import com.squareup.kotlinpoet.javapoet.KTypeName
+
+// Represent '?' in Java and '*' in Kotlin
+internal class KspStarTypeArgumentType(
+    env: KspProcessingEnv,
+    typeArg: KSTypeArgument,
+    //  In Java '?' can have annotations.
+    originalKSAnnotations: Sequence<KSAnnotation> = typeArg.annotations,
+    scope: KSTypeVarianceResolverScope? = null,
+    typeAlias: KSType? = null,
+) :
+    KspTypeArgumentType(
+        env,
+        typeArg,
+        originalKSAnnotations,
+        scope = scope,
+        typeAlias = typeAlias,
+        ksType =
+            if (env.delegate.kspVersion >= KotlinVersion(2, 0)) {
+                // `typeArg.type` is `null` in KSP2, here we use `Unit` as a placeholder.
+                env.resolver.builtIns.unitType
+            } else {
+                typeArg.requireType()
+            }
+    ) {
+    override fun resolveJTypeName(): JTypeName {
+        return JWildcardTypeName.subtypeOf(JTypeName.OBJECT)
+    }
+
+    override fun resolveKTypeName(): KTypeName {
+        return STAR
+    }
+
+    override fun copy(
+        env: KspProcessingEnv,
+        ksType: KSType,
+        originalKSAnnotations: Sequence<KSAnnotation>,
+        scope: KSTypeVarianceResolverScope?,
+        typeAlias: KSType?
+    ) =
+        KspStarTypeArgumentType(
+            env = env,
+            typeArg = DelegatingTypeArg(typeArg, type = ksType.createTypeReference()),
+            originalKSAnnotations,
+            scope = scope,
+            typeAlias = typeAlias
+        )
+}
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeArgumentType.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeArgumentType.kt
index bbff1d9..3b4cffab 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeArgumentType.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeArgumentType.kt
@@ -30,16 +30,17 @@
  * The typeName for type arguments requires the type parameter, hence we have a special type for
  * them when we produce them.
  */
-internal class KspTypeArgumentType(
+internal open class KspTypeArgumentType(
     env: KspProcessingEnv,
     val typeArg: KSTypeArgument,
     originalKSAnnotations: Sequence<KSAnnotation> = typeArg.annotations,
     scope: KSTypeVarianceResolverScope? = null,
     typeAlias: KSType? = null,
+    ksType: KSType = typeArg.requireType(),
 ) :
     KspType(
         env = env,
-        ksType = typeArg.requireType(),
+        ksType = ksType,
         originalKSAnnotations = originalKSAnnotations,
         scope = scope,
         typeAlias = typeAlias,
@@ -92,7 +93,7 @@
             typeAlias = typeAlias
         )
 
-    private class DelegatingTypeArg(
+    internal class DelegatingTypeArg(
         val original: KSTypeArgument,
         override val type: KSTypeReference
     ) : KSTypeArgument by original
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationTest.kt
index 7aa2b31..e8f2e14 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationTest.kt
@@ -1407,11 +1407,19 @@
                 // Check the annotations on the types and type arguments
                 mapOf(
                         "superClass" to superClass,
+                        "superClassArg" to superClass.typeArguments.single(),
                         "superInterface" to superInterface,
+                        "superInterfaceArg" to superInterface.typeArguments.single(),
                         "field" to field.type,
+                        "fieldArg" to field.type.typeArguments.single(),
                         "methodReturnType" to method.returnType,
+                        "methodReturnTypeArg" to method.returnType.typeArguments.single(),
                         "methodParameter" to method.parameters.single().type,
+                        "methodParameterArg" to
+                            method.parameters.single().type.typeArguments.single(),
                         "constructorParameter" to constructor.parameters.single().type,
+                        "constructorParameterArg" to
+                            constructor.parameters.single().type.typeArguments.single(),
                     )
                     .forEach { (desc, type) ->
                         if (!invocation.isKsp && source == javaSource && preCompiled) {
@@ -1420,16 +1428,10 @@
                             assertWithMessage("$desc type: $type")
                                 .that(type.getAllAnnotationTypeElements())
                                 .isEmpty()
-                            assertWithMessage("$desc type-argument: ${type.typeArguments[0]}")
-                                .that(type.getAllAnnotationTypeElements())
-                                .isEmpty()
                         } else {
                             assertWithMessage("$desc type: $type")
                                 .that(type.getAllAnnotationTypeElements())
                                 .containsExactly(a, b)
-                            assertWithMessage("$desc type-argument: ${type.typeArguments[0]}")
-                                .that(type.getAllAnnotationTypeElements())
-                                .containsExactly(a, b)
                         }
                     }
             }
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableElementTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableElementTest.kt
index cbc0702..7f2fba6 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableElementTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableElementTest.kt
@@ -20,7 +20,6 @@
 import androidx.kruth.assertWithMessage
 import androidx.room.compiler.codegen.XTypeName
 import androidx.room.compiler.codegen.asClassName
-import androidx.room.compiler.processing.ksp.KspProcessingEnv
 import androidx.room.compiler.processing.util.CONTINUATION_JCLASS_NAME
 import androidx.room.compiler.processing.util.Source
 import androidx.room.compiler.processing.util.UNIT_JCLASS_NAME
@@ -29,6 +28,7 @@
 import androidx.room.compiler.processing.util.getDeclaredMethodByJvmName
 import androidx.room.compiler.processing.util.getMethodByJvmName
 import androidx.room.compiler.processing.util.getParameter
+import androidx.room.compiler.processing.util.kspProcessingEnv
 import androidx.room.compiler.processing.util.runProcessorTest
 import androidx.room.compiler.processing.util.typeName
 import com.google.testing.junit.testparameterinjector.TestParameter
@@ -124,7 +124,15 @@
                 assertThat(method.isVarArgs()).isTrue()
                 assertThat(method.parameters.single().type.asTypeName())
                     .isEqualTo(
-                        XTypeName.getArrayName(String::class.asClassName().copy(nullable = true))
+                        XTypeName.getArrayName(
+                                if (it.isKsp && it.kspProcessingEnv.isKsp2) {
+                                    XTypeName.getProducerExtendsName(
+                                        String::class.asClassName().copy(nullable = true)
+                                    )
+                                } else {
+                                    String::class.asClassName().copy(nullable = true)
+                                }
+                            )
                             .copy(nullable = true)
                     )
             }
@@ -1553,15 +1561,7 @@
                             assertThat(parameterName).isEqualTo("param1")
                         } else {
                             if (it.isKsp) {
-                                if (hasDebugFlag && (it.processingEnv as KspProcessingEnv).isKsp2) {
-                                    if (isAbstract || isJavaNative) {
-                                        assertThat(parameterName).isEqualTo("p0")
-                                    } else {
-                                        assertThat(parameterName).isEqualTo("param1")
-                                    }
-                                } else {
-                                    assertThat(parameterName).isEqualTo("p0")
-                                }
+                                assertThat(parameterName).isEqualTo("p0")
                             } else { // Javac
                                 if (hasDebugFlag) {
                                     if (isAbstract || isJavaNative) {
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeTest.kt
index b6300f9..c3172f6 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeTest.kt
@@ -22,8 +22,11 @@
 import androidx.room.compiler.codegen.XTypeName
 import androidx.room.compiler.codegen.XTypeName.Companion.ANY_OBJECT
 import androidx.room.compiler.codegen.XTypeName.Companion.UNAVAILABLE_KTYPE_NAME
+import androidx.room.compiler.processing.compat.XConverters.toKS
+import androidx.room.compiler.processing.javac.JavacType
 import androidx.room.compiler.processing.ksp.ERROR_JTYPE_NAME
 import androidx.room.compiler.processing.ksp.ERROR_KTYPE_NAME
+import androidx.room.compiler.processing.ksp.KspTypeArgumentType
 import androidx.room.compiler.processing.util.Source
 import androidx.room.compiler.processing.util.XTestInvocation
 import androidx.room.compiler.processing.util.asJClassName
@@ -41,6 +44,7 @@
 import androidx.room.compiler.processing.util.runKspTest
 import androidx.room.compiler.processing.util.runProcessorTest
 import com.google.devtools.ksp.getClassDeclarationByName
+import com.google.devtools.ksp.symbol.Variance
 import com.google.testing.junit.testparameterinjector.TestParameter
 import com.google.testing.junit.testparameterinjector.TestParameterInjector
 import com.squareup.javapoet.ClassName
@@ -63,6 +67,9 @@
 
 @RunWith(TestParameterInjector::class)
 class XTypeTest {
+
+    private val UNKNOWN = JWildcardTypeName.subtypeOf(JTypeName.OBJECT)
+
     @Test
     fun typeArguments() {
         val parent =
@@ -198,6 +205,155 @@
     }
 
     @Test
+    fun starProjectionsKotlin() {
+        val source =
+            Source.kotlin(
+                "Parent.kt",
+                """
+            package foo.bar
+            interface TUpper
+            class FooOut<out T: TUpper>
+            class FooIn<in T>
+            class Foo<T: TUpper>
+            class Test {
+                fun f(): Foo<*> = TODO()
+                fun fIn(): FooIn<*> = TODO()
+                fun fOut(): FooOut<*> = TODO()
+            }
+            """
+                    .trimIndent()
+            )
+        fun checkKsp(invocation: XTestInvocation) {
+            invocation.processingEnv.requireTypeElement("foo.bar.Test").let { cls ->
+                cls.getMethodByJvmName("f").returnType.let { returnType ->
+                    returnType.typeArguments.single().let { typeArgType ->
+                        (typeArgType as KspTypeArgumentType).typeArg.let { ksTypeArg ->
+                            assertThat(ksTypeArg.variance).isEqualTo(Variance.STAR)
+                            // The type is resolved to the upper bound in KSP1 but is null in KSP2.
+                            if (invocation.kspProcessingEnv.isKsp2) {
+                                assertThat(ksTypeArg.type).isNull()
+                            } else {
+                                assertThat(ksTypeArg.type!!.resolve().toString())
+                                    .isEqualTo("TUpper")
+                            }
+                        }
+
+                        assertThat(typeArgType.asTypeName().java).isEqualTo(UNKNOWN)
+                        assertThat(typeArgType.asTypeName().kotlin).isEqualTo(STAR)
+                    }
+                }
+
+                cls.getMethodByJvmName("fOut").returnType.let { returnType ->
+                    returnType.typeArguments.single().let { typeArgType ->
+                        (typeArgType as KspTypeArgumentType).typeArg.let { ksTypeArg ->
+                            // The variance doesn't get replaced to OUT/COVARIANT.
+                            assertThat(ksTypeArg.variance).isEqualTo(Variance.STAR)
+                            if (invocation.kspProcessingEnv.isKsp2) {
+                                assertThat(ksTypeArg.type).isNull()
+                            } else {
+                                assertThat(ksTypeArg.type!!.resolve().toString())
+                                    .isEqualTo("TUpper")
+                            }
+                        }
+                        assertThat(typeArgType.asTypeName().java).isEqualTo(UNKNOWN)
+                        assertThat(typeArgType.asTypeName().kotlin).isEqualTo(STAR)
+                    }
+                }
+
+                cls.getMethodByJvmName("fIn").returnType.let { returnType ->
+                    returnType.typeArguments.single().let { typeArgType ->
+                        (typeArgType as KspTypeArgumentType).typeArg.let { ksTypeArg ->
+                            // The variance doesn't get replaced to IN/CONTRAVARIANT.
+                            assertThat(ksTypeArg.variance).isEqualTo(Variance.STAR)
+                            if (invocation.kspProcessingEnv.isKsp2) {
+                                assertThat(ksTypeArg.type).isNull()
+                            } else {
+                                // The type is still resolved to the upper bound instead of Nothing.
+                                assertThat(ksTypeArg.type!!.resolve().toString()).isEqualTo("Any?")
+                            }
+                        }
+                        assertThat(typeArgType.asTypeName().java).isEqualTo(UNKNOWN)
+                        assertThat(typeArgType.asTypeName().kotlin).isEqualTo(STAR)
+                    }
+                }
+            }
+        }
+        fun checkJavac(invocation: XTestInvocation) {
+            invocation.processingEnv.requireTypeElement("foo.bar.Test").let { cls ->
+                listOf("f", "fIn", "fOut").forEach { methodName ->
+                    cls.getMethodByJvmName(methodName)
+                        .returnType
+                        .typeArguments
+                        .map { it as JavacType }
+                        .single()
+                        .let {
+                            assertThat(it.toString()).isEqualTo("?")
+                            assertThat(it.asTypeName().java).isEqualTo(UNKNOWN)
+                        }
+                }
+            }
+        }
+        fun handler(invocation: XTestInvocation) {
+            if (invocation.isKsp) {
+                checkKsp(invocation)
+            } else {
+                checkJavac(invocation)
+            }
+        }
+        runProcessorTest(sources = listOf(source), handler = ::handler)
+        runProcessorTest(classpath = compileFiles(listOf(source)), handler = ::handler)
+    }
+
+    @Test
+    fun starProjectionsJava() {
+        val source =
+            Source.java(
+                "foo.bar.Parent",
+                """
+            package foo.bar;
+            import java.io.InputStream;
+            import java.util.Set;
+            import java.util.List;
+
+            interface TUpper {}
+            class Foo<T extends TUpper> {}
+            class Test {
+                Foo<?> f() {
+                    throw new RuntimeException();
+                }
+            }
+            """
+                    .trimIndent()
+            )
+        fun handler(invocation: XTestInvocation) {
+            invocation.processingEnv.requireTypeElement("foo.bar.Test").let { cls ->
+                cls.getMethodByJvmName("f").returnType.let { returnType ->
+                    returnType.typeArguments.single().let { typeArgType ->
+                        if (invocation.isKsp) {
+                            val kspVersion = invocation.processingEnv.toKS().kspVersion
+                            (typeArgType as KspTypeArgumentType).typeArg.type.let { typeRef ->
+                                if (kspVersion >= KotlinVersion(2, 0)) {
+                                    assertThat(typeRef).isNull()
+                                } else {
+                                    assertThat(typeRef!!.resolve().toString())
+                                        .isEqualTo("(TUpper..TUpper?)")
+                                }
+                            }
+                            assertThat(typeArgType.asTypeName().java).isEqualTo(UNKNOWN)
+                            assertThat(typeArgType.asTypeName().kotlin).isEqualTo(STAR)
+                        } else {
+                            assertThat(typeArgType.toString()).isEqualTo("?")
+                            assertThat(typeArgType.asTypeName().java).isEqualTo(UNKNOWN)
+                        }
+                    }
+                }
+            }
+        }
+        runProcessorTest(sources = listOf(source), handler = ::handler)
+        runProcessorTest(classpath = compileFiles(listOf(source)), handler = ::handler)
+    }
+
+    @Test
     fun errorType() {
         val missingTypeRef =
             Source.java(
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/ext/xpoet_ext.kt b/room/room-compiler/src/main/kotlin/androidx/room/ext/xpoet_ext.kt
index d508f8c..883cb38 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/ext/xpoet_ext.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/ext/xpoet_ext.kt
@@ -45,7 +45,7 @@
 }
 
 object SQLiteDriverTypeNames {
-    val SQLITE_KT = XClassName.get(SQLITE_PACKAGE, "SQLiteKt")
+    val SQLITE = XClassName.get(SQLITE_PACKAGE, "SQLite")
     val DRIVER = XClassName.get(SQLITE_PACKAGE, "SQLiteDriver")
     val CONNECTION = XClassName.get(SQLITE_PACKAGE, "SQLiteConnection")
     val STATEMENT = XClassName.get(SQLITE_PACKAGE, "SQLiteStatement")
@@ -270,7 +270,12 @@
 
 object RoomMemberNames {
     val DB_UTIL_QUERY = RoomTypeNames.DB_UTIL.packageMember("query")
+    val DB_UTIL_FOREIGN_KEY_CHECK = RoomTypeNames.DB_UTIL.packageMember("foreignKeyCheck")
     val DB_UTIL_DROP_FTS_SYNC_TRIGGERS = RoomTypeNames.DB_UTIL.packageMember("dropFtsSyncTriggers")
+    val DB_UTIL_PERFORM_SUSPENDING = RoomTypeNames.DB_UTIL.packageMember("performSuspending")
+    val DB_UTIL_PERFORM_BLOCKING = RoomTypeNames.DB_UTIL.packageMember("performBlocking")
+    val DB_UTIL_PERFORM_IN_TRANSACTION_SUSPENDING =
+        RoomTypeNames.DB_UTIL.packageMember("performInTransactionSuspending")
     val CURSOR_UTIL_GET_COLUMN_INDEX = RoomTypeNames.CURSOR_UTIL.packageMember("getColumnIndex")
     val CURSOR_UTIL_GET_COLUMN_INDEX_OR_THROW =
         RoomTypeNames.CURSOR_UTIL.packageMember("getColumnIndexOrThrow")
@@ -286,7 +291,7 @@
 }
 
 object SQLiteDriverMemberNames {
-    val CONNECTION_EXEC_SQL = SQLiteDriverTypeNames.SQLITE_KT.packageMember("execSQL")
+    val CONNECTION_EXEC_SQL = SQLiteDriverTypeNames.SQLITE.packageMember("execSQL")
 }
 
 val DEFERRED_TYPES =
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/prepared/binder/CoroutinePreparedQueryResultBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/prepared/binder/CoroutinePreparedQueryResultBinder.kt
index 8fcc822..33f8aa2 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/prepared/binder/CoroutinePreparedQueryResultBinder.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/prepared/binder/CoroutinePreparedQueryResultBinder.kt
@@ -18,13 +18,12 @@
 
 import androidx.room.compiler.codegen.XCodeBlock
 import androidx.room.compiler.codegen.XCodeBlock.Builder.Companion.addLocalVal
-import androidx.room.compiler.codegen.XMemberName.Companion.packageMember
 import androidx.room.compiler.codegen.XPropertySpec
 import androidx.room.compiler.codegen.XTypeName
 import androidx.room.compiler.codegen.box
 import androidx.room.ext.InvokeWithLambdaParameter
 import androidx.room.ext.LambdaSpec
-import androidx.room.ext.RoomTypeNames
+import androidx.room.ext.RoomMemberNames.DB_UTIL_PERFORM_SUSPENDING
 import androidx.room.ext.SQLiteDriverTypeNames
 import androidx.room.solver.CodeGenScope
 import androidx.room.solver.prepared.result.PreparedQueryResultAdapter
@@ -57,7 +56,7 @@
         val performBlock =
             InvokeWithLambdaParameter(
                 scope = scope,
-                functionName = RoomTypeNames.DB_UTIL.packageMember("performSuspending"),
+                functionName = DB_UTIL_PERFORM_SUSPENDING,
                 argFormat = listOf("%N", "%L", "%L"),
                 args = listOf(dbProperty, /* isReadOnly= */ false, /* inTransaction= */ true),
                 continuationParamName = continuationParamName,
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/prepared/binder/InstantPreparedQueryResultBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/prepared/binder/InstantPreparedQueryResultBinder.kt
index 9c0b45e..dfd91fe 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/prepared/binder/InstantPreparedQueryResultBinder.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/prepared/binder/InstantPreparedQueryResultBinder.kt
@@ -19,13 +19,12 @@
 import androidx.room.compiler.codegen.CodeLanguage
 import androidx.room.compiler.codegen.XCodeBlock
 import androidx.room.compiler.codegen.XCodeBlock.Builder.Companion.addLocalVal
-import androidx.room.compiler.codegen.XMemberName.Companion.packageMember
 import androidx.room.compiler.codegen.XPropertySpec
 import androidx.room.compiler.codegen.XTypeName
 import androidx.room.compiler.codegen.box
 import androidx.room.ext.InvokeWithLambdaParameter
 import androidx.room.ext.LambdaSpec
-import androidx.room.ext.RoomTypeNames
+import androidx.room.ext.RoomMemberNames.DB_UTIL_PERFORM_BLOCKING
 import androidx.room.ext.SQLiteDriverTypeNames
 import androidx.room.solver.CodeGenScope
 import androidx.room.solver.prepared.result.PreparedQueryResultAdapter
@@ -62,7 +61,7 @@
         val performBlock =
             InvokeWithLambdaParameter(
                 scope = scope,
-                functionName = RoomTypeNames.DB_UTIL.packageMember("performBlocking"),
+                functionName = DB_UTIL_PERFORM_BLOCKING,
                 argFormat = listOf("%N", "%L", "%L"),
                 args = listOf(dbProperty, /* isReadOnly= */ false, /* inTransaction= */ true),
                 lambdaSpec =
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/BaseObservableQueryResultBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/BaseObservableQueryResultBinder.kt
index 53b54cf..2fc9d6d 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/BaseObservableQueryResultBinder.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/BaseObservableQueryResultBinder.kt
@@ -21,11 +21,10 @@
 import androidx.room.compiler.codegen.XCodeBlock
 import androidx.room.compiler.codegen.XFunSpec
 import androidx.room.compiler.codegen.XFunSpec.Builder.Companion.addStatement
-import androidx.room.compiler.codegen.XMemberName.Companion.packageMember
 import androidx.room.compiler.codegen.XPropertySpec
 import androidx.room.compiler.codegen.XTypeSpec
 import androidx.room.ext.AndroidTypeNames.CURSOR
-import androidx.room.ext.RoomTypeNames
+import androidx.room.ext.RoomMemberNames.DB_UTIL_QUERY
 import androidx.room.solver.CodeGenScope
 
 /**
@@ -77,7 +76,7 @@
                     XCodeBlock.of(
                         language = language,
                         format = "%M(%N, %L, %L, %L)",
-                        RoomTypeNames.DB_UTIL.packageMember("query"),
+                        DB_UTIL_QUERY,
                         dbProperty,
                         roomSQLiteQueryVar,
                         if (shouldCopyCursor) "true" else "false",
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/CoroutineResultBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/CoroutineResultBinder.kt
index 5767d9c..2a82c10 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/CoroutineResultBinder.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/CoroutineResultBinder.kt
@@ -20,7 +20,6 @@
 import androidx.room.compiler.codegen.XCodeBlock
 import androidx.room.compiler.codegen.XCodeBlock.Builder.Companion.addLocalVal
 import androidx.room.compiler.codegen.XMemberName.Companion.companionMember
-import androidx.room.compiler.codegen.XMemberName.Companion.packageMember
 import androidx.room.compiler.codegen.XPropertySpec
 import androidx.room.compiler.codegen.XTypeName
 import androidx.room.compiler.codegen.box
@@ -30,7 +29,8 @@
 import androidx.room.ext.InvokeWithLambdaParameter
 import androidx.room.ext.LambdaSpec
 import androidx.room.ext.RoomCoroutinesTypeNames
-import androidx.room.ext.RoomTypeNames
+import androidx.room.ext.RoomMemberNames.DB_UTIL_PERFORM_SUSPENDING
+import androidx.room.ext.RoomMemberNames.DB_UTIL_QUERY
 import androidx.room.ext.SQLiteDriverTypeNames
 import androidx.room.solver.CodeGenScope
 
@@ -129,7 +129,7 @@
                 XCodeBlock.of(
                     language,
                     "%M(%N, %L, %L, %L)",
-                    RoomTypeNames.DB_UTIL.packageMember("query"),
+                    DB_UTIL_QUERY,
                     dbProperty,
                     roomSQLiteQueryVar,
                     if (shouldCopyCursor) "true" else "false",
@@ -167,7 +167,7 @@
         val performBlock =
             InvokeWithLambdaParameter(
                 scope = scope,
-                functionName = RoomTypeNames.DB_UTIL.packageMember("performSuspending"),
+                functionName = DB_UTIL_PERFORM_SUSPENDING,
                 argFormat = listOf("%N", "%L", "%L"),
                 args = listOf(dbProperty, /* isReadOnly= */ true, inTransaction),
                 continuationParamName = continuationParamName,
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/InstantQueryResultBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/InstantQueryResultBinder.kt
index f3cafda..5f1e385 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/InstantQueryResultBinder.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/InstantQueryResultBinder.kt
@@ -18,14 +18,14 @@
 import androidx.room.compiler.codegen.CodeLanguage
 import androidx.room.compiler.codegen.XCodeBlock
 import androidx.room.compiler.codegen.XCodeBlock.Builder.Companion.addLocalVal
-import androidx.room.compiler.codegen.XMemberName.Companion.packageMember
 import androidx.room.compiler.codegen.XPropertySpec
 import androidx.room.compiler.codegen.XTypeName
 import androidx.room.compiler.codegen.box
 import androidx.room.ext.AndroidTypeNames
 import androidx.room.ext.InvokeWithLambdaParameter
 import androidx.room.ext.LambdaSpec
-import androidx.room.ext.RoomTypeNames
+import androidx.room.ext.RoomMemberNames.DB_UTIL_PERFORM_BLOCKING
+import androidx.room.ext.RoomMemberNames.DB_UTIL_QUERY
 import androidx.room.ext.SQLiteDriverTypeNames
 import androidx.room.solver.CodeGenScope
 
@@ -57,7 +57,7 @@
                     XCodeBlock.of(
                         language,
                         "%M(%N, %L, %L, %L)",
-                        RoomTypeNames.DB_UTIL.packageMember("query"),
+                        DB_UTIL_QUERY,
                         dbProperty,
                         roomSQLiteQueryVar,
                         if (shouldCopyCursor) "true" else "false",
@@ -94,7 +94,7 @@
         val performBlock =
             InvokeWithLambdaParameter(
                 scope = scope,
-                functionName = RoomTypeNames.DB_UTIL.packageMember("performBlocking"),
+                functionName = DB_UTIL_PERFORM_BLOCKING,
                 argFormat = listOf("%N", "%L", "%L"),
                 args = listOf(dbProperty, /* isReadOnly= */ true, inTransaction),
                 lambdaSpec =
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt
index c462ef8..a16c91f 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt
@@ -21,14 +21,13 @@
 import androidx.room.compiler.codegen.XCodeBlock
 import androidx.room.compiler.codegen.XFunSpec
 import androidx.room.compiler.codegen.XFunSpec.Builder.Companion.addStatement
-import androidx.room.compiler.codegen.XMemberName.Companion.packageMember
 import androidx.room.compiler.codegen.XPropertySpec
 import androidx.room.compiler.codegen.XTypeSpec
 import androidx.room.compiler.processing.XNullability
 import androidx.room.compiler.processing.XType
 import androidx.room.ext.AndroidTypeNames.CURSOR
 import androidx.room.ext.CallableTypeSpecBuilder
-import androidx.room.ext.RoomTypeNames
+import androidx.room.ext.RoomMemberNames.DB_UTIL_QUERY
 import androidx.room.solver.CodeGenScope
 import androidx.room.solver.RxType
 
@@ -101,7 +100,7 @@
                 XCodeBlock.of(
                     language = language,
                     format = "%M(%N, %L, %L, %L)",
-                    RoomTypeNames.DB_UTIL.packageMember("query"),
+                    DB_UTIL_QUERY,
                     dbProperty,
                     roomSQLiteQueryVar,
                     if (shouldCopyCursor) "true" else "false",
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/CoroutineDeleteOrUpdateMethodBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/CoroutineDeleteOrUpdateMethodBinder.kt
index 7fa568f..f80277c 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/CoroutineDeleteOrUpdateMethodBinder.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/CoroutineDeleteOrUpdateMethodBinder.kt
@@ -17,14 +17,13 @@
 package androidx.room.solver.shortcut.binder
 
 import androidx.room.compiler.codegen.XCodeBlock
-import androidx.room.compiler.codegen.XMemberName.Companion.packageMember
 import androidx.room.compiler.codegen.XPropertySpec
 import androidx.room.compiler.codegen.XTypeSpec
 import androidx.room.compiler.codegen.box
 import androidx.room.compiler.processing.XType
 import androidx.room.ext.InvokeWithLambdaParameter
 import androidx.room.ext.LambdaSpec
-import androidx.room.ext.RoomTypeNames
+import androidx.room.ext.RoomMemberNames.DB_UTIL_PERFORM_SUSPENDING
 import androidx.room.ext.SQLiteDriverTypeNames
 import androidx.room.solver.CodeGenScope
 import androidx.room.solver.shortcut.result.DeleteOrUpdateMethodAdapter
@@ -50,7 +49,7 @@
         val performBlock =
             InvokeWithLambdaParameter(
                 scope = scope,
-                functionName = RoomTypeNames.DB_UTIL.packageMember("performSuspending"),
+                functionName = DB_UTIL_PERFORM_SUSPENDING,
                 argFormat = listOf("%N", "%L", "%L"),
                 args = listOf(dbProperty, /* isReadOnly= */ false, /* inTransaction= */ true),
                 continuationParamName = continuationParamName,
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/CoroutineInsertMethodBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/CoroutineInsertMethodBinder.kt
index b5de1e7..8a8a0f1 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/CoroutineInsertMethodBinder.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/CoroutineInsertMethodBinder.kt
@@ -17,13 +17,12 @@
 package androidx.room.solver.shortcut.binder
 
 import androidx.room.compiler.codegen.XCodeBlock
-import androidx.room.compiler.codegen.XMemberName.Companion.packageMember
 import androidx.room.compiler.codegen.XPropertySpec
 import androidx.room.compiler.codegen.box
 import androidx.room.compiler.processing.XType
 import androidx.room.ext.InvokeWithLambdaParameter
 import androidx.room.ext.LambdaSpec
-import androidx.room.ext.RoomTypeNames
+import androidx.room.ext.RoomMemberNames.DB_UTIL_PERFORM_SUSPENDING
 import androidx.room.ext.SQLiteDriverTypeNames
 import androidx.room.solver.CodeGenScope
 import androidx.room.solver.shortcut.result.InsertOrUpsertMethodAdapter
@@ -49,7 +48,7 @@
         val performBlock =
             InvokeWithLambdaParameter(
                 scope = scope,
-                functionName = RoomTypeNames.DB_UTIL.packageMember("performSuspending"),
+                functionName = DB_UTIL_PERFORM_SUSPENDING,
                 argFormat = listOf("%N", "%L", "%L"),
                 args = listOf(dbProperty, /* isReadOnly= */ false, /* inTransaction= */ true),
                 continuationParamName = continuationParamName,
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/CoroutineUpsertMethodBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/CoroutineUpsertMethodBinder.kt
index 6f758dc..436574c 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/CoroutineUpsertMethodBinder.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/CoroutineUpsertMethodBinder.kt
@@ -17,13 +17,12 @@
 package androidx.room.solver.shortcut.binder
 
 import androidx.room.compiler.codegen.XCodeBlock
-import androidx.room.compiler.codegen.XMemberName.Companion.packageMember
 import androidx.room.compiler.codegen.XPropertySpec
 import androidx.room.compiler.codegen.box
 import androidx.room.compiler.processing.XType
 import androidx.room.ext.InvokeWithLambdaParameter
 import androidx.room.ext.LambdaSpec
-import androidx.room.ext.RoomTypeNames
+import androidx.room.ext.RoomMemberNames.DB_UTIL_PERFORM_SUSPENDING
 import androidx.room.ext.SQLiteDriverTypeNames
 import androidx.room.solver.CodeGenScope
 import androidx.room.solver.shortcut.result.InsertOrUpsertMethodAdapter
@@ -49,7 +48,7 @@
         val performBlock =
             InvokeWithLambdaParameter(
                 scope = scope,
-                functionName = RoomTypeNames.DB_UTIL.packageMember("performSuspending"),
+                functionName = DB_UTIL_PERFORM_SUSPENDING,
                 argFormat = listOf("%N", "%L", "%L"),
                 args = listOf(dbProperty, /* isReadOnly= */ false, /* inTransaction= */ true),
                 continuationParamName = continuationParamName,
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/InstantDeleteOrUpdateMethodBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/InstantDeleteOrUpdateMethodBinder.kt
index 472c33a..2b11c20 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/InstantDeleteOrUpdateMethodBinder.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/InstantDeleteOrUpdateMethodBinder.kt
@@ -18,13 +18,12 @@
 
 import androidx.room.compiler.codegen.CodeLanguage
 import androidx.room.compiler.codegen.XCodeBlock
-import androidx.room.compiler.codegen.XMemberName.Companion.packageMember
 import androidx.room.compiler.codegen.XPropertySpec
 import androidx.room.compiler.codegen.XTypeSpec
 import androidx.room.compiler.codegen.box
 import androidx.room.ext.InvokeWithLambdaParameter
 import androidx.room.ext.LambdaSpec
-import androidx.room.ext.RoomTypeNames
+import androidx.room.ext.RoomMemberNames.DB_UTIL_PERFORM_BLOCKING
 import androidx.room.ext.SQLiteDriverTypeNames
 import androidx.room.ext.isNotVoid
 import androidx.room.solver.CodeGenScope
@@ -48,7 +47,7 @@
         val performBlock =
             InvokeWithLambdaParameter(
                 scope = scope,
-                functionName = RoomTypeNames.DB_UTIL.packageMember("performBlocking"),
+                functionName = DB_UTIL_PERFORM_BLOCKING,
                 argFormat = listOf("%N", "%L", "%L"),
                 args = listOf(dbProperty, /* isReadOnly= */ false, /* inTransaction= */ true),
                 lambdaSpec =
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/InstantInsertMethodBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/InstantInsertMethodBinder.kt
index f70e2fa..4dd9f21 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/InstantInsertMethodBinder.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/InstantInsertMethodBinder.kt
@@ -18,12 +18,11 @@
 
 import androidx.room.compiler.codegen.CodeLanguage
 import androidx.room.compiler.codegen.XCodeBlock
-import androidx.room.compiler.codegen.XMemberName.Companion.packageMember
 import androidx.room.compiler.codegen.XPropertySpec
 import androidx.room.compiler.codegen.box
 import androidx.room.ext.InvokeWithLambdaParameter
 import androidx.room.ext.LambdaSpec
-import androidx.room.ext.RoomTypeNames
+import androidx.room.ext.RoomMemberNames.DB_UTIL_PERFORM_BLOCKING
 import androidx.room.ext.SQLiteDriverTypeNames
 import androidx.room.ext.isNotVoid
 import androidx.room.solver.CodeGenScope
@@ -47,7 +46,7 @@
         val performBlock =
             InvokeWithLambdaParameter(
                 scope = scope,
-                functionName = RoomTypeNames.DB_UTIL.packageMember("performBlocking"),
+                functionName = DB_UTIL_PERFORM_BLOCKING,
                 argFormat = listOf("%N", "%L", "%L"),
                 args = listOf(dbProperty, /* isReadOnly= */ false, /* inTransaction= */ true),
                 lambdaSpec =
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/InstantUpsertMethodBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/InstantUpsertMethodBinder.kt
index f933586..d3c14f1 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/InstantUpsertMethodBinder.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/InstantUpsertMethodBinder.kt
@@ -18,12 +18,11 @@
 
 import androidx.room.compiler.codegen.CodeLanguage
 import androidx.room.compiler.codegen.XCodeBlock
-import androidx.room.compiler.codegen.XMemberName.Companion.packageMember
 import androidx.room.compiler.codegen.XPropertySpec
 import androidx.room.compiler.codegen.box
 import androidx.room.ext.InvokeWithLambdaParameter
 import androidx.room.ext.LambdaSpec
-import androidx.room.ext.RoomTypeNames
+import androidx.room.ext.RoomMemberNames.DB_UTIL_PERFORM_BLOCKING
 import androidx.room.ext.SQLiteDriverTypeNames
 import androidx.room.ext.isNotVoid
 import androidx.room.solver.CodeGenScope
@@ -47,7 +46,7 @@
         val performBlock =
             InvokeWithLambdaParameter(
                 scope = scope,
-                functionName = RoomTypeNames.DB_UTIL.packageMember("performBlocking"),
+                functionName = DB_UTIL_PERFORM_BLOCKING,
                 argFormat = listOf("%N", "%L", "%L"),
                 args = listOf(dbProperty, /* isReadOnly= */ false, /* inTransaction= */ true),
                 lambdaSpec =
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/transaction/binder/CoroutineTransactionMethodBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/transaction/binder/CoroutineTransactionMethodBinder.kt
index d016c37..f1ae556 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/transaction/binder/CoroutineTransactionMethodBinder.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/transaction/binder/CoroutineTransactionMethodBinder.kt
@@ -19,14 +19,13 @@
 import androidx.room.compiler.codegen.CodeLanguage
 import androidx.room.compiler.codegen.XClassName
 import androidx.room.compiler.codegen.XCodeBlock
-import androidx.room.compiler.codegen.XMemberName.Companion.packageMember
 import androidx.room.compiler.codegen.XPropertySpec
 import androidx.room.compiler.codegen.XTypeName
 import androidx.room.compiler.processing.XType
 import androidx.room.ext.InvokeWithLambdaParameter
 import androidx.room.ext.KotlinTypeNames
 import androidx.room.ext.LambdaSpec
-import androidx.room.ext.RoomTypeNames
+import androidx.room.ext.RoomMemberNames.DB_UTIL_PERFORM_IN_TRANSACTION_SUSPENDING
 import androidx.room.solver.CodeGenScope
 import androidx.room.solver.transaction.result.TransactionMethodAdapter
 
@@ -47,8 +46,7 @@
         val performBlock =
             InvokeWithLambdaParameter(
                 scope = scope,
-                functionName =
-                    RoomTypeNames.DB_UTIL.packageMember("performInTransactionSuspending"),
+                functionName = DB_UTIL_PERFORM_IN_TRANSACTION_SUSPENDING,
                 argFormat = listOf("%N"),
                 args = listOf(dbProperty),
                 continuationParamName = continuationParamName,
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/transaction/binder/InstantTransactionMethodBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/transaction/binder/InstantTransactionMethodBinder.kt
index 3f7a743..e2e6208 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/transaction/binder/InstantTransactionMethodBinder.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/transaction/binder/InstantTransactionMethodBinder.kt
@@ -19,7 +19,6 @@
 import androidx.room.compiler.codegen.CodeLanguage
 import androidx.room.compiler.codegen.XClassName
 import androidx.room.compiler.codegen.XCodeBlock
-import androidx.room.compiler.codegen.XMemberName.Companion.packageMember
 import androidx.room.compiler.codegen.XPropertySpec
 import androidx.room.compiler.codegen.box
 import androidx.room.compiler.processing.XType
@@ -28,7 +27,7 @@
 import androidx.room.ext.InvokeWithLambdaParameter
 import androidx.room.ext.KotlinTypeNames
 import androidx.room.ext.LambdaSpec
-import androidx.room.ext.RoomTypeNames
+import androidx.room.ext.RoomMemberNames.DB_UTIL_PERFORM_BLOCKING
 import androidx.room.ext.SQLiteDriverTypeNames
 import androidx.room.solver.CodeGenScope
 import androidx.room.solver.transaction.result.TransactionMethodAdapter
@@ -54,7 +53,7 @@
         val performBlock =
             InvokeWithLambdaParameter(
                 scope = scope,
-                functionName = RoomTypeNames.DB_UTIL.packageMember("performBlocking"),
+                functionName = DB_UTIL_PERFORM_BLOCKING,
                 argFormat = listOf("%N", "%L", "%L"),
                 args = listOf(dbProperty, /* isReadOnly= */ false, /* inTransaction= */ true),
                 lambdaSpec =
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/writer/AutoMigrationWriter.kt b/room/room-compiler/src/main/kotlin/androidx/room/writer/AutoMigrationWriter.kt
index 9269745..00d8468 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/writer/AutoMigrationWriter.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/writer/AutoMigrationWriter.kt
@@ -21,11 +21,11 @@
 import androidx.room.compiler.codegen.XCodeBlock
 import androidx.room.compiler.codegen.XFunSpec
 import androidx.room.compiler.codegen.XFunSpec.Builder.Companion.addStatement
-import androidx.room.compiler.codegen.XMemberName.Companion.packageMember
 import androidx.room.compiler.codegen.XTypeSpec
 import androidx.room.compiler.codegen.XTypeSpec.Builder.Companion.addOriginatingElement
 import androidx.room.compiler.codegen.XTypeSpec.Builder.Companion.addProperty
 import androidx.room.compiler.processing.XTypeElement
+import androidx.room.ext.RoomMemberNames.DB_UTIL_FOREIGN_KEY_CHECK
 import androidx.room.ext.RoomTypeNames
 import androidx.room.ext.SQLiteDriverMemberNames
 import androidx.room.ext.SQLiteDriverTypeNames.CONNECTION
@@ -372,11 +372,7 @@
         tableName: String,
         migrateBuilder: XFunSpec.Builder
     ) {
-        migrateBuilder.addStatement(
-            "%M(connection, %S)",
-            RoomTypeNames.DB_UTIL.packageMember("foreignKeyCheck"),
-            tableName
-        )
+        migrateBuilder.addStatement("%M(connection, %S)", DB_UTIL_FOREIGN_KEY_CHECK, tableName)
     }
 
     /**
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/processor/DatabaseProcessorTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/processor/DatabaseProcessorTest.kt
index caaae66..5885790 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/processor/DatabaseProcessorTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/processor/DatabaseProcessorTest.kt
@@ -19,6 +19,7 @@
 import COMMON
 import androidx.kruth.assertThat
 import androidx.room.DatabaseProcessingStep
+import androidx.room.RoomKspProcessor
 import androidx.room.RoomProcessor
 import androidx.room.compiler.codegen.CodeLanguage
 import androidx.room.compiler.processing.XType
@@ -42,6 +43,8 @@
 import androidx.room.vo.ReadQueryMethod
 import androidx.room.vo.Warning
 import com.google.auto.service.processor.AutoServiceProcessor
+import com.google.testing.junit.testparameterinjector.TestParameter
+import com.google.testing.junit.testparameterinjector.TestParameterInjector
 import java.io.File
 import java.io.FileOutputStream
 import java.net.URL
@@ -59,10 +62,9 @@
 import org.junit.Test
 import org.junit.rules.TemporaryFolder
 import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
 import org.mockito.Mockito.mock
 
-@RunWith(JUnit4::class)
+@RunWith(TestParameterInjector::class)
 class DatabaseProcessorTest {
     companion object {
         const val DATABASE_PREFIX =
@@ -1534,31 +1536,39 @@
     }
 
     @Test
-    fun exportSchemaToJarResources() {
+    fun exportSchemaToJarResources(@TestParameter withKotlinSrc: Boolean) {
         val dbSource =
-            Source.java(
-                "foo.bar.MyDb",
-                """
-            package foo.bar;
-            import androidx.room.*;
-            @Database(entities = {User.class}, version = 1, exportSchema = true)
-            public abstract class MyDb extends RoomDatabase {}
-            """
-                    .trimIndent()
-            )
-        val lib =
-            compileFiles(
-                sources = listOf(dbSource, USER),
-                annotationProcessors = listOf(RoomProcessor()),
-                options = mapOf("room.exportSchemaResource" to "true"),
-                includeSystemClasspath = false
-            )
-        assertThat(
-                lib.any { libDir ->
-                    libDir.walkTopDown().any { it.endsWith("schemas/foo.bar.MyDb/1.json") }
-                }
-            )
-            .isTrue()
+            if (withKotlinSrc) {
+                Source.kotlin(
+                    "foo/bar/MyDb.kt",
+                    """
+                    package foo.bar
+                    import androidx.room.*
+                    @Database(entities = [User::class], version = 1, exportSchema = true)
+                    abstract class MyDb : RoomDatabase()
+                    """
+                        .trimIndent()
+                )
+            } else {
+                Source.java(
+                    "foo.bar.MyDb",
+                    """
+                    package foo.bar;
+                    import androidx.room.*;
+                    @Database(entities = {User.class}, version = 1, exportSchema = true)
+                    public abstract class MyDb extends RoomDatabase {}
+                    """
+                        .trimIndent()
+                )
+            }
+        runProcessorTest(
+            sources = listOf(dbSource, USER),
+            javacProcessors = listOf(RoomProcessor()),
+            symbolProcessorProviders = listOf(RoomKspProcessor.Provider()),
+            options = mapOf("room.exportSchemaResource" to "true"),
+        ) {
+            it.generatedResourceFileWithPath("schemas/foo.bar.MyDb/1.json")
+        }
     }
 
     @Test
diff --git a/room/room-compiler/src/test/test-data/autoMigrationWriter/output/java/AutoMigrationWithProvidedSpec.java b/room/room-compiler/src/test/test-data/autoMigrationWriter/output/java/AutoMigrationWithProvidedSpec.java
index e33f4bd..6e2d6fc 100644
--- a/room/room-compiler/src/test/test-data/autoMigrationWriter/output/java/AutoMigrationWithProvidedSpec.java
+++ b/room/room-compiler/src/test/test-data/autoMigrationWriter/output/java/AutoMigrationWithProvidedSpec.java
@@ -3,8 +3,8 @@
 import androidx.annotation.NonNull;
 import androidx.room.migration.AutoMigrationSpec;
 import androidx.room.migration.Migration;
+import androidx.sqlite.SQLite;
 import androidx.sqlite.SQLiteConnection;
-import androidx.sqlite.SQLiteKt;
 import java.lang.Override;
 import java.lang.SuppressWarnings;
 import javax.annotation.processing.Generated;
@@ -21,7 +21,7 @@
 
     @Override
     public void migrate(@NonNull final SQLiteConnection connection) {
-        SQLiteKt.execSQL(connection, "ALTER TABLE `Song` ADD COLUMN `artistId` INTEGER DEFAULT NULL");
+        SQLite.execSQL(connection, "ALTER TABLE `Song` ADD COLUMN `artistId` INTEGER DEFAULT NULL");
         callback.onPostMigrate(connection);
     }
 }
\ No newline at end of file
diff --git a/room/room-compiler/src/test/test-data/autoMigrationWriter/output/java/ValidAutoMigrationWithDefault.java b/room/room-compiler/src/test/test-data/autoMigrationWriter/output/java/ValidAutoMigrationWithDefault.java
index 66cd44a..cef6678 100644
--- a/room/room-compiler/src/test/test-data/autoMigrationWriter/output/java/ValidAutoMigrationWithDefault.java
+++ b/room/room-compiler/src/test/test-data/autoMigrationWriter/output/java/ValidAutoMigrationWithDefault.java
@@ -3,8 +3,8 @@
 import androidx.annotation.NonNull;
 import androidx.room.migration.AutoMigrationSpec;
 import androidx.room.migration.Migration;
+import androidx.sqlite.SQLite;
 import androidx.sqlite.SQLiteConnection;
-import androidx.sqlite.SQLiteKt;
 import java.lang.Override;
 import java.lang.SuppressWarnings;
 import javax.annotation.processing.Generated;
@@ -20,7 +20,7 @@
 
     @Override
     public void migrate(@NonNull final SQLiteConnection connection) {
-        SQLiteKt.execSQL(connection, "ALTER TABLE `Song` ADD COLUMN `artistId` INTEGER NOT NULL DEFAULT 0");
+        SQLite.execSQL(connection, "ALTER TABLE `Song` ADD COLUMN `artistId` INTEGER NOT NULL DEFAULT 0");
         callback.onPostMigrate(connection);
     }
 }
\ No newline at end of file
diff --git a/room/room-compiler/src/test/test-data/autoMigrationWriter/output/java/ValidAutoMigrationWithoutDefault.java b/room/room-compiler/src/test/test-data/autoMigrationWriter/output/java/ValidAutoMigrationWithoutDefault.java
index 34881bf..b6d835a 100644
--- a/room/room-compiler/src/test/test-data/autoMigrationWriter/output/java/ValidAutoMigrationWithoutDefault.java
+++ b/room/room-compiler/src/test/test-data/autoMigrationWriter/output/java/ValidAutoMigrationWithoutDefault.java
@@ -3,8 +3,8 @@
 import androidx.annotation.NonNull;
 import androidx.room.migration.AutoMigrationSpec;
 import androidx.room.migration.Migration;
+import androidx.sqlite.SQLite;
 import androidx.sqlite.SQLiteConnection;
-import androidx.sqlite.SQLiteKt;
 import java.lang.Override;
 import java.lang.SuppressWarnings;
 import javax.annotation.processing.Generated;
@@ -20,7 +20,7 @@
 
     @Override
     public void migrate(@NonNull final SQLiteConnection connection) {
-        SQLiteKt.execSQL(connection, "ALTER TABLE `Song` ADD COLUMN `artistId` INTEGER DEFAULT NULL");
+        SQLite.execSQL(connection, "ALTER TABLE `Song` ADD COLUMN `artistId` INTEGER DEFAULT NULL");
         callback.onPostMigrate(connection);
     }
 }
\ No newline at end of file
diff --git a/room/room-compiler/src/test/test-data/databasewriter/output/ComplexDatabase.java b/room/room-compiler/src/test/test-data/databasewriter/output/ComplexDatabase.java
index a15107e..2e67b2d 100644
--- a/room/room-compiler/src/test/test-data/databasewriter/output/ComplexDatabase.java
+++ b/room/room-compiler/src/test/test-data/databasewriter/output/ComplexDatabase.java
@@ -8,8 +8,8 @@
 import androidx.room.util.DBUtil;
 import androidx.room.util.TableInfo;
 import androidx.room.util.ViewInfo;
+import androidx.sqlite.SQLite;
 import androidx.sqlite.SQLiteConnection;
-import androidx.sqlite.SQLiteKt;
 import java.lang.Class;
 import java.lang.Override;
 import java.lang.String;
@@ -33,20 +33,20 @@
         final RoomOpenDelegate _openDelegate = new RoomOpenDelegate(1923, "12b646c55443feeefb567521e2bece85", "2f1dbf49584f5d6c91cb44f8a6ecfee2") {
             @Override
             public void createAllTables(@NonNull final SQLiteConnection connection) {
-                SQLiteKt.execSQL(connection, "CREATE TABLE IF NOT EXISTS `User` (`uid` INTEGER NOT NULL, `name` TEXT, `lastName` TEXT, `ageColumn` INTEGER NOT NULL, PRIMARY KEY(`uid`))");
-                SQLiteKt.execSQL(connection, "CREATE TABLE IF NOT EXISTS `Child1` (`id` INTEGER NOT NULL, `name` TEXT, `serial` INTEGER, `code` TEXT, PRIMARY KEY(`id`))");
-                SQLiteKt.execSQL(connection, "CREATE TABLE IF NOT EXISTS `Child2` (`id` INTEGER NOT NULL, `name` TEXT, `serial` INTEGER, `code` TEXT, PRIMARY KEY(`id`))");
-                SQLiteKt.execSQL(connection, "CREATE VIEW `UserSummary` AS SELECT uid, name FROM User");
-                SQLiteKt.execSQL(connection, "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)");
-                SQLiteKt.execSQL(connection, "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '12b646c55443feeefb567521e2bece85')");
+                SQLite.execSQL(connection, "CREATE TABLE IF NOT EXISTS `User` (`uid` INTEGER NOT NULL, `name` TEXT, `lastName` TEXT, `ageColumn` INTEGER NOT NULL, PRIMARY KEY(`uid`))");
+                SQLite.execSQL(connection, "CREATE TABLE IF NOT EXISTS `Child1` (`id` INTEGER NOT NULL, `name` TEXT, `serial` INTEGER, `code` TEXT, PRIMARY KEY(`id`))");
+                SQLite.execSQL(connection, "CREATE TABLE IF NOT EXISTS `Child2` (`id` INTEGER NOT NULL, `name` TEXT, `serial` INTEGER, `code` TEXT, PRIMARY KEY(`id`))");
+                SQLite.execSQL(connection, "CREATE VIEW `UserSummary` AS SELECT uid, name FROM User");
+                SQLite.execSQL(connection, "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)");
+                SQLite.execSQL(connection, "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '12b646c55443feeefb567521e2bece85')");
             }
 
             @Override
             public void dropAllTables(@NonNull final SQLiteConnection connection) {
-                SQLiteKt.execSQL(connection, "DROP TABLE IF EXISTS `User`");
-                SQLiteKt.execSQL(connection, "DROP TABLE IF EXISTS `Child1`");
-                SQLiteKt.execSQL(connection, "DROP TABLE IF EXISTS `Child2`");
-                SQLiteKt.execSQL(connection, "DROP VIEW IF EXISTS `UserSummary`");
+                SQLite.execSQL(connection, "DROP TABLE IF EXISTS `User`");
+                SQLite.execSQL(connection, "DROP TABLE IF EXISTS `Child1`");
+                SQLite.execSQL(connection, "DROP TABLE IF EXISTS `Child2`");
+                SQLite.execSQL(connection, "DROP VIEW IF EXISTS `UserSummary`");
             }
 
             @Override
diff --git a/room/room-paging/build.gradle b/room/room-paging/build.gradle
index 4dc6d6c..defbfa9 100644
--- a/room/room-paging/build.gradle
+++ b/room/room-paging/build.gradle
@@ -14,21 +14,58 @@
  * limitations under the License.
  */
 
-/**
- * This file was created using the `create_project.py` script located in the
- * `<AndroidX root>/development/project-creator` directory.
- *
- * Please use that script when creating a new project, rather than copying an existing project and
- * modifying its settings.
- */
-import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+import androidx.build.PlatformIdentifier
 import androidx.build.LibraryType
 
 plugins {
     id("AndroidXPlugin")
-    id("com.android.library")
-    id("kotlin-android")
     id("com.google.devtools.ksp")
+    id("com.android.library")
+}
+
+androidXMultiplatform {
+    android()
+    jvm()
+    mac()
+    linux()
+    ios()
+
+    defaultPlatform(PlatformIdentifier.ANDROID)
+
+    sourceSets {
+        commonMain {
+            dependencies {
+                api(libs.kotlinStdlib)
+                api("androidx.paging:paging-common:3.3.0")
+                api(project(":room:room-runtime"))
+            }
+        }
+
+        commonTest {
+            dependencies {
+                implementation(libs.kotlinCoroutinesTest)
+                implementation(project(":kruth:kruth"))
+            }
+        }
+
+        androidMain {
+            dependsOn(commonMain)
+        }
+
+        androidInstrumentedTest {
+            dependsOn(commonTest)
+            dependencies {
+                implementation(libs.junit)
+                implementation(project(":internal-testutils-common"))
+                implementation(libs.kotlinTestJunit)
+                implementation(libs.testExtJunit)
+                implementation(libs.testCore)
+                implementation(libs.testRunner)
+                implementation("androidx.arch.core:core-testing:2.2.0")
+                implementation(projectOrArtifact(":paging:paging-testing"))
+            }
+        }
+    }
 }
 
 android {
@@ -36,23 +73,7 @@
 }
 
 dependencies {
-    api(libs.kotlinStdlib)
-
-    api(project(":room:room-runtime"))
-    implementation(project(":room:room-ktx"))
-    api("androidx.paging:paging-common:3.1.1")
-
-    androidTestImplementation(libs.kotlinCoroutinesTest)
-    androidTestImplementation(libs.kotlinTestJunit)
-    androidTestImplementation(libs.junit)
-    androidTestImplementation(libs.testExtJunit)
-    androidTestImplementation(libs.testCore)
-    androidTestImplementation(libs.testRunner)
-    kspAndroidTest(project(":room:room-compiler"))
-    androidTestImplementation(project(":kruth:kruth"))
-    androidTestImplementation("androidx.arch.core:core-testing:2.2.0")
-    androidTestImplementation(project(":internal-testutils-common"))
-    androidTestImplementation(projectOrArtifact(":paging:paging-testing"))
+    add("kspAndroidAndroidTest", project(":room:room-compiler"))
 }
 
 androidx {
diff --git a/room/room-paging/src/androidTest/AndroidManifest.xml b/room/room-paging/src/androidInstrumentedTest/AndroidManifest.xml
similarity index 100%
rename from room/room-paging/src/androidTest/AndroidManifest.xml
rename to room/room-paging/src/androidInstrumentedTest/AndroidManifest.xml
diff --git a/room/room-paging/src/androidTest/kotlin/androidx/room/paging/LimitOffsetPagingSourceTest.kt b/room/room-paging/src/androidInstrumentedTest/kotlin/androidx/room/paging/LimitOffsetPagingSourceTest.kt
similarity index 100%
rename from room/room-paging/src/androidTest/kotlin/androidx/room/paging/LimitOffsetPagingSourceTest.kt
rename to room/room-paging/src/androidInstrumentedTest/kotlin/androidx/room/paging/LimitOffsetPagingSourceTest.kt
diff --git a/room/room-paging/src/androidTest/kotlin/androidx/room/paging/LimitOffsetTestDb.kt b/room/room-paging/src/androidInstrumentedTest/kotlin/androidx/room/paging/LimitOffsetTestDb.kt
similarity index 100%
rename from room/room-paging/src/androidTest/kotlin/androidx/room/paging/LimitOffsetTestDb.kt
rename to room/room-paging/src/androidInstrumentedTest/kotlin/androidx/room/paging/LimitOffsetTestDb.kt
diff --git a/room/room-paging/src/androidTest/kotlin/androidx/room/paging/TestItem.kt b/room/room-paging/src/androidInstrumentedTest/kotlin/androidx/room/paging/TestItem.kt
similarity index 100%
rename from room/room-paging/src/androidTest/kotlin/androidx/room/paging/TestItem.kt
rename to room/room-paging/src/androidInstrumentedTest/kotlin/androidx/room/paging/TestItem.kt
diff --git a/room/room-paging/src/androidTest/kotlin/androidx/room/paging/TestItemDao.kt b/room/room-paging/src/androidInstrumentedTest/kotlin/androidx/room/paging/TestItemDao.kt
similarity index 100%
rename from room/room-paging/src/androidTest/kotlin/androidx/room/paging/TestItemDao.kt
rename to room/room-paging/src/androidInstrumentedTest/kotlin/androidx/room/paging/TestItemDao.kt
diff --git a/room/room-paging/src/main/java/androidx/room/paging/LimitOffsetPagingSource.kt b/room/room-paging/src/androidMain/kotlin/androidx/room/paging/LimitOffsetPagingSource.android.kt
similarity index 100%
rename from room/room-paging/src/main/java/androidx/room/paging/LimitOffsetPagingSource.kt
rename to room/room-paging/src/androidMain/kotlin/androidx/room/paging/LimitOffsetPagingSource.android.kt
diff --git a/room/room-paging/src/main/java/androidx/room/paging/util/RoomPagingUtil.kt b/room/room-paging/src/androidMain/kotlin/androidx/room/paging/util/RoomPagingUtil.android.kt
similarity index 100%
rename from room/room-paging/src/main/java/androidx/room/paging/util/RoomPagingUtil.kt
rename to room/room-paging/src/androidMain/kotlin/androidx/room/paging/util/RoomPagingUtil.android.kt
diff --git a/room/room-paging/src/main/java/androidx/room/paging/util/ThreadSafeInvalidationObserver.kt b/room/room-paging/src/androidMain/kotlin/androidx/room/paging/util/ThreadSafeInvalidationObserver.android.kt
similarity index 100%
rename from room/room-paging/src/main/java/androidx/room/paging/util/ThreadSafeInvalidationObserver.kt
rename to room/room-paging/src/androidMain/kotlin/androidx/room/paging/util/ThreadSafeInvalidationObserver.android.kt
diff --git a/room/room-paging/src/commonMain/kotlin/androidx/room/paging/Placeholder.kt b/room/room-paging/src/commonMain/kotlin/androidx/room/paging/Placeholder.kt
new file mode 100644
index 0000000..fb1781e
--- /dev/null
+++ b/room/room-paging/src/commonMain/kotlin/androidx/room/paging/Placeholder.kt
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.room.paging
+// empty file to trigger klib creation
+// see: https://youtrack.jetbrains.com/issue/KT-52344
diff --git a/room/room-runtime/api/api_lint.ignore b/room/room-runtime/api/api_lint.ignore
index ea57dfd..7aca103 100644
--- a/room/room-runtime/api/api_lint.ignore
+++ b/room/room-runtime/api/api_lint.ignore
@@ -1,10 +1,4 @@
 // Baseline format: 1.0
-AcronymName: androidx.room.Transactor.SQLiteTransactionType:
-    Acronyms should not be capitalized in class names: was `SQLiteTransactionType`, should this be `SqLiteTransactionType`?
-AcronymName: androidx.room.TransactorKt#execSQL(androidx.room.PooledConnection, String, kotlin.coroutines.Continuation<? super kotlin.Unit>):
-    Acronyms should not be capitalized in method names: was `execSQL`, should this be `execSql`?
-
-
 ArrayReturn: androidx.room.RoomDatabase#query(String, Object[]) parameter #1:
     Method parameter should be Collection<Object> (or subclass) instead of raw array; was `java.lang.Object[]`
 
diff --git a/room/room-runtime/build.gradle b/room/room-runtime/build.gradle
index cfcc74c..760faab 100644
--- a/room/room-runtime/build.gradle
+++ b/room/room-runtime/build.gradle
@@ -106,6 +106,7 @@
                 api(libs.kotlinStdlib)
                 api(project(":room:room-common"))
                 api(project(":sqlite:sqlite"))
+                api("androidx.collection:collection:1.4.0")
                 api("androidx.annotation:annotation:1.8.0")
                 api(libs.kotlinCoroutinesCore)
                 implementation(libs.atomicFu)
@@ -141,7 +142,6 @@
                 api(project(":sqlite:sqlite-framework"))
                 api(libs.kotlinCoroutinesAndroid)
                 implementation("androidx.arch.core:core-runtime:2.2.0")
-                compileOnly("androidx.collection:collection:1.2.0")
                 compileOnly("androidx.lifecycle:lifecycle-livedata-core:2.0.0")
                 compileOnly("androidx.paging:paging-common:2.0.0")
                 implementation("androidx.annotation:annotation-experimental:1.4.1")
diff --git a/room/room-runtime/proguard-rules.pro b/room/room-runtime/proguard-rules.pro
index 60b1670..6bdfcb2 100644
--- a/room/room-runtime/proguard-rules.pro
+++ b/room/room-runtime/proguard-rules.pro
@@ -1,3 +1,3 @@
--keep class * extends androidx.room.RoomDatabase
+-keep class * extends androidx.room.RoomDatabase { void <init>(); }
 -dontwarn androidx.room.paging.**
 -dontwarn androidx.lifecycle.LiveData
diff --git a/room/room-runtime/src/androidMain/kotlin/androidx/room/RoomConnectionManager.android.kt b/room/room-runtime/src/androidMain/kotlin/androidx/room/RoomConnectionManager.android.kt
index a622b72..2e10482 100644
--- a/room/room-runtime/src/androidMain/kotlin/androidx/room/RoomConnectionManager.android.kt
+++ b/room/room-runtime/src/androidMain/kotlin/androidx/room/RoomConnectionManager.android.kt
@@ -16,17 +16,17 @@
 
 package androidx.room
 
+import androidx.room.coroutines.AndroidSQLiteDriverConnectionPool
 import androidx.room.coroutines.ConnectionPool
-import androidx.room.coroutines.RawConnectionAccessor
 import androidx.room.coroutines.newConnectionPool
 import androidx.room.coroutines.newSingleConnectionPool
 import androidx.room.driver.SupportSQLiteConnection
+import androidx.room.driver.SupportSQLiteConnectionPool
 import androidx.room.driver.SupportSQLiteDriver
 import androidx.sqlite.SQLiteConnection
-import androidx.sqlite.SQLiteStatement
 import androidx.sqlite.db.SupportSQLiteDatabase
 import androidx.sqlite.db.SupportSQLiteOpenHelper
-import androidx.sqlite.use
+import androidx.sqlite.driver.AndroidSQLiteDriver
 
 /**
  * An Android platform specific [RoomConnectionManager] with backwards compatibility with
@@ -41,7 +41,7 @@
     private val connectionPool: ConnectionPool
 
     internal val supportOpenHelper: SupportSQLiteOpenHelper?
-        get() = (connectionPool as? SupportConnectionPool)?.supportDriver?.openHelper
+        get() = (connectionPool as? SupportSQLiteConnectionPool)?.supportDriver?.openHelper
 
     private var supportDatabase: SupportSQLiteDatabase? = null
 
@@ -64,12 +64,19 @@
                     .callback(SupportOpenHelperCallback(openDelegate.version))
                     .build()
             this.connectionPool =
-                SupportConnectionPool(
+                SupportSQLiteConnectionPool(
                     SupportSQLiteDriver(config.sqliteOpenHelperFactory.create(openHelperConfig))
                 )
         } else {
             this.connectionPool =
-                if (configuration.name == null) {
+                if (config.sqliteDriver is AndroidSQLiteDriver) {
+                    // Special-case the Android driver and use a pass-through pool since the Android
+                    // bindings internally already have a thread-confined connection pool.
+                    AndroidSQLiteDriverConnectionPool(
+                        driver = DriverWrapper(config.sqliteDriver),
+                        fileName = configuration.name ?: ":memory:"
+                    )
+                } else if (configuration.name == null) {
                     // An in-memory database must use a single connection pool.
                     newSingleConnectionPool(
                         driver = DriverWrapper(config.sqliteDriver),
@@ -100,7 +107,7 @@
         val configWithCompatibilityCallback =
             config.installOnOpenCallback { db -> supportDatabase = db }
         this.connectionPool =
-            SupportConnectionPool(
+            SupportSQLiteConnectionPool(
                 SupportSQLiteDriver(
                     supportOpenHelperFactory.invoke(configWithCompatibilityCallback)
                 )
@@ -184,103 +191,6 @@
         }
     }
 
-    /**
-     * An implementation of a connection pool used in compatibility mode. This impl doesn't do any
-     * connection management since the SupportSQLite* APIs already internally do.
-     */
-    private class SupportConnectionPool(val supportDriver: SupportSQLiteDriver) : ConnectionPool {
-        private val supportConnection by
-            lazy(LazyThreadSafetyMode.PUBLICATION) {
-                val fileName = supportDriver.openHelper.databaseName ?: ":memory:"
-                SupportPooledConnection(supportDriver.open(fileName))
-            }
-
-        override suspend fun <R> useConnection(
-            isReadOnly: Boolean,
-            block: suspend (Transactor) -> R
-        ): R {
-            return block.invoke(supportConnection)
-        }
-
-        override fun close() {
-            supportDriver.openHelper.close()
-        }
-    }
-
-    private class SupportPooledConnection(val delegate: SupportSQLiteConnection) :
-        Transactor, RawConnectionAccessor {
-
-        private var currentTransactionType: Transactor.SQLiteTransactionType? = null
-
-        override val rawConnection: SQLiteConnection
-            get() = delegate
-
-        override suspend fun <R> usePrepared(sql: String, block: (SQLiteStatement) -> R): R {
-            return delegate.prepare(sql).use { block.invoke(it) }
-        }
-
-        // TODO(b/318767291): Add coroutine confinement like RoomDatabase.withTransaction
-        override suspend fun <R> withTransaction(
-            type: Transactor.SQLiteTransactionType,
-            block: suspend TransactionScope<R>.() -> R
-        ): R {
-            return transaction(type, block)
-        }
-
-        private suspend fun <R> transaction(
-            type: Transactor.SQLiteTransactionType,
-            block: suspend TransactionScope<R>.() -> R
-        ): R {
-            val db = delegate.db
-            if (!db.inTransaction()) {
-                currentTransactionType = type
-            }
-            when (type) {
-                Transactor.SQLiteTransactionType.DEFERRED -> db.beginTransactionReadOnly()
-                Transactor.SQLiteTransactionType.IMMEDIATE -> db.beginTransactionNonExclusive()
-                Transactor.SQLiteTransactionType.EXCLUSIVE -> db.beginTransaction()
-            }
-            try {
-                val result = SupportTransactor<R>().block()
-                db.setTransactionSuccessful()
-                return result
-            } catch (rollback: RollbackException) {
-                @Suppress("UNCHECKED_CAST") return rollback.result as R
-            } finally {
-                db.endTransaction()
-                if (!db.inTransaction()) {
-                    currentTransactionType = null
-                }
-            }
-        }
-
-        override suspend fun inTransaction(): Boolean {
-            return delegate.db.inTransaction()
-        }
-
-        private class RollbackException(val result: Any?) : Throwable()
-
-        private inner class SupportTransactor<T> : TransactionScope<T>, RawConnectionAccessor {
-
-            override val rawConnection: SQLiteConnection
-                get() = [email protected]
-
-            override suspend fun <R> usePrepared(sql: String, block: (SQLiteStatement) -> R): R {
-                return [email protected](sql, block)
-            }
-
-            override suspend fun <R> withNestedTransaction(
-                block: suspend (TransactionScope<R>) -> R
-            ): R {
-                return transaction(checkNotNull(currentTransactionType), block)
-            }
-
-            override suspend fun rollback(result: T): Nothing {
-                throw RollbackException(result)
-            }
-        }
-    }
-
     private fun DatabaseConfiguration.installOnOpenCallback(
         onOpen: (SupportSQLiteDatabase) -> Unit
     ): DatabaseConfiguration {
diff --git a/room/room-runtime/src/androidMain/kotlin/androidx/room/coroutines/AndroidSQLiteDriverConnectionPool.android.kt b/room/room-runtime/src/androidMain/kotlin/androidx/room/coroutines/AndroidSQLiteDriverConnectionPool.android.kt
new file mode 100644
index 0000000..a815c7e
--- /dev/null
+++ b/room/room-runtime/src/androidMain/kotlin/androidx/room/coroutines/AndroidSQLiteDriverConnectionPool.android.kt
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.room.coroutines
+
+import androidx.room.TransactionScope
+import androidx.room.Transactor
+import androidx.sqlite.SQLiteConnection
+import androidx.sqlite.SQLiteDriver
+import androidx.sqlite.SQLiteStatement
+import androidx.sqlite.driver.AndroidSQLiteConnection
+import androidx.sqlite.driver.AndroidSQLiteDriver
+import androidx.sqlite.use
+
+/**
+ * An implementation of a connection pool used when an [AndroidSQLiteDriver] is provided. This impl
+ * doesn't do any connection management since the Android SQLite APIs already internally do.
+ */
+internal class AndroidSQLiteDriverConnectionPool(
+    private val driver: SQLiteDriver,
+    private val fileName: String
+) : ConnectionPool {
+
+    private val androidConnection by lazy {
+        AndroidSQLiteDriverPooledConnection(driver.open(fileName) as AndroidSQLiteConnection)
+    }
+
+    override suspend fun <R> useConnection(
+        isReadOnly: Boolean,
+        block: suspend (Transactor) -> R
+    ): R {
+        return block.invoke(androidConnection)
+    }
+
+    override fun close() {
+        androidConnection.delegate.close()
+    }
+}
+
+private class AndroidSQLiteDriverPooledConnection(val delegate: AndroidSQLiteConnection) :
+    Transactor, RawConnectionAccessor {
+
+    private var currentTransactionType: Transactor.SQLiteTransactionType? = null
+
+    override val rawConnection: SQLiteConnection
+        get() = delegate
+
+    override suspend fun <R> usePrepared(sql: String, block: (SQLiteStatement) -> R): R {
+        return delegate.prepare(sql).use { block.invoke(it) }
+    }
+
+    // TODO(b/318767291): Add coroutine confinement like RoomDatabase.withTransaction
+    override suspend fun <R> withTransaction(
+        type: Transactor.SQLiteTransactionType,
+        block: suspend TransactionScope<R>.() -> R
+    ): R {
+        return transaction(type, block)
+    }
+
+    private suspend fun <R> transaction(
+        type: Transactor.SQLiteTransactionType,
+        block: suspend TransactionScope<R>.() -> R
+    ): R {
+        val db = delegate.db
+        if (!db.inTransaction()) {
+            currentTransactionType = type
+        }
+        when (type) {
+            // TODO(b/288918056): Use Android V API for DEFERRED once it is available
+            Transactor.SQLiteTransactionType.DEFERRED -> db.beginTransactionNonExclusive()
+            Transactor.SQLiteTransactionType.IMMEDIATE -> db.beginTransactionNonExclusive()
+            Transactor.SQLiteTransactionType.EXCLUSIVE -> db.beginTransaction()
+        }
+        try {
+            val result = AndroidSQLiteDriverTransactor<R>().block()
+            db.setTransactionSuccessful()
+            return result
+        } catch (rollback: ConnectionPool.RollbackException) {
+            @Suppress("UNCHECKED_CAST") return rollback.result as R
+        } finally {
+            db.endTransaction()
+            if (!db.inTransaction()) {
+                currentTransactionType = null
+            }
+        }
+    }
+
+    override suspend fun inTransaction(): Boolean {
+        return delegate.db.inTransaction()
+    }
+
+    private inner class AndroidSQLiteDriverTransactor<T> :
+        TransactionScope<T>, RawConnectionAccessor {
+
+        override val rawConnection: SQLiteConnection
+            get() = [email protected]
+
+        override suspend fun <R> usePrepared(sql: String, block: (SQLiteStatement) -> R): R {
+            return [email protected](sql, block)
+        }
+
+        override suspend fun <R> withNestedTransaction(
+            block: suspend (TransactionScope<R>) -> R
+        ): R {
+            return transaction(checkNotNull(currentTransactionType), block)
+        }
+
+        override suspend fun rollback(result: T): Nothing {
+            throw ConnectionPool.RollbackException(result)
+        }
+    }
+}
diff --git a/room/room-runtime/src/androidMain/kotlin/androidx/room/driver/SupportSQLiteConnectionPool.android.kt b/room/room-runtime/src/androidMain/kotlin/androidx/room/driver/SupportSQLiteConnectionPool.android.kt
new file mode 100644
index 0000000..194d4047
--- /dev/null
+++ b/room/room-runtime/src/androidMain/kotlin/androidx/room/driver/SupportSQLiteConnectionPool.android.kt
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.room.driver
+
+import androidx.room.TransactionScope
+import androidx.room.Transactor
+import androidx.room.coroutines.ConnectionPool
+import androidx.room.coroutines.RawConnectionAccessor
+import androidx.sqlite.SQLiteConnection
+import androidx.sqlite.SQLiteStatement
+import androidx.sqlite.use
+
+/**
+ * An implementation of a connection pool used in compatibility mode. This impl doesn't do any
+ * connection management since the SupportSQLite* APIs already internally do.
+ */
+internal class SupportSQLiteConnectionPool(internal val supportDriver: SupportSQLiteDriver) :
+    ConnectionPool {
+    private val supportConnection by
+        lazy(LazyThreadSafetyMode.PUBLICATION) {
+            val fileName = supportDriver.openHelper.databaseName ?: ":memory:"
+            SupportSQLitePooledConnection(supportDriver.open(fileName))
+        }
+
+    override suspend fun <R> useConnection(
+        isReadOnly: Boolean,
+        block: suspend (Transactor) -> R
+    ): R {
+        return block.invoke(supportConnection)
+    }
+
+    override fun close() {
+        supportDriver.openHelper.close()
+    }
+}
+
+private class SupportSQLitePooledConnection(val delegate: SupportSQLiteConnection) :
+    Transactor, RawConnectionAccessor {
+
+    private var currentTransactionType: Transactor.SQLiteTransactionType? = null
+
+    override val rawConnection: SQLiteConnection
+        get() = delegate
+
+    override suspend fun <R> usePrepared(sql: String, block: (SQLiteStatement) -> R): R {
+        return delegate.prepare(sql).use { block.invoke(it) }
+    }
+
+    override suspend fun <R> withTransaction(
+        type: Transactor.SQLiteTransactionType,
+        block: suspend TransactionScope<R>.() -> R
+    ): R {
+        return transaction(type, block)
+    }
+
+    private suspend fun <R> transaction(
+        type: Transactor.SQLiteTransactionType,
+        block: suspend TransactionScope<R>.() -> R
+    ): R {
+        val db = delegate.db
+        if (!db.inTransaction()) {
+            currentTransactionType = type
+        }
+        when (type) {
+            Transactor.SQLiteTransactionType.DEFERRED -> db.beginTransactionReadOnly()
+            Transactor.SQLiteTransactionType.IMMEDIATE -> db.beginTransactionNonExclusive()
+            Transactor.SQLiteTransactionType.EXCLUSIVE -> db.beginTransaction()
+        }
+        try {
+            val result = SupportSQLiteTransactor<R>().block()
+            db.setTransactionSuccessful()
+            return result
+        } catch (rollback: ConnectionPool.RollbackException) {
+            @Suppress("UNCHECKED_CAST") return rollback.result as R
+        } finally {
+            db.endTransaction()
+            if (!db.inTransaction()) {
+                currentTransactionType = null
+            }
+        }
+    }
+
+    override suspend fun inTransaction(): Boolean {
+        return delegate.db.inTransaction()
+    }
+
+    private inner class SupportSQLiteTransactor<T> : TransactionScope<T>, RawConnectionAccessor {
+
+        override val rawConnection: SQLiteConnection
+            get() = [email protected]
+
+        override suspend fun <R> usePrepared(sql: String, block: (SQLiteStatement) -> R): R {
+            return [email protected](sql, block)
+        }
+
+        override suspend fun <R> withNestedTransaction(
+            block: suspend (TransactionScope<R>) -> R
+        ): R {
+            return transaction(checkNotNull(currentTransactionType), block)
+        }
+
+        override suspend fun rollback(result: T): Nothing {
+            throw ConnectionPool.RollbackException(result)
+        }
+    }
+}
diff --git a/room/room-runtime/src/androidMain/kotlin/androidx/room/util/RelationUtil.android.kt b/room/room-runtime/src/androidMain/kotlin/androidx/room/util/RelationUtil.android.kt
index 2da15f2..1ea7240 100644
--- a/room/room-runtime/src/androidMain/kotlin/androidx/room/util/RelationUtil.android.kt
+++ b/room/room-runtime/src/androidMain/kotlin/androidx/room/util/RelationUtil.android.kt
@@ -21,7 +21,6 @@
 
 import androidx.annotation.RestrictTo
 import androidx.collection.ArrayMap
-import androidx.collection.LongSparseArray
 import androidx.room.RoomDatabase
 
 /**
@@ -71,43 +70,6 @@
     }
 }
 
-/** Same as [recursiveFetchHashMap] but for [LongSparseArray]. */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
-fun <V> recursiveFetchLongSparseArray(
-    map: LongSparseArray<V>,
-    isRelationCollection: Boolean,
-    fetchBlock: (LongSparseArray<V>) -> Unit
-) {
-    val tmpMap = LongSparseArray<V>(RoomDatabase.MAX_BIND_PARAMETER_CNT)
-    var count = 0
-    var mapIndex = 0
-    val limit = map.size()
-    while (mapIndex < limit) {
-        if (isRelationCollection) {
-            tmpMap.put(map.keyAt(mapIndex), map.valueAt(mapIndex))
-        } else {
-            // Safe because `V` is a nullable type arg when isRelationCollection == false
-            @Suppress("UNCHECKED_CAST") tmpMap.put(map.keyAt(mapIndex), null as V)
-        }
-        mapIndex++
-        count++
-        if (count == RoomDatabase.MAX_BIND_PARAMETER_CNT) {
-            fetchBlock(tmpMap)
-            if (!isRelationCollection) {
-                map.putAll(tmpMap)
-            }
-            tmpMap.clear()
-            count = 0
-        }
-    }
-    if (count > 0) {
-        fetchBlock(tmpMap)
-        if (!isRelationCollection) {
-            map.putAll(tmpMap)
-        }
-    }
-}
-
 /** Same as [recursiveFetchHashMap] but for [ArrayMap]. */
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
 fun <K : Any, V> recursiveFetchArrayMap(
diff --git a/room/room-runtime/src/androidUnitTest/kotlin/androidx/room/InvalidationTrackerTest.kt b/room/room-runtime/src/androidUnitTest/kotlin/androidx/room/InvalidationTrackerTest.kt
index f649b1e..ed9ea59 100644
--- a/room/room-runtime/src/androidUnitTest/kotlin/androidx/room/InvalidationTrackerTest.kt
+++ b/room/room-runtime/src/androidUnitTest/kotlin/androidx/room/InvalidationTrackerTest.kt
@@ -23,6 +23,7 @@
 import androidx.sqlite.SQLiteConnection
 import androidx.sqlite.SQLiteDriver
 import androidx.sqlite.SQLiteStatement
+import androidx.test.filters.FlakyTest
 import java.lang.ref.WeakReference
 import java.util.Locale
 import java.util.concurrent.CountDownLatch
@@ -313,6 +314,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 349880963)
     fun multipleRefreshAsync() = runTest {
         // Validate that when multiple refresh are enqueued, that only one runs.
         tracker.refreshAsync()
diff --git a/room/room-runtime/src/commonMain/kotlin/androidx/room/Transactor.kt b/room/room-runtime/src/commonMain/kotlin/androidx/room/Transactor.kt
index 7ba38d0..105f220 100644
--- a/room/room-runtime/src/commonMain/kotlin/androidx/room/Transactor.kt
+++ b/room/room-runtime/src/commonMain/kotlin/androidx/room/Transactor.kt
@@ -42,6 +42,7 @@
 }
 
 /** Executes a single SQL statement that returns no values. */
+@Suppress("AcronymName") // SQL is a known term and should remain capitalized
 suspend fun PooledConnection.execSQL(sql: String) {
     usePrepared(sql) { it.step() }
 }
@@ -77,6 +78,7 @@
      *
      * @see Transactor.withTransaction
      */
+    @Suppress("AcronymName") // SQL is a known term and should remain capitalized
     enum class SQLiteTransactionType {
         /**
          * The transaction mode that does not start the actual transaction until the database is
diff --git a/room/room-runtime/src/commonMain/kotlin/androidx/room/coroutines/ConnectionPool.kt b/room/room-runtime/src/commonMain/kotlin/androidx/room/coroutines/ConnectionPool.kt
index 7725d48..b69b880 100644
--- a/room/room-runtime/src/commonMain/kotlin/androidx/room/coroutines/ConnectionPool.kt
+++ b/room/room-runtime/src/commonMain/kotlin/androidx/room/coroutines/ConnectionPool.kt
@@ -63,6 +63,9 @@
      * the pool is closed.
      */
     fun close()
+
+    /** Internal exception thrown to rollback a transaction. */
+    class RollbackException(val result: Any?) : Throwable()
 }
 
 /**
diff --git a/room/room-runtime/src/commonMain/kotlin/androidx/room/coroutines/ConnectionPoolImpl.kt b/room/room-runtime/src/commonMain/kotlin/androidx/room/coroutines/ConnectionPoolImpl.kt
index 27f43ab..62d9754 100644
--- a/room/room-runtime/src/commonMain/kotlin/androidx/room/coroutines/ConnectionPoolImpl.kt
+++ b/room/room-runtime/src/commonMain/kotlin/androidx/room/coroutines/ConnectionPoolImpl.kt
@@ -320,7 +320,7 @@
             return TransactionImpl<R>().block()
         } catch (ex: Throwable) {
             success = false
-            if (ex is RollbackException) {
+            if (ex is ConnectionPool.RollbackException) {
                 // Type arguments in exception subclasses is not allowed but the exception is always
                 // created with the correct type.
                 @Suppress("UNCHECKED_CAST") return (ex.result as R)
@@ -377,8 +377,6 @@
 
     private class TransactionItem(val id: Int, var shouldRollback: Boolean)
 
-    private class RollbackException(val result: Any?) : Throwable()
-
     private inner class TransactionImpl<T> : TransactionScope<T>, RawConnectionAccessor {
 
         override val rawConnection: SQLiteConnection
@@ -396,7 +394,7 @@
                 error("Not in a transaction")
             }
             delegate.withLock { transactionStack.last().shouldRollback = true }
-            throw RollbackException(result)
+            throw ConnectionPool.RollbackException(result)
         }
     }
 
diff --git a/room/room-runtime/src/commonMain/kotlin/androidx/room/util/RelationUtil.kt b/room/room-runtime/src/commonMain/kotlin/androidx/room/util/RelationUtil.kt
index cf1cc7d..828c589 100644
--- a/room/room-runtime/src/commonMain/kotlin/androidx/room/util/RelationUtil.kt
+++ b/room/room-runtime/src/commonMain/kotlin/androidx/room/util/RelationUtil.kt
@@ -20,6 +20,7 @@
 package androidx.room.util
 
 import androidx.annotation.RestrictTo
+import androidx.collection.LongSparseArray
 import kotlin.jvm.JvmMultifileClass
 import kotlin.jvm.JvmName
 
@@ -70,5 +71,42 @@
     }
 }
 
+/** Same as [recursiveFetchMap] but for [LongSparseArray]. */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+fun <V> recursiveFetchLongSparseArray(
+    map: LongSparseArray<V>,
+    isRelationCollection: Boolean,
+    fetchBlock: (LongSparseArray<V>) -> Unit
+) {
+    val tmpMap = LongSparseArray<V>(MAX_BIND_PARAMETER_CNT)
+    var count = 0
+    var mapIndex = 0
+    val limit = map.size()
+    while (mapIndex < limit) {
+        if (isRelationCollection) {
+            tmpMap.put(map.keyAt(mapIndex), map.valueAt(mapIndex))
+        } else {
+            // Safe because `V` is a nullable type arg when isRelationCollection == false
+            @Suppress("UNCHECKED_CAST") tmpMap.put(map.keyAt(mapIndex), null as V)
+        }
+        mapIndex++
+        count++
+        if (count == MAX_BIND_PARAMETER_CNT) {
+            fetchBlock(tmpMap)
+            if (!isRelationCollection) {
+                map.putAll(tmpMap)
+            }
+            tmpMap.clear()
+            count = 0
+        }
+    }
+    if (count > 0) {
+        fetchBlock(tmpMap)
+        if (!isRelationCollection) {
+            map.putAll(tmpMap)
+        }
+    }
+}
+
 /** Unfortunately, we cannot read this value so we are only setting it to the SQLite default. */
 internal const val MAX_BIND_PARAMETER_CNT = 999
diff --git a/samples/AndroidXDemos/build.gradle b/samples/AndroidXDemos/build.gradle
index 147b863..519d459 100644
--- a/samples/AndroidXDemos/build.gradle
+++ b/samples/AndroidXDemos/build.gradle
@@ -13,15 +13,25 @@
 
 dependencies {
     api(libs.kotlinStdlib)
+
     implementation(project(":appcompat:appcompat"))
+    implementation(project(':appcompat:appcompat-resources'))
     implementation(project(":cardview:cardview"))
+    implementation(project(':core:core'))
     implementation(project(":drawerlayout:drawerlayout"))
     implementation(project(":gridlayout:gridlayout"))
     implementation(project(":palette:palette"))
     implementation(project(":recyclerview:recyclerview"))
     implementation(project(":recyclerview:recyclerview-selection"))
-    implementation("androidx.concurrent:concurrent-futures:1.1.0")
-    api(libs.material)
+    implementation(libs.material)
+    implementation(libs.androidx.annotation)
+    implementation('androidx.collection:collection:1.1.0')
+    implementation('androidx.loader:loader:1.0.0')
+    implementation('androidx.cursoradapter:cursoradapter:1.0.0')
+    implementation('androidx.lifecycle:lifecycle-viewmodel:2.6.2')
+    implementation('androidx.fragment:fragment:1.5.4')
+    implementation('androidx.coordinatorlayout:coordinatorlayout:1.1.0')
+    implementation('androidx.viewpager:viewpager:1.0.0')
 }
 
 android {
diff --git a/security/security-state/src/androidTest/java/androidx/security/state/SecurityStateManagerTest.kt b/security/security-state/src/androidTest/java/androidx/security/state/SecurityStateManagerTest.kt
index 35e8762..d9ec8e5c 100644
--- a/security/security-state/src/androidTest/java/androidx/security/state/SecurityStateManagerTest.kt
+++ b/security/security-state/src/androidTest/java/androidx/security/state/SecurityStateManagerTest.kt
@@ -52,5 +52,25 @@
         // Check if kernel version is in the format X.X.XX
         val versionRegex = "^\\d+\\.\\d+\\.\\d+$"
         assertTrue(bundle.getString("kernel_version")!!.matches(versionRegex.toRegex()))
+
+        // Webview keys are expected to have specific naming and version formats
+        var foundWebView = false
+        val nameRegex = "^com\\.[a-zA-Z0-9_.]+\\.webview$"
+        val versionRegexWebView = "^\\d+\\.\\d+\\.\\d+\\.\\d+$"
+        for (key in bundle.keySet()) {
+            if (key.contains("webview")) {
+                foundWebView = true
+                val nameMatch = key.matches(nameRegex.toRegex())
+                val versionMatch = bundle.getString(key)!!.matches(versionRegexWebView.toRegex())
+
+                assertTrue("Webview name format incorrect: $key", nameMatch)
+                assertTrue(
+                    "Webview version format incorrect for $key: ${bundle.getString(key)}",
+                    versionMatch
+                )
+                break
+            }
+        }
+        assertTrue("No webview key found in bundle", foundWebView)
     }
 }
diff --git a/security/security-state/src/main/java/androidx/security/state/SecurityPatchState.kt b/security/security-state/src/main/java/androidx/security/state/SecurityPatchState.kt
index 4f8a68f..5cfa248 100644
--- a/security/security-state/src/main/java/androidx/security/state/SecurityPatchState.kt
+++ b/security/security-state/src/main/java/androidx/security/state/SecurityPatchState.kt
@@ -295,13 +295,6 @@
         return systemModules.ifEmpty { DEFAULT_SYSTEM_MODULES }
     }
 
-    private fun buildAllowedComponents(): List<String> {
-        // Adding fixed components to the list of system modules
-        val fixedComponents = listOf("system", "kernel", "vendor", "webview")
-
-        return getSystemModules() + fixedComponents
-    }
-
     /**
      * Parses a JSON string to extract vulnerability report data. This method validates the format
      * of the input JSON and constructs a [VulnerabilityReport] object, preparing the class to
@@ -319,7 +312,6 @@
      */
     public fun loadVulnerabilityReport(jsonString: String) {
         val result: VulnerabilityReport
-        val allowedComponents = buildAllowedComponents()
 
         try {
             result = Gson().fromJson(jsonString, VulnerabilityReport::class.java)
@@ -364,7 +356,7 @@
         }
 
         val cvePattern = Pattern.compile("CVE-\\d{4}-\\d{4,}")
-        val asbPattern = Pattern.compile("ASB-\\d{4,}")
+        val asbPattern = Pattern.compile("ASB-A-\\d{4,}")
 
         result.vulnerabilities.values.flatten().forEach { group ->
             group.cveIdentifiers.forEach { cve ->
@@ -378,7 +370,7 @@
             group.asbIdentifiers.forEach { asb ->
                 if (!asbPattern.matcher(asb).matches()) {
                     throw IllegalArgumentException(
-                        "ASB identifier does not match the required format (ASB-XXXX): $asb"
+                        "ASB identifier does not match the required format (ASB-A-XXXX): $asb"
                     )
                 }
             }
@@ -390,12 +382,6 @@
                     "Severity must be: critical, high, moderate, low. Found: ${group.severity}"
                 )
             }
-
-            group.components.forEach { component ->
-                if (!allowedComponents.contains(component)) {
-                    throw IllegalArgumentException("Invalid component. Found: $component")
-                }
-            }
         }
 
         vulnerabilityReport = result
diff --git a/security/security-state/src/main/java/androidx/security/state/SecurityStateManager.kt b/security/security-state/src/main/java/androidx/security/state/SecurityStateManager.kt
index 88e75d8..71e3f5d9 100644
--- a/security/security-state/src/main/java/androidx/security/state/SecurityStateManager.kt
+++ b/security/security-state/src/main/java/androidx/security/state/SecurityStateManager.kt
@@ -22,7 +22,6 @@
 import android.os.Build
 import android.os.Bundle
 import android.system.Os
-import android.util.Log
 import androidx.annotation.RequiresApi
 import androidx.annotation.RestrictTo
 import androidx.webkit.WebViewCompat
@@ -122,10 +121,10 @@
     @RestrictTo(RestrictTo.Scope.LIBRARY)
     public open fun getPackageVersion(packageName: String): String {
         if (packageName.isNotEmpty()) {
-            try {
-                return packageManager.getPackageInfo(packageName, 0).versionName ?: ""
+            return try {
+                packageManager.getPackageInfo(packageName, 0).versionName ?: ""
             } catch (e: PackageManager.NameNotFoundException) {
-                Log.e(TAG, "Failed to get SPL for package $packageName.", e)
+                ""
             }
         }
         return ""
@@ -163,7 +162,7 @@
             } else {
                 null
             }
-        return webViewPackageInfo?.versionName ?: ""
+        return webViewPackageInfo?.packageName ?: ""
     }
 
     /**
diff --git a/security/security-state/src/test/java/androidx/security/state/SecurityPatchStateTest.kt b/security/security-state/src/test/java/androidx/security/state/SecurityPatchStateTest.kt
index ba62223..3725bdf 100644
--- a/security/security-state/src/test/java/androidx/security/state/SecurityPatchStateTest.kt
+++ b/security/security-state/src/test/java/androidx/security/state/SecurityPatchStateTest.kt
@@ -170,7 +170,7 @@
                 "vulnerabilities": {
                     "2020-01-01": [{
                         "cve_identifiers": ["CVE-2020-1234"],
-                        "asb_identifiers": ["ASB-2020"],
+                        "asb_identifiers": ["ASB-A-2020"],
                         "severity": "high",
                         "components": ["system", "vendor"]
                     }]
@@ -250,19 +250,19 @@
                 "vulnerabilities": {
                     "2023-01-01": [{
                         "cve_identifiers": ["CVE-1234-4321"],
-                        "asb_identifiers": ["ASB-2023111"],
+                        "asb_identifiers": ["ASB-A-2023111"],
                         "severity": "high",
                         "components": ["com.google.android.modulemetadata"]
                     }],
                     "2023-05-01": [{
                         "cve_identifiers": ["CVE-1235-4321"],
-                        "asb_identifiers": ["ASB-2025111"],
+                        "asb_identifiers": ["ASB-A-2025111"],
                         "severity": "high",
                         "components": ["com.google.mainline.telemetry"]
                     }],
                     "2022-09-01": [{
                         "cve_identifiers": ["CVE-1236-4321"],
-                        "asb_identifiers": ["ASB-2026111"],
+                        "asb_identifiers": ["ASB-A-2026111"],
                         "severity": "high",
                         "components": ["com.google.mainline.adservices"]
                     }]
@@ -302,7 +302,7 @@
                 "vulnerabilities": {
                     "2023-01-01": [{
                         "cve_identifiers": ["CVE-1234-4321"],
-                        "asb_identifiers": ["ASB-2023111"],
+                        "asb_identifiers": ["ASB-A-2023111"],
                         "severity": "high",
                         "components": ["com.google.android.modulemetadata"]
                     }]
@@ -332,7 +332,7 @@
                 "vulnerabilities": {
                     "2023-05-15": [{
                         "cve_identifiers": ["CVE-5678-1234"],
-                        "asb_identifiers": ["ASB-2024222"],
+                        "asb_identifiers": ["ASB-A-2024222"],
                         "severity": "critical",
                         "components": ["vendor"]
                     }]
@@ -361,7 +361,7 @@
                 "vulnerabilities": {
                     "2023-05-15": [{
                         "cve_identifiers": ["CVE-5678-1234"],
-                        "asb_identifiers": ["ASB-2024222"],
+                        "asb_identifiers": ["ASB-A-2024222"],
                         "severity": "critical",
                         "components": ["vendor"]
                     }]
@@ -437,7 +437,7 @@
                 "vulnerabilities": {
                     "$date": [{
                         "cve_identifiers": ["CVE-1234-6789"],
-                        "asb_identifiers": ["ASB-2023333"],
+                        "asb_identifiers": ["ASB-A-2023333"],
                         "severity": "high",
                         "components": ["$component"]
                     }]
@@ -478,13 +478,13 @@
                 "vulnerabilities": {
                     "2023-01-01": [{
                         "cve_identifiers": ["CVE-2023-0001", "CVE-2023-0002"],
-                        "asb_identifiers": ["ASB-2023011"],
+                        "asb_identifiers": ["ASB-A-2023011"],
                         "severity": "high",
                         "components": ["system"]
                     }],
                     "2023-01-15": [{
                         "cve_identifiers": ["CVE-2023-0010"],
-                        "asb_identifiers": ["ASB-2023022"],
+                        "asb_identifiers": ["ASB-A-2023022"],
                         "severity": "moderate",
                         "components": ["vendor"]
                     }]
@@ -655,19 +655,19 @@
                 "vulnerabilities": {
                     "2023-05-01": [{
                         "cve_identifiers": ["CVE-1234-4321"],
-                        "asb_identifiers": ["ASB-2023111"],
+                        "asb_identifiers": ["ASB-A-2023111"],
                         "severity": "high",
                         "components": ["com.google.android.modulemetadata"]
                     }],
                     "2023-01-01": [{
                         "cve_identifiers": ["CVE-1234-1321"],
-                        "asb_identifiers": ["ASB-2023121"],
+                        "asb_identifiers": ["ASB-A-2023121"],
                         "severity": "critical",
                         "components": ["system"]
                     }],
                     "2023-02-01": [{
                         "cve_identifiers": ["CVE-1234-3321"],
-                        "asb_identifiers": ["ASB-2023151"],
+                        "asb_identifiers": ["ASB-A-2023151"],
                         "severity": "moderate",
                         "components": ["vendor"]
                     }]
@@ -697,19 +697,19 @@
                 "vulnerabilities": {
                     "2023-05-01": [{
                         "cve_identifiers": ["CVE-1234-4321"],
-                        "asb_identifiers": ["ASB-2023111"],
+                        "asb_identifiers": ["ASB-A-2023111"],
                         "severity": "high",
                         "components": ["com.google.android.modulemetadata"]
                     }],
                     "2024-05-01": [{
                         "cve_identifiers": ["CVE-1234-4321"],
-                        "asb_identifiers": ["ASB-2023111"],
+                        "asb_identifiers": ["ASB-A-2023111"],
                         "severity": "high",
                         "components": ["com.google.android.modulemetadata"]
                     }],
                     "2023-01-01": [{
                         "cve_identifiers": ["CVE-1234-1321"],
-                        "asb_identifiers": ["ASB-2023121"],
+                        "asb_identifiers": ["ASB-A-2023121"],
                         "severity": "critical",
                         "components": ["system"]
                     }]
@@ -732,19 +732,19 @@
                 "vulnerabilities": {
                     "2023-05-01": [{
                         "cve_identifiers": ["CVE-1234-4321"],
-                        "asb_identifiers": ["ASB-2023111"],
+                        "asb_identifiers": ["ASB-A-2023111"],
                         "severity": "high",
                         "components": ["com.google.android.modulemetadata"]
                     }],
                     "2023-01-01": [{
                         "cve_identifiers": ["CVE-2023-0001", "CVE-2023-0002"],
-                        "asb_identifiers": ["ASB-2023011"],
+                        "asb_identifiers": ["ASB-A-2023011"],
                         "severity": "high",
                         "components": ["system"]
                     }],
                     "2023-01-15": [{
                         "cve_identifiers": ["CVE-2023-0010"],
-                        "asb_identifiers": ["ASB-2023022"],
+                        "asb_identifiers": ["ASB-A-2023022"],
                         "severity": "moderate",
                         "components": ["vendor"]
                     }]
@@ -777,19 +777,19 @@
                 "vulnerabilities": {
                     "2021-05-01": [{
                         "cve_identifiers": ["CVE-1234-4321"],
-                        "asb_identifiers": ["ASB-2023111"],
+                        "asb_identifiers": ["ASB-A-2023111"],
                         "severity": "high",
                         "components": ["com.google.android.modulemetadata"]
                     }],
                     "2022-01-01": [{
                         "cve_identifiers": ["CVE-2023-0001", "CVE-2023-0002"],
-                        "asb_identifiers": ["ASB-2023011"],
+                        "asb_identifiers": ["ASB-A-2023011"],
                         "severity": "high",
                         "components": ["system"]
                     }],
                     "2021-01-15": [{
                         "cve_identifiers": ["CVE-2023-0010"],
-                        "asb_identifiers": ["ASB-2023022"],
+                        "asb_identifiers": ["ASB-A-2023022"],
                         "severity": "moderate",
                         "components": ["vendor"]
                     }]
@@ -822,19 +822,19 @@
                 "vulnerabilities": {
                     "2021-05-01": [{
                         "cve_identifiers": ["CVE-1234-4321"],
-                        "asb_identifiers": ["ASB-2023111"],
+                        "asb_identifiers": ["ASB-A-2023111"],
                         "severity": "high",
                         "components": ["com.google.android.modulemetadata"]
                     }],
                     "2022-01-01": [{
                         "cve_identifiers": ["CVE-2023-0001", "CVE-2023-0002"],
-                        "asb_identifiers": ["ASB-2023011"],
+                        "asb_identifiers": ["ASB-A-2023011"],
                         "severity": "high",
                         "components": ["system"]
                     }],
                     "2021-01-15": [{
                         "cve_identifiers": ["CVE-2023-0010"],
-                        "asb_identifiers": ["ASB-2023022"],
+                        "asb_identifiers": ["ASB-A-2023022"],
                         "severity": "moderate",
                         "components": ["vendor"]
                     }]
diff --git a/settings.gradle b/settings.gradle
index 53dc676..3006362 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -887,7 +887,7 @@
 includeProject(":room:room-gradle-plugin", [BuildType.MAIN])
 includeProject(":room:room-ktx", [BuildType.MAIN, BuildType.COMPOSE])
 includeProject(":room:room-migration", [BuildType.MAIN, BuildType.COMPOSE, BuildType.KMP, BuildType.INFRAROGUE])
-includeProject(":room:room-paging", [BuildType.MAIN, BuildType.COMPOSE])
+includeProject(":room:room-paging", [BuildType.MAIN, BuildType.COMPOSE, BuildType.KMP, BuildType.INFRAROGUE])
 includeProject(":room:room-paging-guava", [BuildType.MAIN])
 includeProject(":room:room-paging-rxjava2", [BuildType.MAIN])
 includeProject(":room:room-paging-rxjava3", [BuildType.MAIN])
diff --git a/sqlite/sqlite-bundled/api/api_lint.ignore b/sqlite/sqlite-bundled/api/api_lint.ignore
index 499ebfc..1ad4322 100644
--- a/sqlite/sqlite-bundled/api/api_lint.ignore
+++ b/sqlite/sqlite-bundled/api/api_lint.ignore
@@ -1,5 +1,5 @@
 // Baseline format: 1.0
+AcronymName: androidx.sqlite.driver.bundled.BundledSQLite:
+    Acronyms should not be capitalized in class names: was `BundledSQLite`, should this be `BundledSqLite`?
 AcronymName: androidx.sqlite.driver.bundled.BundledSQLiteDriver:
     Acronyms should not be capitalized in class names: was `BundledSQLiteDriver`, should this be `BundledSqLiteDriver`?
-AcronymName: androidx.sqlite.driver.bundled.BundledSQLiteKt:
-    Acronyms should not be capitalized in class names: was `BundledSQLiteKt`, should this be `BundledSqLiteKt`?
diff --git a/sqlite/sqlite-bundled/api/current.txt b/sqlite/sqlite-bundled/api/current.txt
index 68a2651..f739ac9 100644
--- a/sqlite/sqlite-bundled/api/current.txt
+++ b/sqlite/sqlite-bundled/api/current.txt
@@ -1,13 +1,7 @@
 // Signature format: 4.0
 package androidx.sqlite.driver.bundled {
 
-  public final class BundledSQLiteDriver implements androidx.sqlite.SQLiteDriver {
-    ctor public BundledSQLiteDriver();
-    method public androidx.sqlite.SQLiteConnection open(String fileName);
-    method public androidx.sqlite.SQLiteConnection open(String fileName, int flags);
-  }
-
-  public final class BundledSQLiteKt {
+  public final class BundledSQLite {
     field public static final int SQLITE_OPEN_CREATE = 4; // 0x4
     field public static final int SQLITE_OPEN_EXRESCODE = 33554432; // 0x2000000
     field public static final int SQLITE_OPEN_FULLMUTEX = 65536; // 0x10000
@@ -19,5 +13,11 @@
     field public static final int SQLITE_OPEN_URI = 64; // 0x40
   }
 
+  public final class BundledSQLiteDriver implements androidx.sqlite.SQLiteDriver {
+    ctor public BundledSQLiteDriver();
+    method public androidx.sqlite.SQLiteConnection open(String fileName);
+    method public androidx.sqlite.SQLiteConnection open(String fileName, int flags);
+  }
+
 }
 
diff --git a/sqlite/sqlite-bundled/api/restricted_current.txt b/sqlite/sqlite-bundled/api/restricted_current.txt
index 615c210..1407e9c 100644
--- a/sqlite/sqlite-bundled/api/restricted_current.txt
+++ b/sqlite/sqlite-bundled/api/restricted_current.txt
@@ -1,15 +1,7 @@
 // Signature format: 4.0
 package androidx.sqlite.driver.bundled {
 
-  public final class BundledSQLiteDriver implements androidx.sqlite.SQLiteDriver {
-    ctor public BundledSQLiteDriver();
-    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public int getThreadingMode();
-    method public androidx.sqlite.SQLiteConnection open(String fileName);
-    method public androidx.sqlite.SQLiteConnection open(String fileName, int flags);
-    property @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final int threadingMode;
-  }
-
-  public final class BundledSQLiteKt {
+  public final class BundledSQLite {
     field public static final int SQLITE_OPEN_CREATE = 4; // 0x4
     field public static final int SQLITE_OPEN_EXRESCODE = 33554432; // 0x2000000
     field public static final int SQLITE_OPEN_FULLMUTEX = 65536; // 0x10000
@@ -21,5 +13,13 @@
     field public static final int SQLITE_OPEN_URI = 64; // 0x40
   }
 
+  public final class BundledSQLiteDriver implements androidx.sqlite.SQLiteDriver {
+    ctor public BundledSQLiteDriver();
+    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public int getThreadingMode();
+    method public androidx.sqlite.SQLiteConnection open(String fileName);
+    method public androidx.sqlite.SQLiteConnection open(String fileName, int flags);
+    property @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final int threadingMode;
+  }
+
 }
 
diff --git a/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.kt b/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.kt
index 3b13d5e..6adf9ca 100644
--- a/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.kt
+++ b/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.kt
@@ -14,10 +14,13 @@
  * limitations under the License.
  */
 
+@file:JvmName("BundledSQLite")
+
 package androidx.sqlite.driver.bundled
 
 import androidx.annotation.IntDef
 import androidx.annotation.RestrictTo
+import kotlin.jvm.JvmName
 
 /** Opens the database in read-only mode. */
 const val SQLITE_OPEN_READONLY = 0x00000001
diff --git a/sqlite/sqlite-framework/api/restricted_current.txt b/sqlite/sqlite-framework/api/restricted_current.txt
index cc962ad..2a96c29 100644
--- a/sqlite/sqlite-framework/api/restricted_current.txt
+++ b/sqlite/sqlite-framework/api/restricted_current.txt
@@ -10,6 +10,14 @@
 
 package androidx.sqlite.driver {
 
+  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final class AndroidSQLiteConnection implements androidx.sqlite.SQLiteConnection {
+    ctor public AndroidSQLiteConnection(android.database.sqlite.SQLiteDatabase db);
+    method public void close();
+    method public android.database.sqlite.SQLiteDatabase getDb();
+    method public androidx.sqlite.SQLiteStatement prepare(String sql);
+    property public final android.database.sqlite.SQLiteDatabase db;
+  }
+
   public final class AndroidSQLiteDriver implements androidx.sqlite.SQLiteDriver {
     ctor public AndroidSQLiteDriver();
     method public androidx.sqlite.SQLiteConnection open(String fileName);
diff --git a/sqlite/sqlite-framework/src/androidInstrumentedTest/kotlin/androidx/sqlite/db/framework/OpenHelperRecoveryTest.kt b/sqlite/sqlite-framework/src/androidInstrumentedTest/kotlin/androidx/sqlite/db/framework/OpenHelperRecoveryTest.kt
index 0a8ab16..7056a4d 100644
--- a/sqlite/sqlite-framework/src/androidInstrumentedTest/kotlin/androidx/sqlite/db/framework/OpenHelperRecoveryTest.kt
+++ b/sqlite/sqlite-framework/src/androidInstrumentedTest/kotlin/androidx/sqlite/db/framework/OpenHelperRecoveryTest.kt
@@ -286,6 +286,38 @@
     }
 
     @Test
+    fun noAllowDataLossOnRecovery_onOpenSQLiteError() {
+        var openAttempts = 0
+        val badCallback =
+            object : SupportSQLiteOpenHelper.Callback(1) {
+                override fun onCreate(db: SupportSQLiteDatabase) {}
+
+                override fun onUpgrade(
+                    db: SupportSQLiteDatabase,
+                    oldVersion: Int,
+                    newVersion: Int
+                ) {}
+
+                override fun onOpen(db: SupportSQLiteDatabase) {
+                    openAttempts++
+                    db.execSQL("SELECT * FROM bad_table")
+                }
+            }
+        // FrameworkSQLiteOpenHelper will attempt to open the database twice, but if it can't
+        // and with allowDataLossOnRecovery == false, then it shouldn't recover by deleting the
+        // database and the error should be thrown.
+        val openHelper = FrameworkSQLiteOpenHelper(context, dbName, badCallback, false, false)
+        try {
+            openHelper.writableDatabase
+            fail("Database should have failed to open.")
+        } catch (ex: SQLiteException) {
+            // Expected
+            assertThat(ex.message).contains("no such table: bad_table")
+        }
+        assertThat(openAttempts).isEqualTo(2)
+    }
+
+    @Test
     fun allowDataLossOnRecovery_onOpenRecursive() {
         var openHelper: FrameworkSQLiteOpenHelper? = null
         val badCallback =
diff --git a/sqlite/sqlite-framework/src/androidMain/kotlin/androidx/sqlite/db/framework/FrameworkSQLiteOpenHelper.android.kt b/sqlite/sqlite-framework/src/androidMain/kotlin/androidx/sqlite/db/framework/FrameworkSQLiteOpenHelper.android.kt
index bb8f0395..2db2847 100644
--- a/sqlite/sqlite-framework/src/androidMain/kotlin/androidx/sqlite/db/framework/FrameworkSQLiteOpenHelper.android.kt
+++ b/sqlite/sqlite-framework/src/androidMain/kotlin/androidx/sqlite/db/framework/FrameworkSQLiteOpenHelper.android.kt
@@ -175,14 +175,15 @@
             } catch (e: InterruptedException) {
                 // Ignore, and continue
             }
-            val openRetryError: Throwable =
+            var openRetryError: Throwable =
                 try {
                     return getWritableOrReadableDatabase(writable)
                 } catch (t: Throwable) {
                     t
                 }
+
+            // Callback error (onCreate, onUpgrade, onOpen, etc), possibly user error.
             if (openRetryError is CallbackException) {
-                // Callback error (onCreate, onUpgrade, onOpen, etc), possibly user error.
                 val cause = openRetryError.cause
                 when (openRetryError.callbackName) {
                     CallbackName.ON_CONFIGURE,
@@ -192,17 +193,19 @@
                     CallbackName.ON_OPEN -> {}
                 }
                 // If callback exception is not an SQLiteException, then more certainly it is not
-                // recoverable.
+                // recoverable, rethrow.
                 if (cause !is SQLiteException) {
                     throw cause
                 }
-            } else if (openRetryError is SQLiteException) {
-                // Ideally we are looking for SQLiteCantOpenDatabaseException and similar, but
-                // corruption can manifest in others forms.
-                if (name == null || !allowDataLossOnRecovery) {
-                    throw openRetryError
-                }
-            } else {
+                // Exception in callback is a SQLiteException, might be recoverable.
+                openRetryError = cause
+            }
+
+            // Ideally we are looking for SQLiteCantOpenDatabaseException and similar, but
+            // corruption can manifest in others forms so check if error is SQLiteException as
+            // that might be recoverable, unless it's an in-memory database or data loss is not
+            // allowed.
+            if (openRetryError !is SQLiteException || name == null || !allowDataLossOnRecovery) {
                 throw openRetryError
             }
 
diff --git a/sqlite/sqlite-framework/src/androidMain/kotlin/androidx/sqlite/driver/AndroidSQLiteConnection.android.kt b/sqlite/sqlite-framework/src/androidMain/kotlin/androidx/sqlite/driver/AndroidSQLiteConnection.android.kt
index 8e8cba8..375a279 100644
--- a/sqlite/sqlite-framework/src/androidMain/kotlin/androidx/sqlite/driver/AndroidSQLiteConnection.android.kt
+++ b/sqlite/sqlite-framework/src/androidMain/kotlin/androidx/sqlite/driver/AndroidSQLiteConnection.android.kt
@@ -17,12 +17,14 @@
 package androidx.sqlite.driver
 
 import android.database.sqlite.SQLiteDatabase
+import androidx.annotation.RestrictTo
 import androidx.sqlite.SQLiteConnection
 import androidx.sqlite.SQLiteStatement
 import androidx.sqlite.driver.ResultCode.SQLITE_MISUSE
 import androidx.sqlite.throwSQLiteException
 
-internal class AndroidSQLiteConnection(private val db: SQLiteDatabase) : SQLiteConnection {
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+class AndroidSQLiteConnection(val db: SQLiteDatabase) : SQLiteConnection {
     override fun prepare(sql: String): SQLiteStatement {
         if (db.isOpen) {
             return AndroidSQLiteStatement.create(db, sql)
diff --git a/sqlite/sqlite-ktx/src/main/java/androidx/sqlite/db/SupportSQLiteDatabaseExt.kt b/sqlite/sqlite-ktx/src/main/java/androidx/sqlite/db/SupportSQLiteDatabaseExt.kt
index 7eb48e3..e637a991 100644
--- a/sqlite/sqlite-ktx/src/main/java/androidx/sqlite/db/SupportSQLiteDatabaseExt.kt
+++ b/sqlite/sqlite-ktx/src/main/java/androidx/sqlite/db/SupportSQLiteDatabaseExt.kt
@@ -21,6 +21,7 @@
  * Run [body] in a transaction marking it as successful if it completes without exception.
  *
  * @param exclusive Run in `EXCLUSIVE` mode when true, `IMMEDIATE` mode otherwise.
+ * @param body Lambda to be run in the transaction.
  */
 inline fun <T> SupportSQLiteDatabase.transaction(
     exclusive: Boolean = true,
diff --git a/sqlite/sqlite/api/api_lint.ignore b/sqlite/sqlite/api/api_lint.ignore
index 04d9864..cd89a2c 100644
--- a/sqlite/sqlite/api/api_lint.ignore
+++ b/sqlite/sqlite/api/api_lint.ignore
@@ -1,36 +1,4 @@
 // Baseline format: 1.0
-AcronymName: androidx.sqlite.SQLiteConnection:
-    Acronyms should not be capitalized in class names: was `SQLiteConnection`, should this be `SqLiteConnection`?
-AcronymName: androidx.sqlite.SQLiteDriver:
-    Acronyms should not be capitalized in class names: was `SQLiteDriver`, should this be `SqLiteDriver`?
-AcronymName: androidx.sqlite.SQLiteKt:
-    Acronyms should not be capitalized in class names: was `SQLiteKt`, should this be `SqLiteKt`?
-AcronymName: androidx.sqlite.SQLiteKt#execSQL(androidx.sqlite.SQLiteConnection, String):
-    Acronyms should not be capitalized in method names: was `execSQL`, should this be `execSql`?
-AcronymName: androidx.sqlite.SQLiteKt#throwSQLiteException(int, String):
-    Acronyms should not be capitalized in method names: was `throwSQLiteException`, should this be `throwSqLiteException`?
-AcronymName: androidx.sqlite.SQLiteStatement:
-    Acronyms should not be capitalized in class names: was `SQLiteStatement`, should this be `SqLiteStatement`?
-AcronymName: androidx.sqlite.db.SimpleSQLiteQuery:
-    Acronyms should not be capitalized in class names: was `SimpleSQLiteQuery`, should this be `SimpleSqLiteQuery`?
-AcronymName: androidx.sqlite.db.SupportSQLiteDatabase:
-    Acronyms should not be capitalized in class names: was `SupportSQLiteDatabase`, should this be `SupportSqLiteDatabase`?
-AcronymName: androidx.sqlite.db.SupportSQLiteDatabase#execSQL(String):
-    Acronyms should not be capitalized in method names: was `execSQL`, should this be `execSql`?
-AcronymName: androidx.sqlite.db.SupportSQLiteDatabase#execSQL(String, Object[]):
-    Acronyms should not be capitalized in method names: was `execSQL`, should this be `execSql`?
-AcronymName: androidx.sqlite.db.SupportSQLiteOpenHelper:
-    Acronyms should not be capitalized in class names: was `SupportSQLiteOpenHelper`, should this be `SupportSqLiteOpenHelper`?
-AcronymName: androidx.sqlite.db.SupportSQLiteProgram:
-    Acronyms should not be capitalized in class names: was `SupportSQLiteProgram`, should this be `SupportSqLiteProgram`?
-AcronymName: androidx.sqlite.db.SupportSQLiteQuery:
-    Acronyms should not be capitalized in class names: was `SupportSQLiteQuery`, should this be `SupportSqLiteQuery`?
-AcronymName: androidx.sqlite.db.SupportSQLiteQueryBuilder:
-    Acronyms should not be capitalized in class names: was `SupportSQLiteQueryBuilder`, should this be `SupportSqLiteQueryBuilder`?
-AcronymName: androidx.sqlite.db.SupportSQLiteStatement:
-    Acronyms should not be capitalized in class names: was `SupportSQLiteStatement`, should this be `SupportSqLiteStatement`?
-
-
 ArrayReturn: androidx.sqlite.db.SupportSQLiteDatabase#delete(String, String, Object[]) parameter #2:
     Method parameter should be Collection<Object> (or subclass) instead of raw array; was `java.lang.Object[]`
 ArrayReturn: androidx.sqlite.db.SupportSQLiteDatabase#execSQL(String, Object[]) parameter #1:
diff --git a/sqlite/sqlite/api/current.txt b/sqlite/sqlite/api/current.txt
index 0ab19f2..cf865c2 100644
--- a/sqlite/sqlite/api/current.txt
+++ b/sqlite/sqlite/api/current.txt
@@ -1,6 +1,12 @@
 // Signature format: 4.0
 package androidx.sqlite {
 
+  public final class SQLite {
+    method public static void execSQL(androidx.sqlite.SQLiteConnection, String sql);
+    method public static Void throwSQLiteException(int errorCode, String? errorMsg);
+    method public static inline <R> R use(androidx.sqlite.SQLiteStatement, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteStatement,? extends R> block);
+  }
+
   public interface SQLiteConnection {
     method public void close();
     method public androidx.sqlite.SQLiteStatement prepare(String sql);
@@ -10,12 +16,6 @@
     method public androidx.sqlite.SQLiteConnection open(String fileName);
   }
 
-  public final class SQLiteKt {
-    method public static void execSQL(androidx.sqlite.SQLiteConnection, String sql);
-    method public static Void throwSQLiteException(int errorCode, String? errorMsg);
-    method public static inline <R> R use(androidx.sqlite.SQLiteStatement, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteStatement,? extends R> block);
-  }
-
   public interface SQLiteStatement {
     method public void bindBlob(int index, byte[] value);
     method public default void bindBoolean(int index, boolean value);
diff --git a/sqlite/sqlite/api/restricted_current.txt b/sqlite/sqlite/api/restricted_current.txt
index 0ab19f2..cf865c2 100644
--- a/sqlite/sqlite/api/restricted_current.txt
+++ b/sqlite/sqlite/api/restricted_current.txt
@@ -1,6 +1,12 @@
 // Signature format: 4.0
 package androidx.sqlite {
 
+  public final class SQLite {
+    method public static void execSQL(androidx.sqlite.SQLiteConnection, String sql);
+    method public static Void throwSQLiteException(int errorCode, String? errorMsg);
+    method public static inline <R> R use(androidx.sqlite.SQLiteStatement, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteStatement,? extends R> block);
+  }
+
   public interface SQLiteConnection {
     method public void close();
     method public androidx.sqlite.SQLiteStatement prepare(String sql);
@@ -10,12 +16,6 @@
     method public androidx.sqlite.SQLiteConnection open(String fileName);
   }
 
-  public final class SQLiteKt {
-    method public static void execSQL(androidx.sqlite.SQLiteConnection, String sql);
-    method public static Void throwSQLiteException(int errorCode, String? errorMsg);
-    method public static inline <R> R use(androidx.sqlite.SQLiteStatement, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteStatement,? extends R> block);
-  }
-
   public interface SQLiteStatement {
     method public void bindBlob(int index, byte[] value);
     method public default void bindBoolean(int index, boolean value);
diff --git a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SimpleSQLiteQuery.android.kt b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SimpleSQLiteQuery.android.kt
index 34a74e6..bbe86d9 100644
--- a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SimpleSQLiteQuery.android.kt
+++ b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SimpleSQLiteQuery.android.kt
@@ -23,6 +23,7 @@
  * @param bindArgs The bind argument value that will replace the placeholders in the query.
  * @constructor Creates an SQL query with the sql string and the bind arguments.
  */
+@Suppress("AcronymName") // SQL is a known term and should remain capitalized
 class SimpleSQLiteQuery(
     private val query: String,
     @Suppress("ArrayReturn") // Due to legacy API
@@ -44,6 +45,7 @@
      *
      * @param [statement] The SQL query to execute. Cannot include bind parameters.
      */
+    @Suppress("AcronymName") // SQL is a known term and should remain capitalized
     override fun bindTo(statement: SupportSQLiteProgram) {
         bind(statement, bindArgs)
     }
@@ -60,6 +62,7 @@
          */
         @JvmStatic
         fun bind(
+            @Suppress("AcronymName") // SQL is a known term and should remain capitalized
             statement: SupportSQLiteProgram,
             @Suppress("ArrayReturn") // Due to legacy API
             bindArgs: Array<out Any?>?
@@ -75,7 +78,12 @@
             }
         }
 
-        private fun bind(statement: SupportSQLiteProgram, index: Int, arg: Any?) {
+        private fun bind(
+            @Suppress("AcronymName") // SQL is a known term and should remain capitalized
+            statement: SupportSQLiteProgram,
+            index: Int,
+            arg: Any?
+        ) {
             // extracted from android.database.sqlite.SQLiteConnection
             if (arg == null) {
                 statement.bindNull(index)
diff --git a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteDatabase.android.kt b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteDatabase.android.kt
index 25693ea..4f4e98c 100644
--- a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteDatabase.android.kt
+++ b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteDatabase.android.kt
@@ -29,6 +29,7 @@
  * A database abstraction which removes the framework dependency and allows swapping underlying sql
  * versions. It mimics the behavior of [android.database.sqlite.SQLiteDatabase]
  */
+@Suppress("AcronymName") // SQL is a known term and should remain capitalized
 interface SupportSQLiteDatabase : Closeable {
     /**
      * Compiles the given SQL statement.
@@ -417,7 +418,9 @@
      *   not supported.
      * @throws SQLException if the SQL string is invalid
      */
-    @Throws(SQLException::class) fun execSQL(sql: String)
+    @Suppress("AcronymName") // SQL is a known term and should remain capitalized
+    @Throws(SQLException::class)
+    fun execSQL(sql: String)
 
     /**
      * Execute a single SQL statement that does not return any data.
@@ -431,7 +434,9 @@
      * @param bindArgs only byte[], String, Long and Double are supported in selectionArgs.
      * @throws SQLException if the SQL string is invalid
      */
-    @Throws(SQLException::class) fun execSQL(sql: String, bindArgs: Array<out Any?>)
+    @Suppress("AcronymName") // SQL is a known term and should remain capitalized
+    @Throws(SQLException::class)
+    fun execSQL(sql: String, bindArgs: Array<out Any?>)
 
     /** Is true if the database is opened as read only. */
     val isReadOnly: Boolean
diff --git a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteOpenHelper.android.kt b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteOpenHelper.android.kt
index 7882a3a..90aee80 100644
--- a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteOpenHelper.android.kt
+++ b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteOpenHelper.android.kt
@@ -31,6 +31,7 @@
  * that class requires overriding certain methods, support implementation uses [Factory.create] to
  * create this and [Callback] to implement the methods that should be overridden.
  */
+@Suppress("AcronymName") // SQL is a known term and should remain capitalized
 interface SupportSQLiteOpenHelper : Closeable {
     /**
      * Return the name of the SQLite database being opened, as given to the constructor. `null`
diff --git a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteProgram.android.kt b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteProgram.android.kt
index 37bd205..9bff8c4 100644
--- a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteProgram.android.kt
+++ b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteProgram.android.kt
@@ -18,6 +18,7 @@
 import java.io.Closeable
 
 /** An interface to map the behavior of [android.database.sqlite.SQLiteProgram]. */
+@Suppress("AcronymName") // SQL is a known term and should remain capitalized
 interface SupportSQLiteProgram : Closeable {
     /**
      * Bind a NULL value to this statement. The value remains bound until [.clearBindings] is
diff --git a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteQuery.android.kt b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteQuery.android.kt
index 2184bd1..b5ffb7e 100644
--- a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteQuery.android.kt
+++ b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteQuery.android.kt
@@ -19,6 +19,7 @@
  * A query with typed bindings. It is better to use this API instead of
  * [android.database.sqlite.SQLiteDatabase.rawQuery] because it allows binding type safe parameters.
  */
+@Suppress("AcronymName") // SQL is a known term and should remain capitalized
 interface SupportSQLiteQuery {
     /** The SQL query. This query can have placeholders(?) for bind arguments. */
     val sql: String
diff --git a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteQueryBuilder.android.kt b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteQueryBuilder.android.kt
index c319f2b..60f5817 100644
--- a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteQueryBuilder.android.kt
+++ b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteQueryBuilder.android.kt
@@ -18,6 +18,7 @@
 import java.util.regex.Pattern
 
 /** A simple query builder to create SQL SELECT queries. */
+@Suppress("AcronymName") // SQL is a known term and should remain capitalized
 class SupportSQLiteQueryBuilder private constructor(private val table: String) {
     private var distinct = false
     private var columns: Array<out String>? = null
diff --git a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteStatement.android.kt b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteStatement.android.kt
index 9be3fd5..829612c 100644
--- a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteStatement.android.kt
+++ b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteStatement.android.kt
@@ -16,6 +16,7 @@
 package androidx.sqlite.db
 
 /** An interface to map the behavior of [android.database.sqlite.SQLiteStatement]. */
+@Suppress("AcronymName") // SQL is a known term and should remain capitalized
 interface SupportSQLiteStatement : SupportSQLiteProgram {
     /**
      * Execute this SQL statement, if it is not a SELECT / INSERT / DELETE / UPDATE, for example
diff --git a/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLite.kt b/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLite.kt
index a350133..b997417 100644
--- a/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLite.kt
+++ b/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLite.kt
@@ -13,16 +13,22 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+@file:Suppress("AcronymName") // SQL is a known term and should remain capitalized
+@file:JvmName("SQLite")
 
 package androidx.sqlite
 
+import kotlin.jvm.JvmName
+
 /** Executes a single SQL statement that returns no values. */
+@Suppress("AcronymName") // SQL is a known term and should remain capitalized
 fun SQLiteConnection.execSQL(sql: String) {
     prepare(sql).use { it.step() }
 }
 
 /** Use the receiver statement within the [block] and closes it once it is done. */
 // TODO(b/315461431): Migrate to a Closeable interface in KMP
+@Suppress("AcronymName") // SQL is a known term and should remain capitalized
 inline fun <R> SQLiteStatement.use(block: (SQLiteStatement) -> R): R {
     try {
         return block.invoke(this)
@@ -32,6 +38,7 @@
 }
 
 /** Throws a [SQLiteException] with its message formed by the given [errorCode] amd [errorMsg]. */
+@Suppress("AcronymName") // SQL is a known term and should remain capitalized
 fun throwSQLiteException(errorCode: Int, errorMsg: String?): Nothing {
     val message = buildString {
         append("Error code: $errorCode")
diff --git a/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteConnection.kt b/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteConnection.kt
index 27b1e3c..5922ca2 100644
--- a/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteConnection.kt
+++ b/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteConnection.kt
@@ -24,7 +24,8 @@
  *
  * See also [Database Connection](https://www.sqlite.org/c3ref/sqlite3.html)
  */
-@Suppress("NotCloseable") // TODO(b/315461431): No common Closeable interface in KMP
+// TODO(b/315461431): No common Closeable interface in KMP
+@Suppress("NotCloseable", "AcronymName") // SQL is a known term and should remain capitalized
 interface SQLiteConnection {
     /**
      * Prepares a new SQL statement.
diff --git a/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteDriver.kt b/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteDriver.kt
index a960ac7..a0fa75c 100644
--- a/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteDriver.kt
+++ b/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteDriver.kt
@@ -17,6 +17,7 @@
 package androidx.sqlite
 
 /** An interface to open database connections. */
+@Suppress("AcronymName") // SQL is a known term and should remain capitalized
 interface SQLiteDriver {
     /**
      * Opens a new database connection.
diff --git a/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteStatement.kt b/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteStatement.kt
index d987daf..039d211 100644
--- a/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteStatement.kt
+++ b/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteStatement.kt
@@ -24,7 +24,8 @@
  *
  * See also [Prepared Statement](https://www.sqlite.org/c3ref/stmt.html)
  */
-@Suppress("NotCloseable") // TODO(b/315461431): No common Closeable interface in KMP
+// TODO(b/315461431): No common Closeable interface in KMP
+@Suppress("NotCloseable", "AcronymName") // SQL is a known term and should remain capitalized
 interface SQLiteStatement {
     /**
      * Binds a ByteArray value to this statement at an index.
diff --git a/stableaidl/stableaidl-gradle-plugin/build.gradle b/stableaidl/stableaidl-gradle-plugin/build.gradle
index 13fded7..4518da8 100644
--- a/stableaidl/stableaidl-gradle-plugin/build.gradle
+++ b/stableaidl/stableaidl-gradle-plugin/build.gradle
@@ -40,15 +40,17 @@
 }
 
 dependencies {
-    implementation(findGradleKotlinDsl())
+    runtimeOnly(findGradleKotlinDsl())
+
+    api(libs.androidGradlePluginApi)
+    api(libs.androidToolsCommon)
+    api(libs.androidToolsSdkCommon)
+    api(libs.guava)
+
     implementation(gradleApi())
-    implementation(libs.androidGradlePluginApi)
-    implementation(libs.androidToolsCommon)
     implementation(libs.androidToolsRepository)
-    implementation(libs.androidToolsSdkCommon)
     implementation(libs.apacheCommonIo)
     implementation(libs.apacheAnt)
-    implementation(libs.guava)
     implementation(libs.kotlinStdlib)
 
     testPlugin(libs.androidGradlePluginz)
@@ -57,9 +59,11 @@
     testImplementation(gradleTestKit())
     testImplementation(project(":internal-testutils-gradle-plugin"))
     testImplementation(libs.androidToolsAnalyticsProtos)
-    testImplementation(libs.gson)
+    testImplementation(libs.asm)
+    testImplementation(libs.builder)
     testImplementation(libs.junit)
     testImplementation(libs.kotlinTest)
+    testImplementation(libs.gson)
     testImplementation(libs.truth)
 }
 
diff --git a/test/uiautomator/integration-tests/testapp/build.gradle b/test/uiautomator/integration-tests/testapp/build.gradle
index 0efa882..eed2f10 100644
--- a/test/uiautomator/integration-tests/testapp/build.gradle
+++ b/test/uiautomator/integration-tests/testapp/build.gradle
@@ -23,16 +23,19 @@
 
 dependencies {
     implementation(libs.kotlinStdlib)
-
-    implementation("androidx.annotation:annotation:1.4.0")
+    implementation(libs.androidx.annotation)
     implementation("androidx.core:core:1.6.0")
 
+    implementation project(":activity:activity")
     implementation(project(":activity:activity-compose"))
+    implementation project(":compose:foundation:foundation")
+    implementation(project(":compose:foundation:foundation-layout"))
     implementation(project(":compose:material:material"))
-    implementation(project(":compose:animation:animation"))
     implementation(project(":compose:runtime:runtime"))
     implementation(project(":compose:ui:ui"))
-    implementation(project(":compose:foundation:foundation-layout"))
+    implementation project(":compose:ui:ui-graphics")
+    implementation project(":compose:ui:ui-text")
+    implementation project(":compose:ui:ui-unit")
 
     androidTestImplementation(project(":test:uiautomator:uiautomator"))
     androidTestImplementation(libs.testCore)
@@ -40,8 +43,10 @@
     androidTestImplementation(libs.testRunner)
 
     // Align dependencies in debugRuntimeClasspath and debugAndroidTestRuntimeClasspath.
-    androidTestImplementation("androidx.lifecycle:lifecycle-common:2.8.2")
-    androidTestImplementation("androidx.annotation:annotation:1.8.0")
+    androidTestImplementation("androidx.lifecycle:lifecycle-common:2.8.3")
+    androidTestImplementation(project(":annotation:annotation"))
+    androidTestImplementation(libs.junit)
+    androidTestImplementation(libs.testMonitor)
 }
 
 android {
diff --git a/test/uiautomator/uiautomator/build.gradle b/test/uiautomator/uiautomator/build.gradle
index 0079b25..a25a404 100644
--- a/test/uiautomator/uiautomator/build.gradle
+++ b/test/uiautomator/uiautomator/build.gradle
@@ -33,10 +33,13 @@
     implementation("androidx.annotation:annotation:1.4.0")
     implementation("androidx.tracing:tracing:1.1.0")
 
+    androidTestImplementation(libs.mockitoCore)
     androidTestImplementation(libs.testCore)
     androidTestImplementation(libs.testExtJunit)
+    androidTestImplementation(libs.testMonitor)
     androidTestImplementation(libs.testRunner)
-    androidTestImplementation(libs.dexmakerMockitoInline)
+
+    androidTestRuntimeOnly(libs.dexmakerMockitoInline)
 }
 
 android {
diff --git a/text/text/src/androidTest/java/androidx/compose/ui/text/android/TextLayoutIntrinsicWidthTest.kt b/text/text/src/androidTest/java/androidx/compose/ui/text/android/TextLayoutIntrinsicWidthTest.kt
index 733f291..e323215 100644
--- a/text/text/src/androidTest/java/androidx/compose/ui/text/android/TextLayoutIntrinsicWidthTest.kt
+++ b/text/text/src/androidTest/java/androidx/compose/ui/text/android/TextLayoutIntrinsicWidthTest.kt
@@ -169,7 +169,8 @@
                 endIndex = end,
                 trimFirstLineTop = true,
                 trimLastLineBottom = true,
-                topRatio = -1f /* default: proportional */
+                topRatio = -1f /* default: proportional */,
+                preserveMinimumHeight = false,
             )
         setSpan(span, start, end)
     }
diff --git a/text/text/src/androidTest/java/androidx/compose/ui/text/android/TextLayoutTest.kt b/text/text/src/androidTest/java/androidx/compose/ui/text/android/TextLayoutTest.kt
index 0f5b73b..e061576 100644
--- a/text/text/src/androidTest/java/androidx/compose/ui/text/android/TextLayoutTest.kt
+++ b/text/text/src/androidTest/java/androidx/compose/ui/text/android/TextLayoutTest.kt
@@ -369,7 +369,12 @@
         val lineHeight = 60f
 
         val layout =
-            TextLayoutWithSmallLineHeight(text = "aA", fontSize = fontSize, lineHeight = lineHeight)
+            TextLayoutWithSmallLineHeight(
+                text = "aA",
+                fontSize = fontSize,
+                lineHeight = lineHeight,
+                preserveMinimumHeight = false
+            )
 
         val defaultFontMetrics = createTextPaint(fontSize).fontMetricsInt
         val expectedPadding = ((fontSize - lineHeight) / 2).toInt()
@@ -392,7 +397,8 @@
             TextLayoutWithSmallLineHeight(
                 text = "aA\naA\naA",
                 fontSize = fontSize,
-                lineHeight = lineHeight
+                lineHeight = lineHeight,
+                preserveMinimumHeight = false
             )
 
         val defaultFontMetrics = createTextPaint(fontSize).fontMetricsInt
@@ -408,10 +414,37 @@
         assertThat(layout.getLineForVertical(layout.height)).isEqualTo(2)
     }
 
+    @Test
+    fun small_lineheight_prevents_clip_multi_line_preserve_linespacing() {
+        val fontSize = 120f
+        val specifyLineHeight = 60f
+        val systemPreferredLineHeight = 120f
+        val layout =
+            TextLayoutWithSmallLineHeight(
+                text = "aA\naA\naA",
+                fontSize = fontSize,
+                lineHeight = specifyLineHeight,
+                preserveMinimumHeight = true
+            )
+        val defaultFontMetrics = createTextPaint(fontSize).fontMetricsInt
+        val expectedPadding = ((fontSize - systemPreferredLineHeight) / 2).toInt()
+
+        assertThat(layout.topPadding).isEqualTo(expectedPadding)
+        assertThat(layout.bottomPadding).isEqualTo(expectedPadding)
+        assertThat(layout.height)
+            .isEqualTo((3 * systemPreferredLineHeight + 2 * expectedPadding).toInt())
+        assertThat(layout.getLineTop(0)).isEqualTo(0)
+        assertThat(layout.getLineBaseline(0)).isEqualTo(-defaultFontMetrics.ascent)
+        assertThat(layout.getLineForVertical(0)).isEqualTo(0)
+        assertThat(layout.getLineBottom(2)).isEqualTo(layout.height)
+        assertThat(layout.getLineForVertical(layout.height)).isEqualTo(2)
+    }
+
     private fun TextLayoutWithSmallLineHeight(
         text: CharSequence,
         fontSize: Float,
-        lineHeight: Float
+        lineHeight: Float,
+        preserveMinimumHeight: Boolean
     ): TextLayout {
         val textPaint = createTextPaint(fontSize)
         val spannable = SpannableString(text)
@@ -422,7 +455,8 @@
                 endIndex = text.length,
                 trimFirstLineTop = false,
                 trimLastLineBottom = false,
-                topRatio = 0.5f
+                topRatio = 0.5f,
+                preserveMinimumHeight = preserveMinimumHeight,
             ),
             0,
             text.length,
diff --git a/text/text/src/androidTest/java/androidx/compose/ui/text/android/style/LineHeightStyleSpanTest.kt b/text/text/src/androidTest/java/androidx/compose/ui/text/android/style/LineHeightStyleSpanTest.kt
index 425dd152..5a330ef 100644
--- a/text/text/src/androidTest/java/androidx/compose/ui/text/android/style/LineHeightStyleSpanTest.kt
+++ b/text/text/src/androidTest/java/androidx/compose/ui/text/android/style/LineHeightStyleSpanTest.kt
@@ -36,8 +36,7 @@
 @SmallTest
 class LineHeightStyleSpanTest {
 
-    @Test
-    fun negative_line_height_does_not_chage_the_values() {
+    private fun negative_line_height_does_not_chage_the_values(preserve: Boolean) {
         val fontMetrics = FontMetricsInt(ascent = 1, descent = 1)
 
         val newFontMetrics =
@@ -45,17 +44,29 @@
                 topRatio = 0.5f,
                 trimFirstLineTop = false,
                 trimLastLineBottom = false,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         assertThat(newFontMetrics.ascent).isEqualTo(fontMetrics.ascent)
         assertThat(newFontMetrics.descent).isEqualTo(fontMetrics.descent)
     }
 
+    @Test
+    fun negative_line_height_does_not_change_the_values_preserve_no() {
+        negative_line_height_does_not_chage_the_values(false)
+    }
+
+    @Test
+    fun negative_line_height_does_not_change_the_values_preserve_yes() {
+        negative_line_height_does_not_chage_the_values(true)
+    }
+
     /* single line, top percentage 0 */
 
-    @Test
-    fun singleLine_topRatio_0_trimFirstLineTop_false_trimLastLineBottom_false() {
+    private fun singleLine_topRatio_0_trimFirstLineTop_false_trimLastLineBottom_false(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val newFontMetrics =
@@ -63,7 +74,8 @@
                 topRatio = 0f,
                 trimFirstLineTop = false,
                 trimLastLineBottom = false,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         assertThat(newFontMetrics.ascent).isEqualTo(fontMetrics.ascent)
@@ -71,7 +83,18 @@
     }
 
     @Test
-    fun singleLine_topRatio_0_trimFirstLineTop_false_trimLastLineBottom_true() {
+    fun singleLine_topRatio_0_trimFirstLineTop_false_trimLastLineBottom_false_preserve_no() {
+        negative_line_height_does_not_chage_the_values(false)
+    }
+
+    @Test
+    fun singleLine_topRatio_0_trimFirstLineTop_false_trimLastLineBottom_false_preserve_yes() {
+        negative_line_height_does_not_chage_the_values(true)
+    }
+
+    private fun singleLine_topRatio_0_trimFirstLineTop_false_trimLastLineBottom_true(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val newFontMetrics =
@@ -79,7 +102,8 @@
                 topRatio = 0f,
                 trimFirstLineTop = false,
                 trimLastLineBottom = true,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         assertThat(newFontMetrics.ascent).isEqualTo(fontMetrics.ascent)
@@ -87,7 +111,18 @@
     }
 
     @Test
-    fun singleLine_topRatio_0_trimFirstLineTop_true_trimLastLineBottom_false() {
+    fun singleLine_topRatio_0_trimFirstLineTop_false_trimLastLineBottom_true_preserve_no() {
+        singleLine_topRatio_0_trimFirstLineTop_false_trimLastLineBottom_true(false)
+    }
+
+    @Test
+    fun singleLine_topRatio_0_trimFirstLineTop_false_trimLastLineBottom_true_preserve_yes() {
+        singleLine_topRatio_0_trimFirstLineTop_false_trimLastLineBottom_true(true)
+    }
+
+    private fun singleLine_topRatio_0_trimFirstLineTop_true_trimLastLineBottom_false(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val newFontMetrics =
@@ -95,7 +130,8 @@
                 topRatio = 0f,
                 trimFirstLineTop = true,
                 trimLastLineBottom = false,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         assertThat(newFontMetrics.ascent).isEqualTo(fontMetrics.ascent)
@@ -103,7 +139,18 @@
     }
 
     @Test
-    fun singleLine_topRatio_0_trimFirstLineTop_true_trimLastLineBottom_true() {
+    fun singleLine_topRatio_0_trimFirstLineTop_true_trimLastLineBottom_false_preserve_no() {
+        singleLine_topRatio_0_trimFirstLineTop_true_trimLastLineBottom_false(false)
+    }
+
+    @Test
+    fun singleLine_topRatio_0_trimFirstLineTop_true_trimLastLineBottom_false_preserve_yes() {
+        singleLine_topRatio_0_trimFirstLineTop_true_trimLastLineBottom_false(true)
+    }
+
+    private fun singleLine_topRatio_0_trimFirstLineTop_true_trimLastLineBottom_true(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val newFontMetrics =
@@ -111,17 +158,29 @@
                 topRatio = 0f,
                 trimFirstLineTop = true,
                 trimLastLineBottom = true,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         assertThat(newFontMetrics.ascent).isEqualTo(fontMetrics.ascent)
         assertThat(newFontMetrics.descent).isEqualTo(fontMetrics.descent)
     }
 
+    @Test
+    fun singleLine_topRatio_0_trimFirstLineTop_true_trimLastLineBottom_true_preserve_no() {
+        singleLine_topRatio_0_trimFirstLineTop_true_trimLastLineBottom_true(false)
+    }
+
+    @Test
+    fun singleLine_topRatio_0_trimFirstLineTop_true_trimLastLineBottom_true_preserve_yes() {
+        singleLine_topRatio_0_trimFirstLineTop_true_trimLastLineBottom_true(true)
+    }
+
     /* single line, top percentage 100 */
 
-    @Test
-    fun singleLine_topRatio_100_trimFirstLineTop_false_trimLastLineBottom_false() {
+    private fun singleLine_topRatio_100_trimFirstLineTop_false_trimLastLineBottom_false(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val newFontMetrics =
@@ -129,7 +188,8 @@
                 topRatio = 1f,
                 trimFirstLineTop = false,
                 trimLastLineBottom = false,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         assertThat(newFontMetrics.ascent).isEqualTo(fontMetrics.ascent - fontMetrics.lineHeight())
@@ -137,7 +197,18 @@
     }
 
     @Test
-    fun singleLine_topRatio_100_trimFirstLineTop_false_trimLastLineBottom_true() {
+    fun singleLine_topRatio_100_trimFirstLineTop_false_trimLastLineBottom_false_preserve_no() {
+        singleLine_topRatio_100_trimFirstLineTop_false_trimLastLineBottom_false(false)
+    }
+
+    @Test
+    fun singleLine_topRatio_100_trimFirstLineTop_false_trimLastLineBottom_false_preserve_yes() {
+        singleLine_topRatio_100_trimFirstLineTop_false_trimLastLineBottom_false(true)
+    }
+
+    private fun singleLine_topRatio_100_trimFirstLineTop_false_trimLastLineBottom_true(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val newFontMetrics =
@@ -145,7 +216,8 @@
                 topRatio = 1f,
                 trimFirstLineTop = false,
                 trimLastLineBottom = true,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         assertThat(newFontMetrics.ascent).isEqualTo(fontMetrics.ascent - fontMetrics.lineHeight())
@@ -153,7 +225,18 @@
     }
 
     @Test
-    fun singleLine_topRatio_100_trimFirstLineTop_true_trimLastLineBottom_false() {
+    fun singleLine_topRatio_100_trimFirstLineTop_false_trimLastLineBottom_true_preserve_no() {
+        singleLine_topRatio_100_trimFirstLineTop_false_trimLastLineBottom_true(false)
+    }
+
+    @Test
+    fun singleLine_topRatio_100_trimFirstLineTop_false_trimLastLineBottom_true_preserve_yes() {
+        singleLine_topRatio_100_trimFirstLineTop_false_trimLastLineBottom_true(true)
+    }
+
+    private fun singleLine_topRatio_100_trimFirstLineTop_true_trimLastLineBottom_false(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val newFontMetrics =
@@ -161,7 +244,8 @@
                 topRatio = 1f,
                 trimFirstLineTop = true,
                 trimLastLineBottom = false,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         assertThat(newFontMetrics.ascent).isEqualTo(fontMetrics.ascent)
@@ -169,7 +253,18 @@
     }
 
     @Test
-    fun singleLine_topRatio_100_trimFirstLineTop_true_trimLastLineBottom_true() {
+    fun singleLine_topRatio_100_trimFirstLineTop_true_trimLastLineBottom_false_preserve_no() {
+        singleLine_topRatio_100_trimFirstLineTop_true_trimLastLineBottom_false(false)
+    }
+
+    @Test
+    fun singleLine_topRatio_100_trimFirstLineTop_true_trimLastLineBottom_false_preserve_yes() {
+        singleLine_topRatio_100_trimFirstLineTop_true_trimLastLineBottom_false(true)
+    }
+
+    private fun singleLine_topRatio_100_trimFirstLineTop_true_trimLastLineBottom_true(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val newFontMetrics =
@@ -177,17 +272,29 @@
                 topRatio = 1f,
                 trimFirstLineTop = true,
                 trimLastLineBottom = true,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         assertThat(newFontMetrics.ascent).isEqualTo(fontMetrics.ascent)
         assertThat(newFontMetrics.descent).isEqualTo(fontMetrics.descent)
     }
 
+    @Test
+    fun singleLine_topRatio_100_trimFirstLineTop_true_trimLastLineBottom_true_preserve_no() {
+        singleLine_topRatio_100_trimFirstLineTop_true_trimLastLineBottom_true(false)
+    }
+
+    @Test
+    fun singleLine_topRatio_100_trimFirstLineTop_true_trimLastLineBottom_true_preserve_yes() {
+        singleLine_topRatio_100_trimFirstLineTop_true_trimLastLineBottom_true(true)
+    }
+
     /* single line, top percentage 50 */
 
-    @Test
-    fun singleLine_topRatio_50_trimFirstLineTop_false_trimLastLineBottom_false() {
+    private fun singleLine_topRatio_50_trimFirstLineTop_false_trimLastLineBottom_false(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val newFontMetrics =
@@ -195,7 +302,8 @@
                 topRatio = 0.5f,
                 trimFirstLineTop = false,
                 trimLastLineBottom = false,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         val halfLeading = fontMetrics.lineHeight() / 2
@@ -204,7 +312,18 @@
     }
 
     @Test
-    fun singleLine_topRatio_50_trimFirstLineTop_false_trimLastLineBottom_true() {
+    fun singleLine_topRatio_50_trimFirstLineTop_false_trimLastLineBottom_false_preserve_no() {
+        singleLine_topRatio_50_trimFirstLineTop_false_trimLastLineBottom_false(false)
+    }
+
+    @Test
+    fun singleLine_topRatio_50_trimFirstLineTop_false_trimLastLineBottom_false_preserve_yes() {
+        singleLine_topRatio_50_trimFirstLineTop_false_trimLastLineBottom_false(true)
+    }
+
+    private fun singleLine_topRatio_50_trimFirstLineTop_false_trimLastLineBottom_true(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val newFontMetrics =
@@ -212,7 +331,8 @@
                 topRatio = 0.5f,
                 trimFirstLineTop = false,
                 trimLastLineBottom = true,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         val halfLeading = fontMetrics.lineHeight() / 2
@@ -221,7 +341,18 @@
     }
 
     @Test
-    fun singleLine_topRatio_50_trimFirstLineTop_true_trimLastLineBottom_false() {
+    fun singleLine_topRatio_50_trimFirstLineTop_false_trimLastLineBottom_true_preserve_no() {
+        singleLine_topRatio_50_trimFirstLineTop_false_trimLastLineBottom_true(false)
+    }
+
+    @Test
+    fun singleLine_topRatio_50_trimFirstLineTop_false_trimLastLineBottom_true_preserve_yes() {
+        singleLine_topRatio_50_trimFirstLineTop_false_trimLastLineBottom_true(true)
+    }
+
+    private fun singleLine_topRatio_50_trimFirstLineTop_true_trimLastLineBottom_false(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val newFontMetrics =
@@ -229,7 +360,8 @@
                 topRatio = 0.5f,
                 trimFirstLineTop = true,
                 trimLastLineBottom = false,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         val halfLeading = fontMetrics.lineHeight() / 2
@@ -238,7 +370,18 @@
     }
 
     @Test
-    fun singleLine_topRatio_50_trimFirstLineTop_true_trimLastLineBottom_true() {
+    fun singleLine_topRatio_50_trimFirstLineTop_true_trimLastLineBottom_false_preserve_no() {
+        singleLine_topRatio_50_trimFirstLineTop_true_trimLastLineBottom_false(false)
+    }
+
+    @Test
+    fun singleLine_topRatio_50_trimFirstLineTop_true_trimLastLineBottom_false_preserve_yes() {
+        singleLine_topRatio_50_trimFirstLineTop_true_trimLastLineBottom_false(true)
+    }
+
+    private fun singleLine_topRatio_50_trimFirstLineTop_true_trimLastLineBottom_true(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val newFontMetrics =
@@ -246,17 +389,29 @@
                 topRatio = 0.5f,
                 trimFirstLineTop = true,
                 trimLastLineBottom = true,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         assertThat(newFontMetrics.ascent).isEqualTo(fontMetrics.ascent)
         assertThat(newFontMetrics.descent).isEqualTo(fontMetrics.descent)
     }
 
+    @Test
+    fun singleLine_topRatio_50_trimFirstLineTop_true_trimLastLineBottom_true_preserve_no() {
+        singleLine_topRatio_50_trimFirstLineTop_true_trimLastLineBottom_true(false)
+    }
+
+    @Test
+    fun singleLine_topRatio_50_trimFirstLineTop_true_trimLastLineBottom_true_preserve_yes() {
+        singleLine_topRatio_50_trimFirstLineTop_true_trimLastLineBottom_true(true)
+    }
+
     /* single line, proportional (topRatio -1) */
 
-    @Test
-    fun singleLine_topRatio_proportional_trimFirstLineTop_false_trimLastLineBottom_false() {
+    private fun singleLine_topRatio_proportional_trimFirstLineTop_false_trimLastLineBottom_false(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val newFontMetrics =
@@ -264,7 +419,8 @@
                 topRatio = -1f,
                 trimFirstLineTop = false,
                 trimLastLineBottom = false,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         val descentDiff = proportionalDescentDiff(fontMetrics)
@@ -274,7 +430,18 @@
     }
 
     @Test
-    fun singleLine_topRatio_proportional_trimFirstLineTop_false_trimLastLineBottom_true() {
+    fun singleLine_topRatio_proportional_trimFirstLineTop_false_trimLastLineBottom_false_preserve_no() {
+        singleLine_topRatio_proportional_trimFirstLineTop_false_trimLastLineBottom_false(false)
+    }
+
+    @Test
+    fun singleLine_topRatio_proportional_trimFirstLineTop_false_trimLastLineBottom_false_preserve_yes() {
+        singleLine_topRatio_proportional_trimFirstLineTop_false_trimLastLineBottom_false(true)
+    }
+
+    private fun singleLine_topRatio_proportional_trimFirstLineTop_false_trimLastLineBottom_true(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val newFontMetrics =
@@ -282,7 +449,8 @@
                 topRatio = -1f,
                 trimFirstLineTop = false,
                 trimLastLineBottom = true,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         val descentDiff = proportionalDescentDiff(fontMetrics)
@@ -292,7 +460,18 @@
     }
 
     @Test
-    fun singleLine_topRatio_proportional_trimFirstLineTop_true_trimLastLineBottom_false() {
+    fun singleLine_topRatio_proportional_trimFirstLineTop_false_trimLastLineBottom_true_preserve_no() {
+        singleLine_topRatio_proportional_trimFirstLineTop_false_trimLastLineBottom_true(false)
+    }
+
+    @Test
+    fun singleLine_topRatio_proportional_trimFirstLineTop_false_trimLastLineBottom_true_preserve_yes() {
+        singleLine_topRatio_proportional_trimFirstLineTop_false_trimLastLineBottom_true(true)
+    }
+
+    private fun singleLine_topRatio_proportional_trimFirstLineTop_true_trimLastLineBottom_false(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val newFontMetrics =
@@ -300,7 +479,8 @@
                 topRatio = -1f,
                 trimFirstLineTop = true,
                 trimLastLineBottom = false,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         val descentDiff = proportionalDescentDiff(fontMetrics)
@@ -309,7 +489,18 @@
     }
 
     @Test
-    fun singleLine_topRatio_proportional_trimFirstLineTop_true_trimLastLineBottom_true() {
+    fun singleLine_topRatio_proportional_trimFirstLineTop_true_trimLastLineBottom_false_preserve_no() {
+        singleLine_topRatio_proportional_trimFirstLineTop_true_trimLastLineBottom_false(false)
+    }
+
+    @Test
+    fun singleLine_topRatio_proportional_trimFirstLineTop_true_trimLastLineBottom_false_preserve_yes() {
+        singleLine_topRatio_proportional_trimFirstLineTop_true_trimLastLineBottom_false(true)
+    }
+
+    private fun singleLine_topRatio_proportional_trimFirstLineTop_true_trimLastLineBottom_true(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val newFontMetrics =
@@ -317,17 +508,29 @@
                 topRatio = -1f,
                 trimFirstLineTop = true,
                 trimLastLineBottom = true,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         assertThat(newFontMetrics.ascent).isEqualTo(fontMetrics.ascent)
         assertThat(newFontMetrics.descent).isEqualTo(fontMetrics.descent)
     }
 
+    @Test
+    fun singleLine_topRatio_proportional_trimFirstLineTop_true_trimLastLineBottom_true_preserve_no() {
+        singleLine_topRatio_proportional_trimFirstLineTop_true_trimLastLineBottom_true(false)
+    }
+
+    @Test
+    fun singleLine_topRatio_proportional_trimFirstLineTop_true_trimLastLineBottom_true_preserve_yes() {
+        singleLine_topRatio_proportional_trimFirstLineTop_true_trimLastLineBottom_true(true)
+    }
+
     /* multi line, top percentage = 0 */
 
-    @Test
-    fun multiLine_topRatio_0_trimFirstLineTop_false_trimLastLineBottom_false() {
+    private fun multiLine_topRatio_0_trimFirstLineTop_false_trimLastLineBottom_false(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val span =
@@ -335,7 +538,8 @@
                 topRatio = 0f,
                 trimFirstLineTop = false,
                 trimLastLineBottom = false,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         var newFontMetrics = span.runFirstLine(fontMetrics)
@@ -352,7 +556,18 @@
     }
 
     @Test
-    fun multiLine_topRatio_0_trimFirstLineTop_false_trimLastLineBottom_true() {
+    fun multiLine_topRatio_0_trimFirstLineTop_false_trimLastLineBottom_false_preserve_no() {
+        multiLine_topRatio_0_trimFirstLineTop_false_trimLastLineBottom_false(false)
+    }
+
+    @Test
+    fun multiLine_topRatio_0_trimFirstLineTop_false_trimLastLineBottom_false_preserve_yes() {
+        multiLine_topRatio_0_trimFirstLineTop_false_trimLastLineBottom_false(true)
+    }
+
+    private fun multiLine_topRatio_0_trimFirstLineTop_false_trimLastLineBottom_true(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val span =
@@ -360,7 +575,8 @@
                 topRatio = 0f,
                 trimFirstLineTop = false,
                 trimLastLineBottom = true,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         var newFontMetrics = span.runFirstLine(fontMetrics)
@@ -377,7 +593,18 @@
     }
 
     @Test
-    fun multiLine_topRatio_0_trimFirstLineTop_true_trimLastLineBottom_false() {
+    fun multiLine_topRatio_0_trimFirstLineTop_false_trimLastLineBottom_true_preserve_no() {
+        multiLine_topRatio_0_trimFirstLineTop_false_trimLastLineBottom_true(false)
+    }
+
+    @Test
+    fun multiLine_topRatio_0_trimFirstLineTop_false_trimLastLineBottom_true_preserve_yes() {
+        multiLine_topRatio_0_trimFirstLineTop_false_trimLastLineBottom_true(true)
+    }
+
+    private fun multiLine_topRatio_0_trimFirstLineTop_true_trimLastLineBottom_false(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val span =
@@ -385,7 +612,8 @@
                 topRatio = 0f,
                 trimFirstLineTop = true,
                 trimLastLineBottom = false,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         var newFontMetrics = span.runFirstLine(fontMetrics)
@@ -402,7 +630,18 @@
     }
 
     @Test
-    fun multiLine_topRatio_0_trimFirstLineTop_true_trimLastLineBottom_true() {
+    fun multiLine_topRatio_0_trimFirstLineTop_true_trimLastLineBottom_false_preserve_no() {
+        multiLine_topRatio_0_trimFirstLineTop_true_trimLastLineBottom_false(false)
+    }
+
+    @Test
+    fun multiLine_topRatio_0_trimFirstLineTop_true_trimLastLineBottom_false_preserve_yes() {
+        multiLine_topRatio_0_trimFirstLineTop_true_trimLastLineBottom_false(true)
+    }
+
+    private fun multiLine_topRatio_0_trimFirstLineTop_true_trimLastLineBottom_true(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val span =
@@ -410,7 +649,8 @@
                 topRatio = 0f,
                 trimFirstLineTop = true,
                 trimLastLineBottom = true,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         var newFontMetrics = span.runFirstLine(fontMetrics)
@@ -426,10 +666,21 @@
         assertThat(newFontMetrics.descent).isEqualTo(fontMetrics.descent)
     }
 
+    @Test
+    fun multiLine_topRatio_0_trimFirstLineTop_true_trimLastLineBottom_true_preserve_no() {
+        multiLine_topRatio_0_trimFirstLineTop_true_trimLastLineBottom_true(false)
+    }
+
+    @Test
+    fun multiLine_topRatio_0_trimFirstLineTop_true_trimLastLineBottom_true_preserve_yes() {
+        multiLine_topRatio_0_trimFirstLineTop_true_trimLastLineBottom_true(true)
+    }
+
     /* multi line, top percentage = 100 */
 
-    @Test
-    fun multiLine_topRatio_100_trimFirstLineTop_false_trimLastLineBottom_false() {
+    private fun multiLine_topRatio_100_trimFirstLineTop_false_trimLastLineBottom_false(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val span =
@@ -437,7 +688,8 @@
                 topRatio = 1f,
                 trimFirstLineTop = false,
                 trimLastLineBottom = false,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         var newFontMetrics = span.runFirstLine(fontMetrics)
@@ -454,7 +706,18 @@
     }
 
     @Test
-    fun multiLine_topRatio_100_trimFirstLineTop_false_trimLastLineBottom_true() {
+    fun multiLine_topRatio_100_trimFirstLineTop_false_trimLastLineBottom_false_preserve_no() {
+        multiLine_topRatio_100_trimFirstLineTop_false_trimLastLineBottom_false(false)
+    }
+
+    @Test
+    fun multiLine_topRatio_100_trimFirstLineTop_false_trimLastLineBottom_false_preserve_yes() {
+        multiLine_topRatio_100_trimFirstLineTop_false_trimLastLineBottom_false(true)
+    }
+
+    private fun multiLine_topRatio_100_trimFirstLineTop_false_trimLastLineBottom_true(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val span =
@@ -462,7 +725,8 @@
                 topRatio = 1f,
                 trimFirstLineTop = false,
                 trimLastLineBottom = true,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         var newFontMetrics = span.runFirstLine(fontMetrics)
@@ -479,7 +743,18 @@
     }
 
     @Test
-    fun multiLine_topRatio_100_trimFirstLineTop_true_trimLastLineBottom_false() {
+    fun multiLine_topRatio_100_trimFirstLineTop_false_trimLastLineBottom_true_preserve_no() {
+        multiLine_topRatio_100_trimFirstLineTop_false_trimLastLineBottom_true(false)
+    }
+
+    @Test
+    fun multiLine_topRatio_100_trimFirstLineTop_false_trimLastLineBottom_true_preserve_yes() {
+        multiLine_topRatio_100_trimFirstLineTop_false_trimLastLineBottom_true(true)
+    }
+
+    private fun multiLine_topRatio_100_trimFirstLineTop_true_trimLastLineBottom_false(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val span =
@@ -487,7 +762,8 @@
                 topRatio = 1f,
                 trimFirstLineTop = true,
                 trimLastLineBottom = false,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         var newFontMetrics = span.runFirstLine(fontMetrics)
@@ -504,7 +780,18 @@
     }
 
     @Test
-    fun multiLine_topRatio_100_trimFirstLineTop_true_trimLastLineBottom_true() {
+    fun multiLine_topRatio_100_trimFirstLineTop_true_trimLastLineBottom_false_preserve_no() {
+        multiLine_topRatio_100_trimFirstLineTop_true_trimLastLineBottom_false(false)
+    }
+
+    @Test
+    fun multiLine_topRatio_100_trimFirstLineTop_true_trimLastLineBottom_false_preserve_yes() {
+        multiLine_topRatio_100_trimFirstLineTop_true_trimLastLineBottom_false(true)
+    }
+
+    private fun multiLine_topRatio_100_trimFirstLineTop_true_trimLastLineBottom_true(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val span =
@@ -512,7 +799,8 @@
                 topRatio = 1f,
                 trimFirstLineTop = true,
                 trimLastLineBottom = true,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         var newFontMetrics = span.runFirstLine(fontMetrics)
@@ -528,10 +816,21 @@
         assertThat(newFontMetrics.descent).isEqualTo(fontMetrics.descent)
     }
 
+    @Test
+    fun multiLine_topRatio_100_trimFirstLineTop_true_trimLastLineBottom_true_preserve_no() {
+        multiLine_topRatio_100_trimFirstLineTop_true_trimLastLineBottom_true(false)
+    }
+
+    @Test
+    fun multiLine_topRatio_100_trimFirstLineTop_true_trimLastLineBottom_true_preserve_yes() {
+        multiLine_topRatio_100_trimFirstLineTop_true_trimLastLineBottom_true(true)
+    }
+
     /* multi line, top percentage = 50 */
 
-    @Test
-    fun multiLine_topRatio_50_trimFirstLineTop_false_trimLastLineBottom_false() {
+    private fun multiLine_topRatio_50_trimFirstLineTop_false_trimLastLineBottom_false(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val span =
@@ -539,7 +838,8 @@
                 topRatio = 0.5f,
                 trimFirstLineTop = false,
                 trimLastLineBottom = false,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve
             )
 
         val halfLeading = fontMetrics.lineHeight() / 2
@@ -557,7 +857,18 @@
     }
 
     @Test
-    fun multiLine_topRatio_50_trimFirstLineTop_false_trimLastLineBottom_true() {
+    fun multiLine_topRatio_50_trimFirstLineTop_false_trimLastLineBottom_false_preserve_no() {
+        multiLine_topRatio_50_trimFirstLineTop_false_trimLastLineBottom_false(false)
+    }
+
+    @Test
+    fun multiLine_topRatio_50_trimFirstLineTop_false_trimLastLineBottom_false_preserve_yes() {
+        multiLine_topRatio_50_trimFirstLineTop_false_trimLastLineBottom_false(true)
+    }
+
+    private fun multiLine_topRatio_50_trimFirstLineTop_false_trimLastLineBottom_true(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val span =
@@ -565,7 +876,8 @@
                 topRatio = 0.5f,
                 trimFirstLineTop = false,
                 trimLastLineBottom = true,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         val halfLeading = fontMetrics.lineHeight() / 2
@@ -583,7 +895,18 @@
     }
 
     @Test
-    fun multiLine_topRatio_50_trimFirstLineTop_true_trimLastLineBottom_false() {
+    fun multiLine_topRatio_50_trimFirstLineTop_false_trimLastLineBottom_true_preserve_no() {
+        multiLine_topRatio_50_trimFirstLineTop_false_trimLastLineBottom_true(false)
+    }
+
+    @Test
+    fun multiLine_topRatio_50_trimFirstLineTop_false_trimLastLineBottom_true_preserve_yes() {
+        multiLine_topRatio_50_trimFirstLineTop_false_trimLastLineBottom_true(true)
+    }
+
+    private fun multiLine_topRatio_50_trimFirstLineTop_true_trimLastLineBottom_false(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val span =
@@ -591,7 +914,8 @@
                 topRatio = 0.5f,
                 trimFirstLineTop = true,
                 trimLastLineBottom = false,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         val halfLeading = fontMetrics.lineHeight() / 2
@@ -609,7 +933,18 @@
     }
 
     @Test
-    fun multiLine_topRatio_50_trimFirstLineTop_true_trimLastLineBottom_true() {
+    fun multiLine_topRatio_50_trimFirstLineTop_true_trimLastLineBottom_false_preserve_no() {
+        multiLine_topRatio_50_trimFirstLineTop_true_trimLastLineBottom_false(false)
+    }
+
+    @Test
+    fun multiLine_topRatio_50_trimFirstLineTop_true_trimLastLineBottom_false_preserve_yes() {
+        multiLine_topRatio_50_trimFirstLineTop_true_trimLastLineBottom_false(true)
+    }
+
+    private fun multiLine_topRatio_50_trimFirstLineTop_true_trimLastLineBottom_true(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val span =
@@ -617,7 +952,8 @@
                 topRatio = 0.5f,
                 trimFirstLineTop = true,
                 trimLastLineBottom = true,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         val halfLeading = fontMetrics.lineHeight() / 2
@@ -634,10 +970,21 @@
         assertThat(newFontMetrics.descent).isEqualTo(fontMetrics.descent)
     }
 
+    @Test
+    fun multiLine_topRatio_50_trimFirstLineTop_true_trimLastLineBottom_true_preserve_no() {
+        multiLine_topRatio_50_trimFirstLineTop_true_trimLastLineBottom_true(false)
+    }
+
+    @Test
+    fun multiLine_topRatio_50_trimFirstLineTop_true_trimLastLineBottom_true_preserve_yes() {
+        multiLine_topRatio_50_trimFirstLineTop_true_trimLastLineBottom_true(true)
+    }
+
     /* multi line, proportional (topRatio -1) */
 
-    @Test
-    fun multiLine_topRatio_proportional_trimFirstLineTop_false_trimLastLineBottom_false() {
+    private fun multiLine_topRatio_proportional_trimFirstLineTop_false_trimLastLineBottom_false(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val span =
@@ -645,7 +992,8 @@
                 topRatio = -1f,
                 trimFirstLineTop = false,
                 trimLastLineBottom = false,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         val descentDiff = proportionalDescentDiff(fontMetrics)
@@ -665,7 +1013,18 @@
     }
 
     @Test
-    fun multiLine_topRatio_proportional_trimFirstLineTop_false_trimLastLineBottom_true() {
+    fun multiLine_topRatio_proportional_trimFirstLineTop_false_trimLastLineBottom_false_preserve_no() {
+        multiLine_topRatio_proportional_trimFirstLineTop_false_trimLastLineBottom_false(false)
+    }
+
+    @Test
+    fun multiLine_topRatio_proportional_trimFirstLineTop_false_trimLastLineBottom_false_preserve_yes() {
+        multiLine_topRatio_proportional_trimFirstLineTop_false_trimLastLineBottom_false(true)
+    }
+
+    private fun multiLine_topRatio_proportional_trimFirstLineTop_false_trimLastLineBottom_true(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val span =
@@ -673,7 +1032,8 @@
                 topRatio = -1f,
                 trimFirstLineTop = false,
                 trimLastLineBottom = true,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         val descentDiff = proportionalDescentDiff(fontMetrics)
@@ -693,7 +1053,18 @@
     }
 
     @Test
-    fun multiLine_topRatio_proportional_trimFirstLineTop_true_trimLastLineBottom_false() {
+    fun multiLine_topRatio_proportional_trimFirstLineTop_false_trimLastLineBottom_true_preserve_no() {
+        multiLine_topRatio_proportional_trimFirstLineTop_false_trimLastLineBottom_true(false)
+    }
+
+    @Test
+    fun multiLine_topRatio_proportional_trimFirstLineTop_false_trimLastLineBottom_true_preserve_yes() {
+        multiLine_topRatio_proportional_trimFirstLineTop_false_trimLastLineBottom_true(true)
+    }
+
+    private fun multiLine_topRatio_proportional_trimFirstLineTop_true_trimLastLineBottom_false(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val span =
@@ -701,7 +1072,8 @@
                 topRatio = -1f,
                 trimFirstLineTop = true,
                 trimLastLineBottom = false,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         val descentDiff = proportionalDescentDiff(fontMetrics)
@@ -721,7 +1093,18 @@
     }
 
     @Test
-    fun multiLine_topRatio_proportional_trimFirstLineTop_true_trimLastLineBottom_true() {
+    fun multiLine_topRatio_proportional_trimFirstLineTop_true_trimLastLineBottom_false_preserve_no() {
+        multiLine_topRatio_proportional_trimFirstLineTop_true_trimLastLineBottom_false(false)
+    }
+
+    @Test
+    fun multiLine_topRatio_proportional_trimFirstLineTop_true_trimLastLineBottom_false_preserve_yes() {
+        multiLine_topRatio_proportional_trimFirstLineTop_true_trimLastLineBottom_false(true)
+    }
+
+    private fun multiLine_topRatio_proportional_trimFirstLineTop_true_trimLastLineBottom_true(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val span =
@@ -729,7 +1112,8 @@
                 topRatio = -1f,
                 trimFirstLineTop = true,
                 trimLastLineBottom = true,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         val descentDiff = proportionalDescentDiff(fontMetrics)
@@ -748,10 +1132,21 @@
         assertThat(newFontMetrics.descent).isEqualTo(fontMetrics.descent)
     }
 
+    @Test
+    fun multiLine_topRatio_proportional_trimFirstLineTop_true_trimLastLineBottom_true_preserve_no() {
+        multiLine_topRatio_proportional_trimFirstLineTop_true_trimLastLineBottom_true(false)
+    }
+
+    @Test
+    fun multiLine_topRatio_proportional_trimFirstLineTop_true_trimLastLineBottom_true_preserve_yes() {
+        multiLine_topRatio_proportional_trimFirstLineTop_true_trimLastLineBottom_true(true)
+    }
+
     /* first ascent & last descent diff */
 
-    @Test
-    fun singleLine_with_firstLineTop_and_lastLineBottom_topRatio_50_larger_line_height() {
+    private fun singleLine_with_firstLineTop_and_lastLineBottom_topRatio_50_larger_line_height(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val span =
@@ -759,7 +1154,8 @@
                 topRatio = 0.5f,
                 trimFirstLineTop = false,
                 trimLastLineBottom = false,
-                newLineHeight = fontMetrics.doubleLineHeight()
+                newLineHeight = fontMetrics.doubleLineHeight(),
+                preserveMinimumHeight = preserve,
             )
 
         span.runFirstLine(fontMetrics)
@@ -770,7 +1166,18 @@
     }
 
     @Test
-    fun multiLine_with_firstLineTop_and_lastLineBottom_topRatio_50_larger_line_height() {
+    fun singleLine_with_firstLineTop_and_lastLineBottom_topRatio_50_larger_line_height_preserve_no() {
+        singleLine_with_firstLineTop_and_lastLineBottom_topRatio_50_larger_line_height(false)
+    }
+
+    @Test
+    fun singleLine_with_firstLineTop_and_lastLineBottom_topRatio_50_larger_line_height_preserve_yes() {
+        singleLine_with_firstLineTop_and_lastLineBottom_topRatio_50_larger_line_height(true)
+    }
+
+    private fun multiLine_with_firstLineTop_and_lastLineBottom_topRatio_50_larger_line_height(
+        preserve: Boolean
+    ) {
         val fontMetrics = createFontMetrics()
 
         val span =
@@ -778,7 +1185,8 @@
                 topRatio = 0.5f,
                 trimFirstLineTop = false,
                 trimLastLineBottom = false,
-                fontMetrics = fontMetrics
+                fontMetrics = fontMetrics,
+                preserveMinimumHeight = preserve,
             )
 
         span.runFirstLine(fontMetrics)
@@ -791,7 +1199,17 @@
     }
 
     @Test
-    fun singleLine_with_firstLineTop_and_lastLineBottom_topRatio_50_smaller_line_height() {
+    fun multiLine_with_firstLineTop_and_lastLineBottom_topRatio_50_larger_line_height_preserve_no() {
+        multiLine_with_firstLineTop_and_lastLineBottom_topRatio_50_larger_line_height(false)
+    }
+
+    @Test
+    fun multiLine_with_firstLineTop_and_lastLineBottom_topRatio_50_larger_line_height_preserve_yes() {
+        multiLine_with_firstLineTop_and_lastLineBottom_topRatio_50_larger_line_height(true)
+    }
+
+    @Test
+    fun singleLine_with_firstLineTop_and_lastLineBottom_topRatio_50_smaller_line_height_preserve_no() {
         val fontMetrics = createFontMetrics()
 
         val span =
@@ -799,7 +1217,8 @@
                 topRatio = 0.5f,
                 trimFirstLineTop = false,
                 trimLastLineBottom = false,
-                newLineHeight = fontMetrics.lineHeight() / 2
+                newLineHeight = fontMetrics.lineHeight() / 2,
+                preserveMinimumHeight = false,
             )
 
         span.runFirstLine(fontMetrics)
@@ -810,7 +1229,26 @@
     }
 
     @Test
-    fun multiLine_with_firstLineTop_and_lastLineBottom_topRatio_50_smaller_line_height() {
+    fun singleLine_with_firstLineTop_and_lastLineBottom_topRatio_50_smaller_line_height_preserve_yes() {
+        val fontMetrics = createFontMetrics()
+
+        val span =
+            createSingleLineSpan(
+                topRatio = 0.5f,
+                trimFirstLineTop = false,
+                trimLastLineBottom = false,
+                newLineHeight = fontMetrics.lineHeight() / 2,
+                preserveMinimumHeight = true,
+            )
+
+        span.runFirstLine(fontMetrics)
+
+        assertThat(span.firstAscentDiff).isEqualTo(0)
+        assertThat(span.lastDescentDiff).isEqualTo(0)
+    }
+
+    @Test
+    fun multiLine_with_firstLineTop_and_lastLineBottom_topRatio_50_smaller_line_height_preserve_no() {
         val fontMetrics = createFontMetrics()
 
         val span =
@@ -818,7 +1256,8 @@
                 topRatio = 0.5f,
                 trimFirstLineTop = false,
                 trimLastLineBottom = false,
-                newLineHeight = fontMetrics.lineHeight() / 2
+                newLineHeight = fontMetrics.lineHeight() / 2,
+                preserveMinimumHeight = false,
             )
 
         span.runFirstLine(fontMetrics)
@@ -830,6 +1269,27 @@
         assertThat(span.lastDescentDiff).isEqualTo(halfLeading)
     }
 
+    @Test
+    fun multiLine_with_firstLineTop_and_lastLineBottom_topRatio_50_smaller_line_height_preserve_yes() {
+        val fontMetrics = createFontMetrics()
+
+        val span =
+            createMultiLineSpan(
+                topRatio = 0.5f,
+                trimFirstLineTop = false,
+                trimLastLineBottom = false,
+                newLineHeight = fontMetrics.lineHeight() / 2,
+                preserveMinimumHeight = true,
+            )
+
+        span.runFirstLine(fontMetrics)
+        span.runSecondLine(fontMetrics)
+        span.runLastLine(fontMetrics)
+
+        assertThat(span.firstAscentDiff).isEqualTo(0)
+        assertThat(span.lastDescentDiff).isEqualTo(0)
+    }
+
     private fun proportionalDescentDiff(fontMetrics: FontMetricsInt): Int {
         val ascent = abs(fontMetrics.ascent.toFloat())
         val ascentRatio = ascent / fontMetrics.lineHeight()
@@ -844,14 +1304,16 @@
         topRatio: Float,
         trimFirstLineTop: Boolean,
         trimLastLineBottom: Boolean,
-        fontMetrics: FontMetricsInt
+        fontMetrics: FontMetricsInt,
+        preserveMinimumHeight: Boolean,
     ): FontMetricsInt {
         val span =
             createSingleLineSpan(
                 topRatio = topRatio,
                 trimFirstLineTop = trimFirstLineTop,
                 trimLastLineBottom = trimLastLineBottom,
-                newLineHeight = fontMetrics.doubleLineHeight()
+                newLineHeight = fontMetrics.doubleLineHeight(),
+                preserveMinimumHeight = preserveMinimumHeight,
             )
 
         return span.runFirstLine(fontMetrics.copy())
@@ -862,7 +1324,8 @@
         topRatio: Float,
         trimFirstLineTop: Boolean,
         trimLastLineBottom: Boolean,
-        newLineHeight: Int
+        newLineHeight: Int,
+        preserveMinimumHeight: Boolean,
     ): LineHeightStyleSpan =
         LineHeightStyleSpan(
             lineHeight = newLineHeight.toFloat(),
@@ -870,7 +1333,8 @@
             endIndex = SingleLineEndIndex,
             trimFirstLineTop = trimFirstLineTop,
             trimLastLineBottom = trimLastLineBottom,
-            topRatio = topRatio
+            topRatio = topRatio,
+            preserveMinimumHeight = preserveMinimumHeight,
         )
 
     /** Creates a LineHeightSpan that covers [MultiLineStartIndex, MultiLineEndIndex]. */
@@ -878,13 +1342,15 @@
         topRatio: Float,
         trimFirstLineTop: Boolean,
         trimLastLineBottom: Boolean,
-        fontMetrics: FontMetricsInt
+        fontMetrics: FontMetricsInt,
+        preserveMinimumHeight: Boolean,
     ): LineHeightStyleSpan =
         createMultiLineSpan(
             topRatio = topRatio,
             trimFirstLineTop = trimFirstLineTop,
             trimLastLineBottom = trimLastLineBottom,
-            newLineHeight = fontMetrics.doubleLineHeight()
+            newLineHeight = fontMetrics.doubleLineHeight(),
+            preserveMinimumHeight = preserveMinimumHeight,
         )
 
     /** Creates a LineHeightSpan that covers [MultiLineStartIndex, MultiLineEndIndex]. */
@@ -892,7 +1358,8 @@
         topRatio: Float,
         trimFirstLineTop: Boolean,
         trimLastLineBottom: Boolean,
-        newLineHeight: Int
+        newLineHeight: Int,
+        preserveMinimumHeight: Boolean,
     ): LineHeightStyleSpan =
         LineHeightStyleSpan(
             lineHeight = newLineHeight.toFloat(),
@@ -900,7 +1367,8 @@
             endIndex = MultiLineEndIndex,
             trimFirstLineTop = trimFirstLineTop,
             trimLastLineBottom = trimLastLineBottom,
-            topRatio = topRatio
+            topRatio = topRatio,
+            preserveMinimumHeight = preserveMinimumHeight,
         )
 
     /** Creates a FontMetricsInt with line height of 20, where ascent is -10, descent is 10 */
diff --git a/text/text/src/main/java/androidx/compose/ui/text/android/style/LineHeightStyleSpan.android.kt b/text/text/src/main/java/androidx/compose/ui/text/android/style/LineHeightStyleSpan.android.kt
index d52c699..e0d6cf0 100644
--- a/text/text/src/main/java/androidx/compose/ui/text/android/style/LineHeightStyleSpan.android.kt
+++ b/text/text/src/main/java/androidx/compose/ui/text/android/style/LineHeightStyleSpan.android.kt
@@ -46,7 +46,8 @@
     private val endIndex: Int,
     private val trimFirstLineTop: Boolean,
     val trimLastLineBottom: Boolean,
-    @FloatRange(from = -1.0, to = 1.0) private val topRatio: Float
+    @FloatRange(from = -1.0, to = 1.0) private val topRatio: Float,
+    private val preserveMinimumHeight: Boolean,
 ) : android.text.style.LineHeightSpan {
 
     private var firstAscent: Int = Int.MIN_VALUE
@@ -98,6 +99,15 @@
 
         // calculate the difference between the current line lineHeight and the requested lineHeight
         val diff = ceiledLineHeight - currentHeight
+        if (preserveMinimumHeight && diff <= 0) {
+            ascent = fontMetricsInt.ascent
+            descent = fontMetricsInt.descent
+            firstAscent = ascent
+            lastDescent = descent
+            firstAscentDiff = 0
+            lastDescentDiff = 0
+            return
+        }
 
         val ascentRatio =
             if (topRatio == -1f) {
@@ -135,7 +145,8 @@
             endIndex = endIndex,
             trimFirstLineTop = trimFirstLineTop,
             trimLastLineBottom = trimLastLineBottom,
-            topRatio = topRatio
+            topRatio = topRatio,
+            preserveMinimumHeight = preserveMinimumHeight,
         )
 }
 
diff --git a/viewpager2/integration-tests/targetsdk-tests/build.gradle b/viewpager2/integration-tests/targetsdk-tests/build.gradle
index 4572431..e032db1 100644
--- a/viewpager2/integration-tests/targetsdk-tests/build.gradle
+++ b/viewpager2/integration-tests/targetsdk-tests/build.gradle
@@ -25,11 +25,9 @@
     productFlavors {
         targetSdk29 {
             dimension "targetSdk"
-            targetSdkVersion 29
         }
         targetSdk30 {
             dimension "targetSdk"
-            targetSdkVersion 30
         }
         targetSdkLatest {
             dimension "targetSdk"
@@ -39,6 +37,15 @@
     namespace "androidx.viewpager2.integration.targestsdktests"
 }
 
+androidComponents {
+    beforeVariants(selector().withFlavor("targetSdk", "targetSdk29")) { variant ->
+        variant.androidTest.targetSdk = 29
+    }
+    beforeVariants(selector().withFlavor("targetSdk", "targetSdk30")) { variant ->
+        variant.androidTest.targetSdk = 30
+    }
+}
+
 dependencies {
     androidTestImplementation(project(":viewpager2:viewpager2"))
     androidTestImplementation("androidx.activity:activity-ktx:1.3.1")
diff --git a/wear/compose/compose-foundation/api/current.txt b/wear/compose/compose-foundation/api/current.txt
index e2b3456..929c2b9 100644
--- a/wear/compose/compose-foundation/api/current.txt
+++ b/wear/compose/compose-foundation/api/current.txt
@@ -168,9 +168,11 @@
   public final class CurvedTextStyle {
     ctor public CurvedTextStyle(androidx.compose.ui.text.TextStyle style);
     ctor @Deprecated public CurvedTextStyle(optional long background, optional long color, optional long fontSize);
-    ctor public CurvedTextStyle(optional long background, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis);
+    ctor @Deprecated public CurvedTextStyle(optional long background, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis);
+    ctor public CurvedTextStyle(optional long background, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional long letterSpacing);
     method @Deprecated public androidx.wear.compose.foundation.CurvedTextStyle copy(optional long background, optional long color, optional long fontSize);
-    method public androidx.wear.compose.foundation.CurvedTextStyle copy(optional long background, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis);
+    method @Deprecated public androidx.wear.compose.foundation.CurvedTextStyle copy(optional long background, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis);
+    method public androidx.wear.compose.foundation.CurvedTextStyle copy(optional long background, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional long letterSpacing);
     method public long getBackground();
     method public long getColor();
     method public androidx.compose.ui.text.font.FontFamily? getFontFamily();
@@ -178,6 +180,7 @@
     method public androidx.compose.ui.text.font.FontStyle? getFontStyle();
     method public androidx.compose.ui.text.font.FontSynthesis? getFontSynthesis();
     method public androidx.compose.ui.text.font.FontWeight? getFontWeight();
+    method public long getLetterSpacing();
     method public androidx.wear.compose.foundation.CurvedTextStyle merge(optional androidx.wear.compose.foundation.CurvedTextStyle? other);
     method public operator androidx.wear.compose.foundation.CurvedTextStyle plus(androidx.wear.compose.foundation.CurvedTextStyle other);
     property public final long background;
@@ -187,6 +190,7 @@
     property public final androidx.compose.ui.text.font.FontStyle? fontStyle;
     property public final androidx.compose.ui.text.font.FontSynthesis? fontSynthesis;
     property public final androidx.compose.ui.text.font.FontWeight? fontWeight;
+    property public final long letterSpacing;
   }
 
   public final class ExpandableItemsDefaults {
@@ -293,6 +297,23 @@
     property public final int Revealing;
   }
 
+  public interface ScrollInfoProvider {
+    method public float getAnchorItemOffset();
+    method public boolean isScrollAwayValid();
+    method public boolean isScrollInProgress();
+    method public boolean isScrollable();
+    property public abstract float anchorItemOffset;
+    property public abstract boolean isScrollAwayValid;
+    property public abstract boolean isScrollInProgress;
+    property public abstract boolean isScrollable;
+  }
+
+  public final class ScrollInfoProviderKt {
+    method public static androidx.wear.compose.foundation.ScrollInfoProvider toScrollAwayInfoProvider(androidx.compose.foundation.lazy.LazyListState);
+    method public static androidx.wear.compose.foundation.ScrollInfoProvider toScrollAwayInfoProvider(androidx.compose.foundation.ScrollState);
+    method public static androidx.wear.compose.foundation.ScrollInfoProvider toScrollAwayInfoProvider(androidx.wear.compose.foundation.lazy.ScalingLazyListState);
+  }
+
   public final class SwipeToDismissBoxDefaults {
     method public androidx.compose.animation.core.SpringSpec<java.lang.Float> getAnimationSpec();
     method public float getEdgeWidth();
diff --git a/wear/compose/compose-foundation/api/restricted_current.txt b/wear/compose/compose-foundation/api/restricted_current.txt
index e2b3456..929c2b9 100644
--- a/wear/compose/compose-foundation/api/restricted_current.txt
+++ b/wear/compose/compose-foundation/api/restricted_current.txt
@@ -168,9 +168,11 @@
   public final class CurvedTextStyle {
     ctor public CurvedTextStyle(androidx.compose.ui.text.TextStyle style);
     ctor @Deprecated public CurvedTextStyle(optional long background, optional long color, optional long fontSize);
-    ctor public CurvedTextStyle(optional long background, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis);
+    ctor @Deprecated public CurvedTextStyle(optional long background, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis);
+    ctor public CurvedTextStyle(optional long background, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional long letterSpacing);
     method @Deprecated public androidx.wear.compose.foundation.CurvedTextStyle copy(optional long background, optional long color, optional long fontSize);
-    method public androidx.wear.compose.foundation.CurvedTextStyle copy(optional long background, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis);
+    method @Deprecated public androidx.wear.compose.foundation.CurvedTextStyle copy(optional long background, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis);
+    method public androidx.wear.compose.foundation.CurvedTextStyle copy(optional long background, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional long letterSpacing);
     method public long getBackground();
     method public long getColor();
     method public androidx.compose.ui.text.font.FontFamily? getFontFamily();
@@ -178,6 +180,7 @@
     method public androidx.compose.ui.text.font.FontStyle? getFontStyle();
     method public androidx.compose.ui.text.font.FontSynthesis? getFontSynthesis();
     method public androidx.compose.ui.text.font.FontWeight? getFontWeight();
+    method public long getLetterSpacing();
     method public androidx.wear.compose.foundation.CurvedTextStyle merge(optional androidx.wear.compose.foundation.CurvedTextStyle? other);
     method public operator androidx.wear.compose.foundation.CurvedTextStyle plus(androidx.wear.compose.foundation.CurvedTextStyle other);
     property public final long background;
@@ -187,6 +190,7 @@
     property public final androidx.compose.ui.text.font.FontStyle? fontStyle;
     property public final androidx.compose.ui.text.font.FontSynthesis? fontSynthesis;
     property public final androidx.compose.ui.text.font.FontWeight? fontWeight;
+    property public final long letterSpacing;
   }
 
   public final class ExpandableItemsDefaults {
@@ -293,6 +297,23 @@
     property public final int Revealing;
   }
 
+  public interface ScrollInfoProvider {
+    method public float getAnchorItemOffset();
+    method public boolean isScrollAwayValid();
+    method public boolean isScrollInProgress();
+    method public boolean isScrollable();
+    property public abstract float anchorItemOffset;
+    property public abstract boolean isScrollAwayValid;
+    property public abstract boolean isScrollInProgress;
+    property public abstract boolean isScrollable;
+  }
+
+  public final class ScrollInfoProviderKt {
+    method public static androidx.wear.compose.foundation.ScrollInfoProvider toScrollAwayInfoProvider(androidx.compose.foundation.lazy.LazyListState);
+    method public static androidx.wear.compose.foundation.ScrollInfoProvider toScrollAwayInfoProvider(androidx.compose.foundation.ScrollState);
+    method public static androidx.wear.compose.foundation.ScrollInfoProvider toScrollAwayInfoProvider(androidx.wear.compose.foundation.lazy.ScalingLazyListState);
+  }
+
   public final class SwipeToDismissBoxDefaults {
     method public androidx.compose.animation.core.SpringSpec<java.lang.Float> getAnimationSpec();
     method public float getEdgeWidth();
diff --git a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/BasicCurvedTextTest.kt b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/BasicCurvedTextTest.kt
index f17f27d..7a50eab 100644
--- a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/BasicCurvedTextTest.kt
+++ b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/BasicCurvedTextTest.kt
@@ -16,6 +16,7 @@
 
 package androidx.wear.compose.foundation
 
+import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.size
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.mutableStateOf
@@ -26,6 +27,7 @@
 import androidx.compose.ui.test.onNodeWithTag
 import androidx.compose.ui.unit.Density
 import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.em
 import androidx.compose.ui.unit.sp
 import org.junit.Assert.assertEquals
 import org.junit.Rule
@@ -76,4 +78,35 @@
         // density and font.
         rule.onNodeWithTag(TEST_TAG).assertWidthIsEqualTo(93.dp)
     }
+
+    @Test
+    fun letter_spacing_increases_size() {
+        val TAG1 = TEST_TAG + "1"
+        val TAG2 = TEST_TAG + "2"
+        rule.setContent {
+            Box {
+                repeat(2) {
+                    val tag = if (it == 0) TAG1 else TAG2
+                    val style =
+                        if (it == 0) CurvedTextStyle(fontSize = 24.sp)
+                        else CurvedTextStyle(fontSize = 24.sp, letterSpacing = 0.5f.em)
+                    CurvedLayout(modifier = Modifier.size(200.dp)) {
+                        curvedRow(modifier = CurvedModifier.testTag(tag)) {
+                            basicCurvedText(
+                                // Use a small text so we can see its width increase, instead of it
+                                // just wrapping around the circle.
+                                text = "Text",
+                                style = style,
+                            )
+                        }
+                    }
+                }
+            }
+        }
+
+        val width1 = rule.onNodeWithTag(TAG1).fetchSemanticsNode().size.width
+        val width2 = rule.onNodeWithTag(TAG2).fetchSemanticsNode().size.width
+        // We added 0.5 em spacing, it should be much bigger
+        assert(width2 > 1.4f * width1)
+    }
 }
diff --git a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/PagerTest.kt b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/PagerTest.kt
index 7bfa0db..2c3ef28 100644
--- a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/PagerTest.kt
+++ b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/PagerTest.kt
@@ -23,6 +23,7 @@
 import androidx.compose.foundation.pager.VerticalPager
 import androidx.compose.foundation.pager.rememberPagerState
 import androidx.compose.foundation.text.BasicText
+import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.test.assertIsDisplayed
@@ -35,6 +36,8 @@
 import androidx.compose.ui.test.swipeRight
 import androidx.compose.ui.test.swipeUp
 import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
 import org.junit.Assert
 import org.junit.Rule
 import org.junit.Test
@@ -113,4 +116,72 @@
             rule.onNodeWithTag(pagerTestTag).performTouchInput { swipeDown() }
         }
     }
+
+    @OptIn(ExperimentalFoundationApi::class)
+    private fun verifyScrollsToEachPage(
+        pageCount: Int,
+        pagerState: PagerState,
+        scrollScope: CoroutineScope
+    ) {
+        val listOfPageIndices = 0 until pageCount
+
+        // Scroll to each page then return to page 0
+        for (i in listOfPageIndices) {
+            rule.runOnIdle { Assert.assertEquals(0, pagerState.currentPage) }
+            rule.onNodeWithText("Page 0").assertIsDisplayed()
+
+            rule.runOnIdle { scrollScope.launch { pagerState.animateScrollToPage(i) } }
+
+            rule.runOnIdle { Assert.assertEquals(i, pagerState.currentPage) }
+            rule.onNodeWithText("Page $i").assertIsDisplayed()
+
+            rule.runOnIdle { scrollScope.launch { pagerState.animateScrollToPage(0) } }
+        }
+    }
+
+    @OptIn(ExperimentalFoundationApi::class)
+    @Test
+    fun horizontal_pager_with_nested_scaling_lazy_column_is_able_to_scroll_to_arbitrary_page() {
+        val pageCount = 5
+        lateinit var pagerState: PagerState
+        lateinit var scrollScope: CoroutineScope
+
+        rule.setContent {
+            pagerState = rememberPagerState { pageCount }
+            scrollScope = rememberCoroutineScope()
+
+            HorizontalPager(state = pagerState, modifier = Modifier.testTag(pagerTestTag)) { page ->
+                ScalingLazyColumn(
+                    modifier = Modifier.fillMaxSize(),
+                ) {
+                    item { BasicText(text = "Page $page") }
+                }
+            }
+        }
+
+        verifyScrollsToEachPage(pageCount, pagerState, scrollScope)
+    }
+
+    @OptIn(ExperimentalFoundationApi::class)
+    @Test
+    fun vertical_pager_with_nested_scaling_lazy_column_is_able_to_scroll_to_arbitrary_page() {
+        val pageCount = 5
+        lateinit var pagerState: PagerState
+        lateinit var scrollScope: CoroutineScope
+
+        rule.setContent {
+            pagerState = rememberPagerState { pageCount }
+            scrollScope = rememberCoroutineScope()
+
+            VerticalPager(state = pagerState, modifier = Modifier.testTag(pagerTestTag)) { page ->
+                ScalingLazyColumn(
+                    modifier = Modifier.fillMaxSize(),
+                ) {
+                    item { BasicText(text = "Page $page") }
+                }
+            }
+        }
+
+        verifyScrollsToEachPage(pageCount, pagerState, scrollScope)
+    }
 }
diff --git a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/lazy/ScalingLazyColumnTest.kt b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/lazy/ScalingLazyColumnTest.kt
index b25dc9d..f80264a 100644
--- a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/lazy/ScalingLazyColumnTest.kt
+++ b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/lazy/ScalingLazyColumnTest.kt
@@ -26,6 +26,7 @@
 import androidx.compose.foundation.layout.requiredWidth
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.text.BasicText
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.MutableState
 import androidx.compose.runtime.getValue
@@ -34,11 +35,13 @@
 import androidx.compose.runtime.setValue
 import androidx.compose.testutils.WithTouchSlop
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.focus.onFocusChanged
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.test.assertHeightIsEqualTo
 import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.assertIsFocused
 import androidx.compose.ui.test.assertWidthIsEqualTo
 import androidx.compose.ui.test.junit4.ComposeContentTestRule
 import androidx.compose.ui.test.junit4.createComposeRule
@@ -56,6 +59,7 @@
 import kotlin.math.roundToInt
 import kotlinx.coroutines.runBlocking
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -942,6 +946,58 @@
             }
         }
     }
+
+    @Test
+    fun scalingLazyColumnIsFocusedByDefault() {
+        var focusSet = false
+
+        rule.setContent {
+            ScalingLazyColumn(
+                modifier =
+                    Modifier.testTag("scalingLazyColumn").onFocusChanged {
+                        focusSet = it.isFocused
+                    },
+            ) {
+                items(100) { BasicText("item $it") }
+            }
+        }
+
+        assert(focusSet)
+    }
+
+    @Test
+    fun scalingLazyColumnIsNotFocused_withDisabledRotary() {
+        var focusSet = false
+
+        rule.setContent {
+            ScalingLazyColumn(
+                modifier =
+                    Modifier.testTag("scalingLazyColumn").onFocusChanged {
+                        focusSet = it.isFocused
+                    },
+                // Disable rotary and focus as well
+                rotaryScrollableBehavior = null,
+            ) {
+                items(100) { BasicText("item $it") }
+            }
+        }
+
+        assert(!focusSet)
+    }
+
+    @Ignore("b/347700248 re-enable test after focusable semantics start working again")
+    @Test
+    fun scalingLazyColumnIsFocusedByDefault_withSemantics() {
+        rule.setContent {
+            ScalingLazyColumn(
+                modifier = Modifier.testTag("scalingLazyColumn"),
+            ) {
+                items(100) { BasicText("item $it") }
+            }
+        }
+
+        rule.onNodeWithTag("scalingLazyColumn").assertIsFocused()
+    }
 }
 
 internal const val TestTouchSlop = 18f
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/BasicCurvedText.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/BasicCurvedText.kt
index 868b699..1ae17c6 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/BasicCurvedText.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/BasicCurvedText.kt
@@ -49,6 +49,8 @@
 import androidx.compose.ui.text.font.resolveAsTypeface
 import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.unit.Constraints
+import androidx.compose.ui.unit.TextUnit
+import androidx.compose.ui.unit.TextUnitType
 import kotlin.math.abs
 import kotlin.math.min
 import kotlin.math.roundToInt
@@ -137,7 +139,13 @@
     }
 
     override fun CurvedMeasureScope.initializeMeasure(measurables: Iterator<Measurable>) {
-        delegate.updateIfNeeded(text, clockwise, actualStyle.fontSize.toPx())
+        delegate.updateIfNeeded(
+            text,
+            clockwise,
+            actualStyle.fontSize.toPx(),
+            actualStyle.letterSpacing,
+            density
+        )
 
         // Size the compose-ui node reasonably.
 
@@ -221,6 +229,8 @@
     private var text: String = ""
     private var clockwise: Boolean = true
     private var fontSizePx: Float = 0f
+    private var letterSpacing: TextUnit = TextUnit.Unspecified
+    private var density: Float = 0f
 
     var textWidth by mutableFloatStateOf(0f)
     var textHeight by mutableFloatStateOf(0f)
@@ -235,12 +245,39 @@
     var lastLayoutInfo: CurvedLayoutInfo? = null
     var lastParentSweepRadians: Float = 0f
 
-    fun updateIfNeeded(text: String, clockwise: Boolean, fontSizePx: Float) {
-        if (text != this.text || clockwise != this.clockwise || fontSizePx != this.fontSizePx) {
+    fun updateIfNeeded(
+        text: String,
+        clockwise: Boolean,
+        fontSizePx: Float,
+        letterSpacing: TextUnit,
+        density: Float
+    ) {
+        if (
+            text != this.text ||
+                clockwise != this.clockwise ||
+                fontSizePx != this.fontSizePx ||
+                letterSpacing != this.letterSpacing ||
+                density != this.density
+        ) {
             this.text = text
             this.clockwise = clockwise
             this.fontSizePx = fontSizePx
+            this.letterSpacing = letterSpacing
+            this.density = density
+
             paint.textSize = fontSizePx
+            paint.letterSpacing =
+                letterSpacing.let {
+                    when (it.type) {
+                        TextUnitType.Em -> it.value
+                        TextUnitType.Sp -> {
+                            val emWidth = paint.textSize * paint.textScaleX
+                            if (emWidth == 0.0f) 0f else it.value * density / emWidth
+                        }
+                        else -> 0f
+                    }
+                }
+
             updateMeasures()
             lastLayoutInfo = null // Ensure paths are recomputed
         }
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedSize.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedSize.kt
index 492ba24..ac8a165 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedSize.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedSize.kt
@@ -109,11 +109,8 @@
         baseInitializeMeasure(measurables)
     }
 
-    override fun calculateSweepRadians(partialLayoutInfo: PartialLayoutInfo): Float =
-        partialLayoutInfo.sweepRadians.coerceIn(
-            minSweepDegrees.toRadians(),
-            maxSweepDegrees.toRadians()
-        )
+    override fun calculateSweepRadians(sweepRadians: Float, measureRadius: Float): Float =
+        sweepRadians.coerceIn(minSweepDegrees.toRadians(), maxSweepDegrees.toRadians())
 }
 
 internal class AngularWidthSizeWrapper(
@@ -134,11 +131,8 @@
         baseInitializeMeasure(measurables)
     }
 
-    override fun calculateSweepRadians(partialLayoutInfo: PartialLayoutInfo): Float =
-        partialLayoutInfo.sweepRadians.coerceIn(
-            minAngularWidthPx / partialLayoutInfo.measureRadius,
-            maxAngularWidthPx / partialLayoutInfo.measureRadius
-        )
+    override fun calculateSweepRadians(sweepRadians: Float, measureRadius: Float) =
+        sweepRadians.coerceIn(minAngularWidthPx / measureRadius, maxAngularWidthPx / measureRadius)
 }
 
 internal abstract class BaseSizeWrapper(
@@ -161,7 +155,7 @@
     override fun doEstimateThickness(maxRadius: Float) =
         wrapped.estimateThickness(maxRadius).coerceIn(minThicknessPx, maxThicknessPx)
 
-    protected abstract fun calculateSweepRadians(partialLayoutInfo: PartialLayoutInfo): Float
+    protected abstract fun calculateSweepRadians(sweepRadians: Float, measureRadius: Float): Float
 
     override fun doAngularPosition(
         parentStartAngleRadians: Float,
@@ -170,7 +164,7 @@
     ): Float {
         wrapped.angularPosition(
             parentStartAngleRadians,
-            parentSweepRadians = sweepRadians,
+            parentSweepRadians = calculateSweepRadians(parentSweepRadians, measureRadius),
             centerOffset
         )
         return parentStartAngleRadians
@@ -182,7 +176,7 @@
     ): PartialLayoutInfo {
         val partialLayoutInfo = wrapped.radialPosition(parentOuterRadius, estimatedThickness)
         return PartialLayoutInfo(
-            calculateSweepRadians(partialLayoutInfo),
+            calculateSweepRadians(partialLayoutInfo.sweepRadians, partialLayoutInfo.measureRadius),
             parentOuterRadius,
             thickness = estimatedThickness,
             measureRadius =
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedTextStyle.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedTextStyle.kt
index f1d40ed..659932a 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedTextStyle.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedTextStyle.kt
@@ -24,7 +24,8 @@
 import androidx.compose.ui.text.font.FontSynthesis
 import androidx.compose.ui.text.font.FontWeight
 import androidx.compose.ui.unit.TextUnit
-import androidx.compose.ui.unit.isUnspecified
+import androidx.compose.ui.unit.em
+import androidx.compose.ui.unit.isSpecified
 import androidx.compose.ui.unit.sp
 
 /** The default values to use if they are not specified. */
@@ -35,7 +36,8 @@
         background = Color.Transparent,
         fontWeight = FontWeight.Normal,
         fontStyle = FontStyle.Normal,
-        fontSynthesis = FontSynthesis.All
+        fontSynthesis = FontSynthesis.All,
+        letterSpacing = 0f.em,
     )
 
 /**
@@ -51,6 +53,7 @@
  * @param fontStyle The typeface variant to use when drawing the letters (e.g. italic).
  * @param fontSynthesis Whether to synthesize font weight and/or style when the requested weight or
  *   style cannot be found in the provided font family.
+ * @param letterSpacing The amount of space (in em) to add between each letter.
  */
 class CurvedTextStyle(
     val background: Color = Color.Unspecified,
@@ -59,7 +62,8 @@
     val fontFamily: FontFamily? = null,
     val fontWeight: FontWeight? = null,
     val fontStyle: FontStyle? = null,
-    val fontSynthesis: FontSynthesis? = null
+    val fontSynthesis: FontSynthesis? = null,
+    val letterSpacing: TextUnit = TextUnit.Unspecified,
 ) {
     /**
      * Styling configuration for a curved text.
@@ -82,11 +86,38 @@
     ) : this(background, color, fontSize, null)
 
     /**
+     * @param background The background color for the text.
+     * @param color The text color.
+     * @param fontSize The size of glyphs (in logical pixels) to use when painting the text. This
+     *   may be [TextUnit.Unspecified] for inheriting from another [CurvedTextStyle].
+     * @param fontFamily The font family to be used when rendering the text.
+     * @param fontWeight The thickness of the glyphs, in a range of [1, 1000]. see [FontWeight]
+     * @param fontStyle The typeface variant to use when drawing the letters (e.g. italic).
+     * @param fontSynthesis Whether to synthesize font weight and/or style when the requested weight
+     *   or style cannot be found in the provided font family.
+     */
+    @Deprecated(
+        "This overload is provided for backwards compatibility with Compose for " +
+            "Wear OS 1.4. A newer overload is available with an additional letter spacing " +
+            "parameter.",
+        level = DeprecationLevel.HIDDEN
+    )
+    constructor(
+        background: Color = Color.Unspecified,
+        color: Color = Color.Unspecified,
+        fontSize: TextUnit = TextUnit.Unspecified,
+        fontFamily: FontFamily? = null,
+        fontWeight: FontWeight? = null,
+        fontStyle: FontStyle? = null,
+        fontSynthesis: FontSynthesis? = null
+    ) : this(background, color, fontSize, fontFamily, fontWeight, fontStyle, fontSynthesis)
+
+    /**
      * Create a curved text style from the given text style.
      *
      * Note that not all parameters in the text style will be used, only [TextStyle.color],
      * [TextStyle.fontSize], [TextStyle.background], [TextStyle.fontFamily], [TextStyle.fontWeight],
-     * [TextStyle.fontStyle] and [TextStyle.fontSynthesis].
+     * [TextStyle.fontStyle], [TextStyle.fontSynthesis] and [TextStyle.letterSpacing].
      */
     constructor(
         style: TextStyle
@@ -97,7 +128,8 @@
         style.fontFamily,
         style.fontWeight,
         style.fontStyle,
-        style.fontSynthesis
+        style.fontSynthesis,
+        style.letterSpacing
     )
 
     /**
@@ -115,12 +147,14 @@
 
         return CurvedTextStyle(
             color = other.color.takeOrElse { this.color },
-            fontSize = if (!other.fontSize.isUnspecified) other.fontSize else this.fontSize,
+            fontSize = if (other.fontSize.isSpecified) other.fontSize else this.fontSize,
             background = other.background.takeOrElse { this.background },
             fontFamily = other.fontFamily ?: this.fontFamily,
             fontWeight = other.fontWeight ?: this.fontWeight,
             fontStyle = other.fontStyle ?: this.fontStyle,
             fontSynthesis = other.fontSynthesis ?: this.fontSynthesis,
+            letterSpacing =
+                if (other.letterSpacing.isSpecified) other.letterSpacing else this.letterSpacing,
         )
     }
 
@@ -143,10 +177,15 @@
             fontFamily = this.fontFamily,
             fontWeight = this.fontWeight,
             fontStyle = this.fontStyle,
-            fontSynthesis = this.fontSynthesis
+            fontSynthesis = this.fontSynthesis,
+            letterSpacing = this.letterSpacing
         )
     }
 
+    @Deprecated(
+        "This overload is provided for backwards compatibility with Compose for " +
+            "Wear OS 1.4. A newer overload is available with additional letter spacing parameter."
+    )
     fun copy(
         background: Color = this.background,
         color: Color = this.color,
@@ -163,7 +202,30 @@
             fontFamily = fontFamily,
             fontWeight = fontWeight,
             fontStyle = fontStyle,
-            fontSynthesis = fontSynthesis
+            fontSynthesis = fontSynthesis,
+            letterSpacing = this.letterSpacing
+        )
+    }
+
+    fun copy(
+        background: Color = this.background,
+        color: Color = this.color,
+        fontSize: TextUnit = this.fontSize,
+        fontFamily: FontFamily? = this.fontFamily,
+        fontWeight: FontWeight? = this.fontWeight,
+        fontStyle: FontStyle? = this.fontStyle,
+        fontSynthesis: FontSynthesis? = this.fontSynthesis,
+        letterSpacing: TextUnit = this.letterSpacing
+    ): CurvedTextStyle {
+        return CurvedTextStyle(
+            background = background,
+            color = color,
+            fontSize = fontSize,
+            fontFamily = fontFamily,
+            fontWeight = fontWeight,
+            fontStyle = fontStyle,
+            fontSynthesis = fontSynthesis,
+            letterSpacing = letterSpacing
         )
     }
 
@@ -177,7 +239,8 @@
             fontFamily == other.fontFamily &&
             fontWeight == other.fontWeight &&
             fontStyle == other.fontStyle &&
-            fontSynthesis == other.fontSynthesis
+            fontSynthesis == other.fontSynthesis &&
+            letterSpacing == other.letterSpacing
     }
 
     override fun hashCode(): Int {
@@ -188,6 +251,7 @@
         result = 31 * result + fontWeight.hashCode()
         result = 31 * result + fontStyle.hashCode()
         result = 31 * result + fontSynthesis.hashCode()
+        result = 31 * result + letterSpacing.hashCode()
         return result
     }
 
@@ -200,6 +264,7 @@
             "fontWeight=$fontWeight, " +
             "fontStyle=$fontStyle, " +
             "fontSynthesis=$fontSynthesis, " +
+            "letterSpacing=$letterSpacing, " +
             ")"
     }
 }
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/ScrollInfoProvider.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/ScrollInfoProvider.kt
new file mode 100644
index 0000000..6fb7c9c
--- /dev/null
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/ScrollInfoProvider.kt
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.foundation
+
+import androidx.compose.foundation.ScrollState
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyListState
+import androidx.compose.ui.util.fastFirstOrNull
+import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
+import androidx.wear.compose.foundation.lazy.ScalingLazyListAnchorType
+import androidx.wear.compose.foundation.lazy.ScalingLazyListState
+import androidx.wear.compose.foundation.lazy.startOffset
+
+/**
+ * An interface for providing scroll information for different scrollable containers, such lists.
+ * Used for scrolling away, showing, hiding or scaling screen elements based on scrollable state.
+ *
+ * [ScrollInfoProvider] can be used to create a ScrollAway modifier, typically applied to an object
+ * that appears at the top of the screen to scroll it away vertically when a list is scrolled
+ * upwards. The scrolled offset is typically calculated with reference to the position of an anchor
+ * e.g. the top item.
+ */
+interface ScrollInfoProvider {
+    /**
+     * Whether it is valid to scroll away the anchor item with the current configuration, For
+     * example, if the selected anchor item does not exist, it is not valid to scroll away.
+     */
+    val isScrollAwayValid: Boolean
+
+    /** Whether the container is currently scrollable. */
+    val isScrollable: Boolean
+
+    /**
+     * Whether the list is currently scrolling (which can be used to show/hide a scroll indicator or
+     * time text during the scroll operation).
+     */
+    val isScrollInProgress: Boolean
+
+    /**
+     * The amount that the anchor item has been scrolled upwards in the y direction (in Pixels),
+     * relative to the initial position of the scrolling container (so >= zero). In the event that
+     * the anchor item is no longer visible on the screen and its offset cannot be calculated, the
+     * returned offset is Float.NaN.
+     */
+    val anchorItemOffset: Float
+}
+
+/**
+ * Extension function for creating a [ScrollInfoProvider] from a [ScalingLazyListState], for use
+ * with [ScalingLazyColumn] - used to create a ScrollAway modifier directly that can be applied to
+ * an object that appears at the top of the screen, to scroll it away vertically when the
+ * [ScalingLazyColumn] is scrolled upwards.
+ */
+fun ScalingLazyListState.toScrollAwayInfoProvider(): ScrollInfoProvider =
+    ScalingLazyListStateScrollInfoProvider(this)
+
+/**
+ * Extension function for creating a [ScrollInfoProvider] from a [LazyListState], for use with
+ * [LazyColumn] - used to create a ScrollAway modifier directly that can be applied to an object
+ * that appears at the top of the screen, to scroll it away vertically when the [LazyColumn] is
+ * scrolled upwards.
+ */
+fun LazyListState.toScrollAwayInfoProvider(): ScrollInfoProvider =
+    LazyListStateScrollInfoProvider(this)
+
+/**
+ * Extension function for creating a [ScrollInfoProvider] from a [ScrollState], for use with
+ * [Column] - used to create a ScrollAway modifier directly that can be applied to an object that
+ * appears at the top of the screen, to scroll it away vertically when the [Column] is scrolled
+ * upwards.
+ */
+fun ScrollState.toScrollAwayInfoProvider(): ScrollInfoProvider = ScrollStateScrollInfoProvider(this)
+
+// Implementation of [ScrollAwayInfoProvider] for [ScalingLazyColumn].
+// Being in Foundation, this implementation has access to the ScalingLazyListState
+// auto-centering params, which are internal.
+private class ScalingLazyListStateScrollInfoProvider(val state: ScalingLazyListState) :
+    ScrollInfoProvider {
+    override val isScrollAwayValid
+        get() =
+            state.layoutInfo.totalItemsCount > (state.config.value?.autoCentering?.itemIndex ?: 1)
+
+    override val isScrollable
+        get() =
+            state.layoutInfo.visibleItemsInfo.isNotEmpty() &&
+                (state.canScrollBackward || state.canScrollForward)
+
+    override val isScrollInProgress
+        get() = state.isScrollInProgress
+
+    override val anchorItemOffset: Float
+        get() {
+            val layoutInfo = state.layoutInfo
+            val autoCentering = state.config.value?.autoCentering
+            return layoutInfo.visibleItemsInfo
+                .fastFirstOrNull { it.index == (autoCentering?.itemIndex ?: 1) }
+                ?.let {
+                    val startOffset = it.startOffset(ScalingLazyListAnchorType.ItemStart)
+                    if (initialStartOffset == null || startOffset > initialStartOffset!!) {
+                        initialStartOffset = startOffset
+                    }
+                    -it.offset + initialStartOffset!!
+                } ?: Float.NaN
+        }
+
+    override fun toString(): String {
+        return "ScalingLazyColumnScrollAwayInfoProvider(isScrollAwayValid=$isScrollAwayValid, " +
+            "isScrollInProgress=$isScrollInProgress, " +
+            "trackedItemOffset=$anchorItemOffset)"
+    }
+
+    private var initialStartOffset: Float? = null
+}
+
+// Implementation of [ScrollAwayInfoProvider] for [LazyColumn].
+private class LazyListStateScrollInfoProvider(val state: LazyListState) : ScrollInfoProvider {
+    override val isScrollAwayValid
+        get() = state.layoutInfo.totalItemsCount > 0
+
+    override val isScrollable
+        get() = state.layoutInfo.totalItemsCount > 0
+
+    override val isScrollInProgress
+        get() = state.isScrollInProgress
+
+    override val anchorItemOffset
+        get() =
+            state.layoutInfo.visibleItemsInfo
+                .fastFirstOrNull { it.index == 0 }
+                ?.let { -it.offset.toFloat() } ?: Float.NaN
+
+    override fun toString(): String {
+        return "LazyColumnScrollAwayInfoProvider(isScrollAwayValid=$isScrollAwayValid, " +
+            "isScrollInProgress=$isScrollInProgress, " +
+            "trackedItemOffset=$anchorItemOffset)"
+    }
+}
+
+// Implementation of [ScrollAwayInfoProvider] for [Column]
+private class ScrollStateScrollInfoProvider(val state: ScrollState) : ScrollInfoProvider {
+    override val isScrollAwayValid: Boolean
+        get() = true
+
+    override val isScrollable = state.maxValue != 0
+    // Work around the default implementation of ScrollState not providing a useful
+    // isScrollInProgress
+    private var prevOffset: Int? = null
+    override val isScrollInProgress
+        get() =
+            state.value.let { currentOffset ->
+                (state.isScrollInProgress || (prevOffset != null && prevOffset != currentOffset))
+                    .also { prevOffset = currentOffset }
+            }
+
+    override val anchorItemOffset: Float
+        get() = state.value.toFloat()
+
+    override fun toString(): String =
+        "DefaultScrollAwayInfoProvider(isScrollAwayValid=$isScrollAwayValid, " +
+            "isScrollInProgress=$isScrollInProgress, " +
+            "trackedItemOffset=$anchorItemOffset)"
+}
diff --git a/wear/compose/compose-foundation/src/test/kotlin/androidx/wear/compose/foundation/CurvedTextStyleTest.kt b/wear/compose/compose-foundation/src/test/kotlin/androidx/wear/compose/foundation/CurvedTextStyleTest.kt
index 3c9dab3..1dfe2ed 100644
--- a/wear/compose/compose-foundation/src/test/kotlin/androidx/wear/compose/foundation/CurvedTextStyleTest.kt
+++ b/wear/compose/compose-foundation/src/test/kotlin/androidx/wear/compose/foundation/CurvedTextStyleTest.kt
@@ -22,6 +22,7 @@
 import androidx.compose.ui.text.font.FontSynthesis
 import androidx.compose.ui.text.font.FontWeight
 import androidx.compose.ui.unit.TextUnit
+import androidx.compose.ui.unit.em
 import androidx.compose.ui.unit.isUnspecified
 import androidx.compose.ui.unit.sp
 import org.junit.Assert.assertEquals
@@ -44,6 +45,7 @@
         assertNull(style.fontFamily)
         assertNull(style.fontStyle)
         assertNull(style.fontSynthesis)
+        assertTrue(style.letterSpacing.isUnspecified)
     }
 
     @Test
@@ -110,6 +112,15 @@
     }
 
     @Test
+    fun `constructor with customized letter spacing`() {
+        val letterSpacing = 0.01f.em
+
+        val style = CurvedTextStyle(letterSpacing = letterSpacing)
+
+        assertEquals(style.letterSpacing, letterSpacing)
+    }
+
+    @Test
     fun `merge with empty other should return this`() {
         val style = CurvedTextStyle()
 
@@ -250,4 +261,23 @@
 
         assertEquals(newStyle.fontSynthesis, otherStyle.fontSynthesis)
     }
+
+    @Test
+    fun `merge with other's letter spacing is unspecified should use this' letter spacing`() {
+        val style = CurvedTextStyle(letterSpacing = 0.123f.em)
+
+        val newStyle = style.merge(CurvedTextStyle(letterSpacing = TextUnit.Unspecified))
+
+        assertEquals(newStyle.letterSpacing, style.letterSpacing)
+    }
+
+    @Test
+    fun `merge with other's letter spacing is set should use other's letter spacing`() {
+        val style = CurvedTextStyle(letterSpacing = 0.123f.em)
+        val otherStyle = CurvedTextStyle(letterSpacing = 0.345f.em)
+
+        val newStyle = style.merge(otherStyle)
+
+        assertEquals(newStyle.letterSpacing, otherStyle.letterSpacing)
+    }
 }
diff --git a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ScalingLazyColumnBenchmark.kt b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ScalingLazyColumnBenchmark.kt
deleted file mode 100644
index 83ed677..0000000
--- a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ScalingLazyColumnBenchmark.kt
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.wear.compose.material.benchmark
-
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.requiredSize
-import androidx.compose.runtime.Composable
-import androidx.compose.testutils.LayeredComposeTestCase
-import androidx.compose.testutils.benchmark.ComposeBenchmarkRule
-import androidx.compose.testutils.benchmark.benchmarkDrawPerf
-import androidx.compose.testutils.benchmark.benchmarkFirstCompose
-import androidx.compose.testutils.benchmark.benchmarkLayoutPerf
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.dp
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.LargeTest
-import androidx.wear.compose.material.MaterialTheme
-import androidx.wear.compose.material.ScalingLazyColumn
-import androidx.wear.compose.material.Text
-import androidx.wear.compose.material.rememberScalingLazyListState
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-
-/** Benchmark for Wear Compose ScalingLazyColumn. */
-@LargeTest
-@RunWith(AndroidJUnit4::class)
-class ScalingLazyColumnBenchmark {
-
-    @get:Rule val benchmarkRule = ComposeBenchmarkRule()
-
-    private val scalingLazyColumnCaseFactory = { ScalingLazyColumnTestCase() }
-
-    @Test
-    fun first_compose() {
-        benchmarkRule.benchmarkFirstCompose(scalingLazyColumnCaseFactory)
-    }
-
-    @Test
-    fun first_measure() {
-        benchmarkRule.benchmarkFirstMeasure(scalingLazyColumnCaseFactory)
-    }
-
-    @Test
-    fun first_layout() {
-        benchmarkRule.benchmarkFirstLayout(scalingLazyColumnCaseFactory)
-    }
-
-    @Test
-    fun first_draw() {
-        benchmarkRule.benchmarkFirstDraw(scalingLazyColumnCaseFactory)
-    }
-
-    @Test
-    fun layout() {
-        benchmarkRule.benchmarkLayoutPerf(scalingLazyColumnCaseFactory)
-    }
-
-    @Test
-    fun draw() {
-        benchmarkRule.benchmarkDrawPerf(scalingLazyColumnCaseFactory)
-    }
-}
-
-@Suppress("DEPRECATION")
-internal class ScalingLazyColumnTestCase : LayeredComposeTestCase() {
-    private var itemSizeDp: Dp = 10.dp
-    private var defaultItemSpacingDp: Dp = 4.dp
-
-    @Composable
-    override fun MeasuredContent() {
-        ScalingLazyColumn(
-            state = rememberScalingLazyListState(),
-            modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
-        ) {
-            items(10) { it -> Box(Modifier.requiredSize(itemSizeDp)) { Text(text = "Item $it") } }
-        }
-    }
-
-    @Composable
-    override fun ContentWrappers(content: @Composable () -> Unit) {
-        MaterialTheme { content() }
-    }
-}
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/CurvedText.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/CurvedText.kt
index c5738cb..4c5fc40 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/CurvedText.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/CurvedText.kt
@@ -25,6 +25,7 @@
 import androidx.compose.ui.text.font.FontWeight
 import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.unit.TextUnit
+import androidx.compose.ui.unit.em
 import androidx.wear.compose.foundation.CurvedDirection
 import androidx.wear.compose.foundation.CurvedLayout
 import androidx.wear.compose.foundation.CurvedModifier
@@ -115,7 +116,8 @@
                 fontWeight = fontWeight,
                 fontStyle = fontStyle,
                 fontSynthesis = fontSynthesis,
-                background = background
+                background = background,
+                letterSpacing = 0.em // keep backward compatibility.
             )
         )
     }
diff --git a/wear/compose/compose-material3/api/current.txt b/wear/compose/compose-material3/api/current.txt
index 532e6c3..1c84c9f 100644
--- a/wear/compose/compose-material3/api/current.txt
+++ b/wear/compose/compose-material3/api/current.txt
@@ -1,6 +1,24 @@
 // Signature format: 4.0
 package androidx.wear.compose.material3 {
 
+  public final class AnimatedTextDefaults {
+    field public static final int CacheSize = 5; // 0x5
+    field public static final androidx.wear.compose.material3.AnimatedTextDefaults INSTANCE;
+  }
+
+  @RequiresApi(31) public final class AnimatedTextFontRegistry {
+    ctor public AnimatedTextFontRegistry(androidx.compose.ui.text.TextStyle textStyle, androidx.compose.ui.text.font.FontVariation.Settings startFontVariationSettings, androidx.compose.ui.text.font.FontVariation.Settings endFontVariationSettings, long startFontSize, long endFontSize, androidx.compose.ui.unit.Density density, androidx.compose.ui.text.font.FontFamily.Resolver fontFamilyResolver, optional long contentColor, optional int cacheSize);
+  }
+
+  public final class AnimatedTextKt {
+    method @RequiresApi(31) @androidx.compose.runtime.Composable public static void AnimatedText(String text, androidx.wear.compose.material3.AnimatedTextFontRegistry fontRegistry, kotlin.jvm.functions.Function0<java.lang.Float> progressFraction, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment contentAlignment);
+    method @RequiresApi(31) @androidx.compose.runtime.Composable public static androidx.wear.compose.material3.AnimatedTextFontRegistry rememberAnimatedTextFontRegistry(androidx.compose.ui.text.font.FontVariation.Settings startFontVariationSettings, androidx.compose.ui.text.font.FontVariation.Settings endFontVariationSettings, optional androidx.compose.ui.text.TextStyle textStyle, optional long startFontSize, optional long endFontSize);
+  }
+
+  public final class AppScaffoldKt {
+    method @androidx.compose.runtime.Composable public static void AppScaffold(optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> timeText, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+  }
+
   @androidx.compose.runtime.Immutable public final class ButtonColors {
     ctor public ButtonColors(androidx.compose.ui.graphics.painter.Painter containerPainter, long contentColor, long secondaryContentColor, long iconColor, androidx.compose.ui.graphics.painter.Painter disabledContainerPainter, long disabledContentColor, long disabledSecondaryContentColor, long disabledIconColor);
     ctor public ButtonColors(long containerColor, long contentColor, long secondaryContentColor, long iconColor, long disabledContainerColor, long disabledContentColor, long disabledSecondaryContentColor, long disabledIconColor);
@@ -38,6 +56,10 @@
     method public androidx.compose.foundation.layout.PaddingValues getCompactButtonTapTargetPadding();
     method public float getCompactButtonVerticalPadding();
     method public androidx.compose.foundation.layout.PaddingValues getContentPadding();
+    method public float getEdgeButtonHeightExtraSmall();
+    method public float getEdgeButtonHeightLarge();
+    method public float getEdgeButtonHeightMedium();
+    method public float getEdgeButtonHeightSmall();
     method public float getHeight();
     method public float getIconSize();
     method public float getLargeIconSize();
@@ -55,6 +77,10 @@
     property public final androidx.compose.foundation.layout.PaddingValues CompactButtonTapTargetPadding;
     property public final float CompactButtonVerticalPadding;
     property public final androidx.compose.foundation.layout.PaddingValues ContentPadding;
+    property public final float EdgeButtonHeightExtraSmall;
+    property public final float EdgeButtonHeightLarge;
+    property public final float EdgeButtonHeightMedium;
+    property public final float EdgeButtonHeightSmall;
     property public final float Height;
     property public final float IconSize;
     property public final float LargeIconSize;
@@ -181,31 +207,6 @@
     method @androidx.compose.runtime.Composable public static void SplitCheckboxButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, String? toggleContentDescription, kotlin.jvm.functions.Function0<kotlin.Unit> onContainerClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.SplitCheckboxButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? toggleInteractionSource, optional androidx.compose.foundation.interaction.MutableInteractionSource? containerInteractionSource, optional String? containerClickLabel, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit>? secondaryLabel, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> label);
   }
 
-  @androidx.compose.runtime.Immutable public final class CheckboxColors {
-    ctor public CheckboxColors(long checkedBoxColor, long checkedCheckmarkColor, long uncheckedBoxColor, long uncheckedCheckmarkColor, long disabledCheckedBoxColor, long disabledCheckedCheckmarkColor, long disabledUncheckedBoxColor, long disabledUncheckedCheckmarkColor);
-    method public long getCheckedBoxColor();
-    method public long getCheckedCheckmarkColor();
-    method public long getDisabledCheckedBoxColor();
-    method public long getDisabledCheckedCheckmarkColor();
-    method public long getDisabledUncheckedBoxColor();
-    method public long getDisabledUncheckedCheckmarkColor();
-    method public long getUncheckedBoxColor();
-    method public long getUncheckedCheckmarkColor();
-    property public final long checkedBoxColor;
-    property public final long checkedCheckmarkColor;
-    property public final long disabledCheckedBoxColor;
-    property public final long disabledCheckedCheckmarkColor;
-    property public final long disabledUncheckedBoxColor;
-    property public final long disabledUncheckedCheckmarkColor;
-    property public final long uncheckedBoxColor;
-    property public final long uncheckedCheckmarkColor;
-  }
-
-  public final class CheckboxDefaults {
-    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.CheckboxColors colors(optional long checkedBoxColor, optional long checkedCheckmarkColor, optional long uncheckedBoxColor, optional long uncheckedCheckmarkColor, optional long disabledCheckedBoxColor, optional long disabledCheckedCheckmarkColor, optional long disabledUncheckedBoxColor, optional long disabledUncheckedCheckmarkColor);
-    field public static final androidx.wear.compose.material3.CheckboxDefaults INSTANCE;
-  }
-
   @androidx.compose.runtime.Immutable @androidx.compose.runtime.Stable public final class ColorScheme {
     ctor public ColorScheme(optional long primary, optional long primaryDim, optional long primaryContainer, optional long onPrimary, optional long onPrimaryContainer, optional long secondary, optional long secondaryDim, optional long secondaryContainer, optional long onSecondary, optional long onSecondaryContainer, optional long tertiary, optional long tertiaryDim, optional long tertiaryContainer, optional long onTertiary, optional long onTertiaryContainer, optional long surfaceContainerLow, optional long surfaceContainer, optional long surfaceContainerHigh, optional long onSurface, optional long onSurfaceVariant, optional long outline, optional long outlineVariant, optional long background, optional long onBackground, optional long error, optional long onError, optional long errorContainer, optional long onErrorContainer);
     method public androidx.wear.compose.material3.ColorScheme copy(optional long primary, optional long primaryDim, optional long primaryContainer, optional long onPrimary, optional long onPrimaryContainer, optional long secondary, optional long secondaryDim, optional long secondaryContainer, optional long onSecondary, optional long onSecondaryContainer, optional long tertiary, optional long tertiaryDim, optional long tertiaryContainer, optional long onTertiary, optional long onTertiaryContainer, optional long surfaceContainerLow, optional long surfaceContainer, optional long surfaceContainerHigh, optional long onSurface, optional long onSurfaceVariant, optional long outline, optional long outlineVariant, optional long background, optional long onBackground, optional long error, optional long onError, optional long errorContainer, optional long onErrorContainer);
@@ -287,6 +288,10 @@
     method public static void curvedText(androidx.wear.compose.foundation.CurvedScope, String text, optional androidx.wear.compose.foundation.CurvedModifier modifier, optional float maxSweepAngle, optional long background, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.wear.compose.foundation.CurvedTextStyle? style, optional androidx.wear.compose.foundation.CurvedDirection.Angular? angularDirection, optional int overflow);
   }
 
+  public final class EdgeButtonKt {
+    method @androidx.compose.runtime.Composable public static void EdgeButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional float buttonHeight, optional boolean enabled, optional androidx.wear.compose.material3.ButtonColors colors, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+  }
+
   @SuppressCompatibility @kotlin.RequiresOptIn(message="This Wear Material3 API is experimental and is likely to change or to be removed in" + " the future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalWearMaterial3Api {
   }
 
@@ -624,6 +629,23 @@
     method @androidx.compose.runtime.Stable public static androidx.compose.foundation.IndicationNodeFactory ripple(optional boolean bounded, optional float radius, optional long color);
   }
 
+  public final class ScreenScaffoldKt {
+    method @androidx.compose.runtime.Composable public static void ScreenScaffold(androidx.compose.foundation.lazy.LazyListState scrollState, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? timeText, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit>? scrollIndicator, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void ScreenScaffold(androidx.compose.foundation.ScrollState scrollState, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? timeText, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit>? scrollIndicator, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void ScreenScaffold(optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? timeText, optional androidx.wear.compose.foundation.ScrollInfoProvider? scrollInfoProvider, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit>? scrollIndicator, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void ScreenScaffold(androidx.wear.compose.foundation.lazy.ScalingLazyListState scrollState, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? timeText, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit>? scrollIndicator, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+  }
+
+  public enum ScreenStage {
+    enum_constant public static final androidx.wear.compose.material3.ScreenStage Idle;
+    enum_constant public static final androidx.wear.compose.material3.ScreenStage New;
+    enum_constant public static final androidx.wear.compose.material3.ScreenStage Scrolling;
+  }
+
+  public final class ScrollAwayKt {
+    method public static androidx.compose.ui.Modifier scrollAway(androidx.compose.ui.Modifier, androidx.wear.compose.foundation.ScrollInfoProvider scrollInfoProvider, kotlin.jvm.functions.Function0<? extends androidx.wear.compose.material3.ScreenStage> screenStage);
+  }
+
   public final class ScrollIndicatorDefaults {
     method public androidx.compose.animation.core.AnimationSpec<java.lang.Float> getPositionAnimationSpec();
     property public final androidx.compose.animation.core.AnimationSpec<java.lang.Float> PositionAnimationSpec;
@@ -762,40 +784,66 @@
     property public final long unselectedSplitContainerColor;
   }
 
-  public final class SplitToggleButtonColors {
-    ctor public SplitToggleButtonColors(long checkedContainerColor, long checkedContentColor, long checkedSecondaryContentColor, long checkedSplitContainerColor, long uncheckedContainerColor, long uncheckedContentColor, long uncheckedSecondaryContentColor, long uncheckedSplitContainerColor, long disabledCheckedContainerColor, long disabledCheckedContentColor, long disabledCheckedSecondaryContentColor, long disabledCheckedSplitContainerColor, long disabledUncheckedContainerColor, long disabledUncheckedContentColor, long disabledUncheckedSecondaryContentColor, long disabledUncheckedSplitContainerColor);
+  public final class SplitSwitchButtonColors {
+    ctor public SplitSwitchButtonColors(long checkedContainerColor, long checkedContentColor, long checkedSecondaryContentColor, long checkedSplitContainerColor, long checkedThumbColor, long checkedThumbIconColor, long checkedTrackColor, long checkedTrackBorderColor, long uncheckedContainerColor, long uncheckedContentColor, long uncheckedSecondaryContentColor, long uncheckedSplitContainerColor, long uncheckedThumbColor, long uncheckedTrackColor, long uncheckedTrackBorderColor, long disabledCheckedContainerColor, long disabledCheckedContentColor, long disabledCheckedSecondaryContentColor, long disabledCheckedSplitContainerColor, long disabledCheckedThumbColor, long disabledCheckedThumbIconColor, long disabledCheckedTrackColor, long disabledCheckedTrackBorderColor, long disabledUncheckedContainerColor, long disabledUncheckedContentColor, long disabledUncheckedSecondaryContentColor, long disabledUncheckedSplitContainerColor, long disabledUncheckedThumbColor, long disabledUncheckedTrackBorderColor);
     method public long getCheckedContainerColor();
     method public long getCheckedContentColor();
     method public long getCheckedSecondaryContentColor();
     method public long getCheckedSplitContainerColor();
+    method public long getCheckedThumbColor();
+    method public long getCheckedThumbIconColor();
+    method public long getCheckedTrackBorderColor();
+    method public long getCheckedTrackColor();
     method public long getDisabledCheckedContainerColor();
     method public long getDisabledCheckedContentColor();
     method public long getDisabledCheckedSecondaryContentColor();
     method public long getDisabledCheckedSplitContainerColor();
+    method public long getDisabledCheckedThumbColor();
+    method public long getDisabledCheckedThumbIconColor();
+    method public long getDisabledCheckedTrackBorderColor();
+    method public long getDisabledCheckedTrackColor();
     method public long getDisabledUncheckedContainerColor();
     method public long getDisabledUncheckedContentColor();
     method public long getDisabledUncheckedSecondaryContentColor();
     method public long getDisabledUncheckedSplitContainerColor();
+    method public long getDisabledUncheckedThumbColor();
+    method public long getDisabledUncheckedTrackBorderColor();
     method public long getUncheckedContainerColor();
     method public long getUncheckedContentColor();
     method public long getUncheckedSecondaryContentColor();
     method public long getUncheckedSplitContainerColor();
+    method public long getUncheckedThumbColor();
+    method public long getUncheckedTrackBorderColor();
+    method public long getUncheckedTrackColor();
     property public final long checkedContainerColor;
     property public final long checkedContentColor;
     property public final long checkedSecondaryContentColor;
     property public final long checkedSplitContainerColor;
+    property public final long checkedThumbColor;
+    property public final long checkedThumbIconColor;
+    property public final long checkedTrackBorderColor;
+    property public final long checkedTrackColor;
     property public final long disabledCheckedContainerColor;
     property public final long disabledCheckedContentColor;
     property public final long disabledCheckedSecondaryContentColor;
     property public final long disabledCheckedSplitContainerColor;
+    property public final long disabledCheckedThumbColor;
+    property public final long disabledCheckedThumbIconColor;
+    property public final long disabledCheckedTrackBorderColor;
+    property public final long disabledCheckedTrackColor;
     property public final long disabledUncheckedContainerColor;
     property public final long disabledUncheckedContentColor;
     property public final long disabledUncheckedSecondaryContentColor;
     property public final long disabledUncheckedSplitContainerColor;
+    property public final long disabledUncheckedThumbColor;
+    property public final long disabledUncheckedTrackBorderColor;
     property public final long uncheckedContainerColor;
     property public final long uncheckedContentColor;
     property public final long uncheckedSecondaryContentColor;
     property public final long uncheckedSplitContainerColor;
+    property public final long uncheckedThumbColor;
+    property public final long uncheckedTrackBorderColor;
+    property public final long uncheckedTrackColor;
   }
 
   @SuppressCompatibility @androidx.wear.compose.material3.ExperimentalWearMaterial3Api public final class StepperDefaults {
@@ -816,45 +864,85 @@
     method @androidx.compose.runtime.Composable public static void SwipeToDismissBox(kotlin.jvm.functions.Function0<kotlin.Unit> onDismissed, optional androidx.compose.ui.Modifier modifier, optional androidx.wear.compose.foundation.SwipeToDismissBoxState state, optional long backgroundScrimColor, optional long contentScrimColor, optional Object backgroundKey, optional Object contentKey, optional boolean userSwipeEnabled, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.layout.BoxScope,? super java.lang.Boolean,kotlin.Unit> content);
   }
 
-  @androidx.compose.runtime.Immutable public final class SwitchColors {
-    ctor public SwitchColors(long checkedThumbColor, long checkedThumbIconColor, long checkedTrackColor, long checkedTrackBorderColor, long uncheckedThumbColor, long uncheckedThumbIconColor, long uncheckedTrackColor, long uncheckedTrackBorderColor, long disabledCheckedThumbColor, long disabledCheckedThumbIconColor, long disabledCheckedTrackColor, long disabledCheckedTrackBorderColor, long disabledUncheckedThumbColor, long disabledUncheckedThumbIconColor, long disabledUncheckedTrackColor, long disabledUncheckedTrackBorderColor);
+  @androidx.compose.runtime.Immutable public final class SwitchButtonColors {
+    ctor public SwitchButtonColors(long checkedContainerColor, long checkedContentColor, long checkedSecondaryContentColor, long checkedIconColor, long checkedThumbColor, long checkedThumbIconColor, long checkedTrackBorderColor, long checkedTrackColor, long uncheckedContainerColor, long uncheckedContentColor, long uncheckedSecondaryContentColor, long uncheckedIconColor, long uncheckedThumbColor, long uncheckedTrackColor, long uncheckedTrackBorderColor, long disabledCheckedContainerColor, long disabledCheckedContentColor, long disabledCheckedSecondaryContentColor, long disabledCheckedIconColor, long disabledCheckedThumbColor, long disabledCheckedThumbIconColor, long disabledCheckedTrackColor, long disabledCheckedTrackBorderColor, long disabledUncheckedContainerColor, long disabledUncheckedContentColor, long disabledUncheckedSecondaryContentColor, long disabledUncheckedIconColor, long disabledUncheckedThumbColor, long disabledUncheckedTrackBorderColor);
+    method public long getCheckedContainerColor();
+    method public long getCheckedContentColor();
+    method public long getCheckedIconColor();
+    method public long getCheckedSecondaryContentColor();
     method public long getCheckedThumbColor();
     method public long getCheckedThumbIconColor();
     method public long getCheckedTrackBorderColor();
     method public long getCheckedTrackColor();
+    method public long getDisabledCheckedContainerColor();
+    method public long getDisabledCheckedContentColor();
+    method public long getDisabledCheckedIconColor();
+    method public long getDisabledCheckedSecondaryContentColor();
     method public long getDisabledCheckedThumbColor();
     method public long getDisabledCheckedThumbIconColor();
     method public long getDisabledCheckedTrackBorderColor();
     method public long getDisabledCheckedTrackColor();
+    method public long getDisabledUncheckedContainerColor();
+    method public long getDisabledUncheckedContentColor();
+    method public long getDisabledUncheckedIconColor();
+    method public long getDisabledUncheckedSecondaryContentColor();
     method public long getDisabledUncheckedThumbColor();
-    method public long getDisabledUncheckedThumbIconColor();
     method public long getDisabledUncheckedTrackBorderColor();
-    method public long getDisabledUncheckedTrackColor();
+    method public long getUncheckedContainerColor();
+    method public long getUncheckedContentColor();
+    method public long getUncheckedIconColor();
+    method public long getUncheckedSecondaryContentColor();
     method public long getUncheckedThumbColor();
-    method public long getUncheckedThumbIconColor();
     method public long getUncheckedTrackBorderColor();
     method public long getUncheckedTrackColor();
+    property public final long checkedContainerColor;
+    property public final long checkedContentColor;
+    property public final long checkedIconColor;
+    property public final long checkedSecondaryContentColor;
     property public final long checkedThumbColor;
     property public final long checkedThumbIconColor;
     property public final long checkedTrackBorderColor;
     property public final long checkedTrackColor;
+    property public final long disabledCheckedContainerColor;
+    property public final long disabledCheckedContentColor;
+    property public final long disabledCheckedIconColor;
+    property public final long disabledCheckedSecondaryContentColor;
     property public final long disabledCheckedThumbColor;
     property public final long disabledCheckedThumbIconColor;
     property public final long disabledCheckedTrackBorderColor;
     property public final long disabledCheckedTrackColor;
+    property public final long disabledUncheckedContainerColor;
+    property public final long disabledUncheckedContentColor;
+    property public final long disabledUncheckedIconColor;
+    property public final long disabledUncheckedSecondaryContentColor;
     property public final long disabledUncheckedThumbColor;
-    property public final long disabledUncheckedThumbIconColor;
     property public final long disabledUncheckedTrackBorderColor;
-    property public final long disabledUncheckedTrackColor;
+    property public final long uncheckedContainerColor;
+    property public final long uncheckedContentColor;
+    property public final long uncheckedIconColor;
+    property public final long uncheckedSecondaryContentColor;
     property public final long uncheckedThumbColor;
-    property public final long uncheckedThumbIconColor;
     property public final long uncheckedTrackBorderColor;
     property public final long uncheckedTrackColor;
   }
 
-  public final class SwitchDefaults {
-    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.SwitchColors colors(optional long checkedThumbColor, optional long checkedThumbIconColor, optional long checkedTrackColor, optional long checkedTrackBorderColor, optional long uncheckedThumbColor, optional long uncheckedThumbIconColor, optional long uncheckedTrackColor, optional long uncheckedTrackBorderColor, optional long disabledCheckedThumbColor, optional long disabledCheckedThumbIconColor, optional long disabledCheckedTrackColor, optional long disabledCheckedTrackBorderColor, optional long disabledUncheckedThumbColor, optional long disabledUncheckedThumbIconColor, optional long disabledUncheckedTrackColor, optional long disabledUncheckedTrackBorderColor);
-    field public static final androidx.wear.compose.material3.SwitchDefaults INSTANCE;
+  public final class SwitchButtonDefaults {
+    method public androidx.compose.foundation.layout.PaddingValues getContentPadding();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getSplitSwitchButtonShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getSwitchButtonShape();
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.SplitSwitchButtonColors splitSwitchButtonColors();
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.SplitSwitchButtonColors splitSwitchButtonColors(optional long checkedContainerColor, optional long checkedContentColor, optional long checkedSecondaryContentColor, optional long checkedSplitContainerColor, optional long checkedThumbColor, optional long checkedThumbIconColor, optional long checkedTrackColor, optional long checkedTrackBorderColor, optional long uncheckedContainerColor, optional long uncheckedContentColor, optional long uncheckedSecondaryContentColor, optional long uncheckedSplitContainerColor, optional long uncheckedThumbColor, optional long uncheckedTrackColor, optional long uncheckedTrackBorderColor, optional long disabledCheckedContainerColor, optional long disabledCheckedContentColor, optional long disabledCheckedSecondaryContentColor, optional long disabledCheckedSplitContainerColor, optional long disabledCheckedThumbColor, optional long disabledCheckedThumbIconColor, optional long disabledCheckedTrackColor, optional long disabledCheckedTrackBorderColor, optional long disabledUncheckedContainerColor, optional long disabledUncheckedContentColor, optional long disabledUncheckedSecondaryContentColor, optional long disabledUncheckedSplitContainerColor, optional long disabledUncheckedThumbColor, optional long disabledUncheckedTrackBorderColor);
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.SwitchButtonColors switchButtonColors();
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.SwitchButtonColors switchButtonColors(optional long checkedContainerColor, optional long checkedContentColor, optional long checkedSecondaryContentColor, optional long checkedIconColor, optional long checkedThumbColor, optional long checkedThumbIconColor, optional long checkedTrackColor, optional long checkedTrackBorderColor, optional long uncheckedContainerColor, optional long uncheckedContentColor, optional long uncheckedSecondaryContentColor, optional long uncheckedIconColor, optional long uncheckedThumbColor, optional long uncheckedTrackColor, optional long uncheckedTrackBorderColor, optional long disabledCheckedContainerColor, optional long disabledCheckedContentColor, optional long disabledCheckedSecondaryContentColor, optional long disabledCheckedIconColor, optional long disabledCheckedThumbColor, optional long disabledCheckedThumbIconColor, optional long disabledCheckedTrackColor, optional long disabledCheckedTrackBorderColor, optional long disabledUncheckedContainerColor, optional long disabledUncheckedContentColor, optional long disabledUncheckedSecondaryContentColor, optional long disabledUncheckedIconColor, optional long disabledUncheckedThumbColor, optional long disabledUncheckedTrackBorderColor);
+    property public final androidx.compose.foundation.layout.PaddingValues ContentPadding;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape splitSwitchButtonShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape switchButtonShape;
+    field public static final androidx.wear.compose.material3.SwitchButtonDefaults INSTANCE;
+  }
+
+  public final class SwitchButtonKt {
+    method @androidx.compose.runtime.Composable public static void SplitSwitchButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, String? toggleContentDescription, kotlin.jvm.functions.Function0<kotlin.Unit> onContainerClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.SplitSwitchButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? toggleInteractionSource, optional androidx.compose.foundation.interaction.MutableInteractionSource? containerInteractionSource, optional String? containerClickLabel, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit>? secondaryLabel, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> label);
+    method @androidx.compose.runtime.Composable public static void SwitchButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.SwitchButtonColors colors, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit>? icon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit>? secondaryLabel, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> label);
   }
 
   @androidx.compose.runtime.Immutable public final class TextButtonColors {
@@ -939,70 +1027,22 @@
 
   @androidx.compose.runtime.Immutable public final class ToggleButtonColors {
     ctor public ToggleButtonColors(long checkedContainerColor, long checkedContentColor, long uncheckedContainerColor, long uncheckedContentColor, long disabledCheckedContainerColor, long disabledCheckedContentColor, long disabledUncheckedContainerColor, long disabledUncheckedContentColor);
-    ctor public ToggleButtonColors(long checkedContainerColor, long checkedContentColor, long checkedSecondaryContentColor, long checkedIconColor, long uncheckedContainerColor, long uncheckedContentColor, long uncheckedSecondaryContentColor, long uncheckedIconColor, long disabledCheckedContainerColor, long disabledCheckedContentColor, long disabledCheckedSecondaryContentColor, long disabledCheckedIconColor, long disabledUncheckedContainerColor, long disabledUncheckedContentColor, long disabledUncheckedSecondaryContentColor, long disabledUncheckedIconColor);
     method public long getCheckedContainerColor();
     method public long getCheckedContentColor();
-    method public long getCheckedIconColor();
-    method public long getCheckedSecondaryContentColor();
     method public long getDisabledCheckedContainerColor();
     method public long getDisabledCheckedContentColor();
-    method public long getDisabledCheckedIconColor();
-    method public long getDisabledCheckedSecondaryContentColor();
     method public long getDisabledUncheckedContainerColor();
     method public long getDisabledUncheckedContentColor();
-    method public long getDisabledUncheckedIconColor();
-    method public long getDisabledUncheckedSecondaryContentColor();
     method public long getUncheckedContainerColor();
     method public long getUncheckedContentColor();
-    method public long getUncheckedIconColor();
-    method public long getUncheckedSecondaryContentColor();
     property public final long checkedContainerColor;
     property public final long checkedContentColor;
-    property public final long checkedIconColor;
-    property public final long checkedSecondaryContentColor;
     property public final long disabledCheckedContainerColor;
     property public final long disabledCheckedContentColor;
-    property public final long disabledCheckedIconColor;
-    property public final long disabledCheckedSecondaryContentColor;
     property public final long disabledUncheckedContainerColor;
     property public final long disabledUncheckedContentColor;
-    property public final long disabledUncheckedIconColor;
-    property public final long disabledUncheckedSecondaryContentColor;
     property public final long uncheckedContainerColor;
     property public final long uncheckedContentColor;
-    property public final long uncheckedIconColor;
-    property public final long uncheckedSecondaryContentColor;
-  }
-
-  public final class ToggleButtonDefaults {
-    method public androidx.compose.foundation.layout.PaddingValues getContentPadding();
-    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getSplitToggleButtonShape();
-    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getToggleButtonShape();
-    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.SplitToggleButtonColors splitToggleButtonColors();
-    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.SplitToggleButtonColors splitToggleButtonColors(optional long checkedContainerColor, optional long checkedContentColor, optional long checkedSecondaryContentColor, optional long checkedSplitContainerColor, optional long uncheckedContainerColor, optional long uncheckedContentColor, optional long uncheckedSecondaryContentColor, optional long uncheckedSplitContainerColor, optional long disabledCheckedContainerColor, optional long disabledCheckedContentColor, optional long disabledCheckedSecondaryContentColor, optional long disabledCheckedSplitContainerColor, optional long disabledUncheckedContainerColor, optional long disabledUncheckedContentColor, optional long disabledUncheckedSecondaryContentColor, optional long disabledUncheckedSplitContainerColor);
-    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.ToggleButtonColors toggleButtonColors();
-    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.ToggleButtonColors toggleButtonColors(optional long checkedContainerColor, optional long checkedContentColor, optional long checkedSecondaryContentColor, optional long checkedIconColor, optional long uncheckedContainerColor, optional long uncheckedContentColor, optional long uncheckedSecondaryContentColor, optional long uncheckedIconColor, optional long disabledCheckedContainerColor, optional long disabledCheckedContentColor, optional long disabledCheckedSecondaryContentColor, optional long disabledCheckedIconColor, optional long disabledUncheckedContainerColor, optional long disabledUncheckedContentColor, optional long disabledUncheckedSecondaryContentColor, optional long disabledUncheckedIconColor);
-    property public final androidx.compose.foundation.layout.PaddingValues ContentPadding;
-    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape splitToggleButtonShape;
-    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape toggleButtonShape;
-    field public static final androidx.wear.compose.material3.ToggleButtonDefaults INSTANCE;
-  }
-
-  public final class ToggleButtonKt {
-    method @androidx.compose.runtime.Composable public static void SplitToggleButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, kotlin.jvm.functions.Function1<? super androidx.wear.compose.material3.ToggleControlScope,kotlin.Unit> toggleControl, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.SplitToggleButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? checkedInteractionSource, optional androidx.compose.foundation.interaction.MutableInteractionSource? clickInteractionSource, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit>? secondaryLabel, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> label);
-    method @androidx.compose.runtime.Composable public static void ToggleButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, kotlin.jvm.functions.Function1<? super androidx.wear.compose.material3.ToggleControlScope,kotlin.Unit> toggleControl, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.ToggleButtonColors colors, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit>? icon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit>? secondaryLabel, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> label);
-  }
-
-  public final class ToggleControlScope {
-    ctor public ToggleControlScope(boolean isEnabled, boolean isChecked);
-    method public boolean isChecked();
-    method public boolean isEnabled();
-    property public final boolean isChecked;
-    property public final boolean isEnabled;
-  }
-
-  public final class ToggleControlsKt {
-    method @androidx.compose.runtime.Composable public static void Switch(androidx.wear.compose.material3.ToggleControlScope, optional androidx.compose.ui.Modifier modifier, optional androidx.wear.compose.material3.SwitchColors colors);
   }
 
   public fun interface TouchExplorationStateProvider {
@@ -1014,8 +1054,10 @@
   }
 
   @androidx.compose.runtime.Immutable public final class Typography {
-    ctor public Typography(optional androidx.compose.ui.text.font.FontFamily defaultFontFamily, optional androidx.compose.ui.text.TextStyle displayLarge, optional androidx.compose.ui.text.TextStyle displayMedium, optional androidx.compose.ui.text.TextStyle displaySmall, optional androidx.compose.ui.text.TextStyle titleLarge, optional androidx.compose.ui.text.TextStyle titleMedium, optional androidx.compose.ui.text.TextStyle titleSmall, optional androidx.compose.ui.text.TextStyle labelLarge, optional androidx.compose.ui.text.TextStyle labelMedium, optional androidx.compose.ui.text.TextStyle labelSmall, optional androidx.compose.ui.text.TextStyle bodyLarge, optional androidx.compose.ui.text.TextStyle bodyMedium, optional androidx.compose.ui.text.TextStyle bodySmall, optional androidx.compose.ui.text.TextStyle bodyExtraSmall);
-    method public androidx.wear.compose.material3.Typography copy(optional androidx.compose.ui.text.TextStyle displayLarge, optional androidx.compose.ui.text.TextStyle displayMedium, optional androidx.compose.ui.text.TextStyle displaySmall, optional androidx.compose.ui.text.TextStyle titleLarge, optional androidx.compose.ui.text.TextStyle titleMedium, optional androidx.compose.ui.text.TextStyle titleSmall, optional androidx.compose.ui.text.TextStyle labelLarge, optional androidx.compose.ui.text.TextStyle labelMedium, optional androidx.compose.ui.text.TextStyle labelSmall, optional androidx.compose.ui.text.TextStyle bodyLarge, optional androidx.compose.ui.text.TextStyle bodyMedium, optional androidx.compose.ui.text.TextStyle bodySmall, optional androidx.compose.ui.text.TextStyle bodyExtraSmall);
+    ctor public Typography(optional androidx.compose.ui.text.font.FontFamily defaultFontFamily, optional androidx.compose.ui.text.TextStyle arcMedium, optional androidx.compose.ui.text.TextStyle arcSmall, optional androidx.compose.ui.text.TextStyle displayLarge, optional androidx.compose.ui.text.TextStyle displayMedium, optional androidx.compose.ui.text.TextStyle displaySmall, optional androidx.compose.ui.text.TextStyle titleLarge, optional androidx.compose.ui.text.TextStyle titleMedium, optional androidx.compose.ui.text.TextStyle titleSmall, optional androidx.compose.ui.text.TextStyle labelLarge, optional androidx.compose.ui.text.TextStyle labelMedium, optional androidx.compose.ui.text.TextStyle labelSmall, optional androidx.compose.ui.text.TextStyle bodyLarge, optional androidx.compose.ui.text.TextStyle bodyMedium, optional androidx.compose.ui.text.TextStyle bodySmall, optional androidx.compose.ui.text.TextStyle bodyExtraSmall, optional androidx.compose.ui.text.TextStyle numeralExtraLarge, optional androidx.compose.ui.text.TextStyle numeralLarge, optional androidx.compose.ui.text.TextStyle numeralMedium, optional androidx.compose.ui.text.TextStyle numeralSmall, optional androidx.compose.ui.text.TextStyle numeralExtraSmall);
+    method public androidx.wear.compose.material3.Typography copy(optional androidx.compose.ui.text.TextStyle arcMedium, optional androidx.compose.ui.text.TextStyle arcSmall, optional androidx.compose.ui.text.TextStyle displayLarge, optional androidx.compose.ui.text.TextStyle displayMedium, optional androidx.compose.ui.text.TextStyle displaySmall, optional androidx.compose.ui.text.TextStyle titleLarge, optional androidx.compose.ui.text.TextStyle titleMedium, optional androidx.compose.ui.text.TextStyle titleSmall, optional androidx.compose.ui.text.TextStyle labelLarge, optional androidx.compose.ui.text.TextStyle labelMedium, optional androidx.compose.ui.text.TextStyle labelSmall, optional androidx.compose.ui.text.TextStyle bodyLarge, optional androidx.compose.ui.text.TextStyle bodyMedium, optional androidx.compose.ui.text.TextStyle bodySmall, optional androidx.compose.ui.text.TextStyle bodyExtraSmall, optional androidx.compose.ui.text.TextStyle numeralExtraLarge, optional androidx.compose.ui.text.TextStyle numeralLarge, optional androidx.compose.ui.text.TextStyle numeralMedium, optional androidx.compose.ui.text.TextStyle numeralSmall, optional androidx.compose.ui.text.TextStyle numeralExtraSmall);
+    method public androidx.compose.ui.text.TextStyle getArcMedium();
+    method public androidx.compose.ui.text.TextStyle getArcSmall();
     method public androidx.compose.ui.text.TextStyle getBodyExtraSmall();
     method public androidx.compose.ui.text.TextStyle getBodyLarge();
     method public androidx.compose.ui.text.TextStyle getBodyMedium();
@@ -1026,9 +1068,16 @@
     method public androidx.compose.ui.text.TextStyle getLabelLarge();
     method public androidx.compose.ui.text.TextStyle getLabelMedium();
     method public androidx.compose.ui.text.TextStyle getLabelSmall();
+    method public androidx.compose.ui.text.TextStyle getNumeralExtraLarge();
+    method public androidx.compose.ui.text.TextStyle getNumeralExtraSmall();
+    method public androidx.compose.ui.text.TextStyle getNumeralLarge();
+    method public androidx.compose.ui.text.TextStyle getNumeralMedium();
+    method public androidx.compose.ui.text.TextStyle getNumeralSmall();
     method public androidx.compose.ui.text.TextStyle getTitleLarge();
     method public androidx.compose.ui.text.TextStyle getTitleMedium();
     method public androidx.compose.ui.text.TextStyle getTitleSmall();
+    property public final androidx.compose.ui.text.TextStyle arcMedium;
+    property public final androidx.compose.ui.text.TextStyle arcSmall;
     property public final androidx.compose.ui.text.TextStyle bodyExtraSmall;
     property public final androidx.compose.ui.text.TextStyle bodyLarge;
     property public final androidx.compose.ui.text.TextStyle bodyMedium;
@@ -1039,6 +1088,11 @@
     property public final androidx.compose.ui.text.TextStyle labelLarge;
     property public final androidx.compose.ui.text.TextStyle labelMedium;
     property public final androidx.compose.ui.text.TextStyle labelSmall;
+    property public final androidx.compose.ui.text.TextStyle numeralExtraLarge;
+    property public final androidx.compose.ui.text.TextStyle numeralExtraSmall;
+    property public final androidx.compose.ui.text.TextStyle numeralLarge;
+    property public final androidx.compose.ui.text.TextStyle numeralMedium;
+    property public final androidx.compose.ui.text.TextStyle numeralSmall;
     property public final androidx.compose.ui.text.TextStyle titleLarge;
     property public final androidx.compose.ui.text.TextStyle titleMedium;
     property public final androidx.compose.ui.text.TextStyle titleSmall;
diff --git a/wear/compose/compose-material3/api/restricted_current.txt b/wear/compose/compose-material3/api/restricted_current.txt
index 532e6c3..1c84c9f 100644
--- a/wear/compose/compose-material3/api/restricted_current.txt
+++ b/wear/compose/compose-material3/api/restricted_current.txt
@@ -1,6 +1,24 @@
 // Signature format: 4.0
 package androidx.wear.compose.material3 {
 
+  public final class AnimatedTextDefaults {
+    field public static final int CacheSize = 5; // 0x5
+    field public static final androidx.wear.compose.material3.AnimatedTextDefaults INSTANCE;
+  }
+
+  @RequiresApi(31) public final class AnimatedTextFontRegistry {
+    ctor public AnimatedTextFontRegistry(androidx.compose.ui.text.TextStyle textStyle, androidx.compose.ui.text.font.FontVariation.Settings startFontVariationSettings, androidx.compose.ui.text.font.FontVariation.Settings endFontVariationSettings, long startFontSize, long endFontSize, androidx.compose.ui.unit.Density density, androidx.compose.ui.text.font.FontFamily.Resolver fontFamilyResolver, optional long contentColor, optional int cacheSize);
+  }
+
+  public final class AnimatedTextKt {
+    method @RequiresApi(31) @androidx.compose.runtime.Composable public static void AnimatedText(String text, androidx.wear.compose.material3.AnimatedTextFontRegistry fontRegistry, kotlin.jvm.functions.Function0<java.lang.Float> progressFraction, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment contentAlignment);
+    method @RequiresApi(31) @androidx.compose.runtime.Composable public static androidx.wear.compose.material3.AnimatedTextFontRegistry rememberAnimatedTextFontRegistry(androidx.compose.ui.text.font.FontVariation.Settings startFontVariationSettings, androidx.compose.ui.text.font.FontVariation.Settings endFontVariationSettings, optional androidx.compose.ui.text.TextStyle textStyle, optional long startFontSize, optional long endFontSize);
+  }
+
+  public final class AppScaffoldKt {
+    method @androidx.compose.runtime.Composable public static void AppScaffold(optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> timeText, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+  }
+
   @androidx.compose.runtime.Immutable public final class ButtonColors {
     ctor public ButtonColors(androidx.compose.ui.graphics.painter.Painter containerPainter, long contentColor, long secondaryContentColor, long iconColor, androidx.compose.ui.graphics.painter.Painter disabledContainerPainter, long disabledContentColor, long disabledSecondaryContentColor, long disabledIconColor);
     ctor public ButtonColors(long containerColor, long contentColor, long secondaryContentColor, long iconColor, long disabledContainerColor, long disabledContentColor, long disabledSecondaryContentColor, long disabledIconColor);
@@ -38,6 +56,10 @@
     method public androidx.compose.foundation.layout.PaddingValues getCompactButtonTapTargetPadding();
     method public float getCompactButtonVerticalPadding();
     method public androidx.compose.foundation.layout.PaddingValues getContentPadding();
+    method public float getEdgeButtonHeightExtraSmall();
+    method public float getEdgeButtonHeightLarge();
+    method public float getEdgeButtonHeightMedium();
+    method public float getEdgeButtonHeightSmall();
     method public float getHeight();
     method public float getIconSize();
     method public float getLargeIconSize();
@@ -55,6 +77,10 @@
     property public final androidx.compose.foundation.layout.PaddingValues CompactButtonTapTargetPadding;
     property public final float CompactButtonVerticalPadding;
     property public final androidx.compose.foundation.layout.PaddingValues ContentPadding;
+    property public final float EdgeButtonHeightExtraSmall;
+    property public final float EdgeButtonHeightLarge;
+    property public final float EdgeButtonHeightMedium;
+    property public final float EdgeButtonHeightSmall;
     property public final float Height;
     property public final float IconSize;
     property public final float LargeIconSize;
@@ -181,31 +207,6 @@
     method @androidx.compose.runtime.Composable public static void SplitCheckboxButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, String? toggleContentDescription, kotlin.jvm.functions.Function0<kotlin.Unit> onContainerClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.SplitCheckboxButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? toggleInteractionSource, optional androidx.compose.foundation.interaction.MutableInteractionSource? containerInteractionSource, optional String? containerClickLabel, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit>? secondaryLabel, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> label);
   }
 
-  @androidx.compose.runtime.Immutable public final class CheckboxColors {
-    ctor public CheckboxColors(long checkedBoxColor, long checkedCheckmarkColor, long uncheckedBoxColor, long uncheckedCheckmarkColor, long disabledCheckedBoxColor, long disabledCheckedCheckmarkColor, long disabledUncheckedBoxColor, long disabledUncheckedCheckmarkColor);
-    method public long getCheckedBoxColor();
-    method public long getCheckedCheckmarkColor();
-    method public long getDisabledCheckedBoxColor();
-    method public long getDisabledCheckedCheckmarkColor();
-    method public long getDisabledUncheckedBoxColor();
-    method public long getDisabledUncheckedCheckmarkColor();
-    method public long getUncheckedBoxColor();
-    method public long getUncheckedCheckmarkColor();
-    property public final long checkedBoxColor;
-    property public final long checkedCheckmarkColor;
-    property public final long disabledCheckedBoxColor;
-    property public final long disabledCheckedCheckmarkColor;
-    property public final long disabledUncheckedBoxColor;
-    property public final long disabledUncheckedCheckmarkColor;
-    property public final long uncheckedBoxColor;
-    property public final long uncheckedCheckmarkColor;
-  }
-
-  public final class CheckboxDefaults {
-    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.CheckboxColors colors(optional long checkedBoxColor, optional long checkedCheckmarkColor, optional long uncheckedBoxColor, optional long uncheckedCheckmarkColor, optional long disabledCheckedBoxColor, optional long disabledCheckedCheckmarkColor, optional long disabledUncheckedBoxColor, optional long disabledUncheckedCheckmarkColor);
-    field public static final androidx.wear.compose.material3.CheckboxDefaults INSTANCE;
-  }
-
   @androidx.compose.runtime.Immutable @androidx.compose.runtime.Stable public final class ColorScheme {
     ctor public ColorScheme(optional long primary, optional long primaryDim, optional long primaryContainer, optional long onPrimary, optional long onPrimaryContainer, optional long secondary, optional long secondaryDim, optional long secondaryContainer, optional long onSecondary, optional long onSecondaryContainer, optional long tertiary, optional long tertiaryDim, optional long tertiaryContainer, optional long onTertiary, optional long onTertiaryContainer, optional long surfaceContainerLow, optional long surfaceContainer, optional long surfaceContainerHigh, optional long onSurface, optional long onSurfaceVariant, optional long outline, optional long outlineVariant, optional long background, optional long onBackground, optional long error, optional long onError, optional long errorContainer, optional long onErrorContainer);
     method public androidx.wear.compose.material3.ColorScheme copy(optional long primary, optional long primaryDim, optional long primaryContainer, optional long onPrimary, optional long onPrimaryContainer, optional long secondary, optional long secondaryDim, optional long secondaryContainer, optional long onSecondary, optional long onSecondaryContainer, optional long tertiary, optional long tertiaryDim, optional long tertiaryContainer, optional long onTertiary, optional long onTertiaryContainer, optional long surfaceContainerLow, optional long surfaceContainer, optional long surfaceContainerHigh, optional long onSurface, optional long onSurfaceVariant, optional long outline, optional long outlineVariant, optional long background, optional long onBackground, optional long error, optional long onError, optional long errorContainer, optional long onErrorContainer);
@@ -287,6 +288,10 @@
     method public static void curvedText(androidx.wear.compose.foundation.CurvedScope, String text, optional androidx.wear.compose.foundation.CurvedModifier modifier, optional float maxSweepAngle, optional long background, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontSynthesis? fontSynthesis, optional androidx.wear.compose.foundation.CurvedTextStyle? style, optional androidx.wear.compose.foundation.CurvedDirection.Angular? angularDirection, optional int overflow);
   }
 
+  public final class EdgeButtonKt {
+    method @androidx.compose.runtime.Composable public static void EdgeButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional float buttonHeight, optional boolean enabled, optional androidx.wear.compose.material3.ButtonColors colors, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+  }
+
   @SuppressCompatibility @kotlin.RequiresOptIn(message="This Wear Material3 API is experimental and is likely to change or to be removed in" + " the future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalWearMaterial3Api {
   }
 
@@ -624,6 +629,23 @@
     method @androidx.compose.runtime.Stable public static androidx.compose.foundation.IndicationNodeFactory ripple(optional boolean bounded, optional float radius, optional long color);
   }
 
+  public final class ScreenScaffoldKt {
+    method @androidx.compose.runtime.Composable public static void ScreenScaffold(androidx.compose.foundation.lazy.LazyListState scrollState, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? timeText, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit>? scrollIndicator, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void ScreenScaffold(androidx.compose.foundation.ScrollState scrollState, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? timeText, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit>? scrollIndicator, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void ScreenScaffold(optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? timeText, optional androidx.wear.compose.foundation.ScrollInfoProvider? scrollInfoProvider, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit>? scrollIndicator, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void ScreenScaffold(androidx.wear.compose.foundation.lazy.ScalingLazyListState scrollState, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? timeText, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit>? scrollIndicator, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+  }
+
+  public enum ScreenStage {
+    enum_constant public static final androidx.wear.compose.material3.ScreenStage Idle;
+    enum_constant public static final androidx.wear.compose.material3.ScreenStage New;
+    enum_constant public static final androidx.wear.compose.material3.ScreenStage Scrolling;
+  }
+
+  public final class ScrollAwayKt {
+    method public static androidx.compose.ui.Modifier scrollAway(androidx.compose.ui.Modifier, androidx.wear.compose.foundation.ScrollInfoProvider scrollInfoProvider, kotlin.jvm.functions.Function0<? extends androidx.wear.compose.material3.ScreenStage> screenStage);
+  }
+
   public final class ScrollIndicatorDefaults {
     method public androidx.compose.animation.core.AnimationSpec<java.lang.Float> getPositionAnimationSpec();
     property public final androidx.compose.animation.core.AnimationSpec<java.lang.Float> PositionAnimationSpec;
@@ -762,40 +784,66 @@
     property public final long unselectedSplitContainerColor;
   }
 
-  public final class SplitToggleButtonColors {
-    ctor public SplitToggleButtonColors(long checkedContainerColor, long checkedContentColor, long checkedSecondaryContentColor, long checkedSplitContainerColor, long uncheckedContainerColor, long uncheckedContentColor, long uncheckedSecondaryContentColor, long uncheckedSplitContainerColor, long disabledCheckedContainerColor, long disabledCheckedContentColor, long disabledCheckedSecondaryContentColor, long disabledCheckedSplitContainerColor, long disabledUncheckedContainerColor, long disabledUncheckedContentColor, long disabledUncheckedSecondaryContentColor, long disabledUncheckedSplitContainerColor);
+  public final class SplitSwitchButtonColors {
+    ctor public SplitSwitchButtonColors(long checkedContainerColor, long checkedContentColor, long checkedSecondaryContentColor, long checkedSplitContainerColor, long checkedThumbColor, long checkedThumbIconColor, long checkedTrackColor, long checkedTrackBorderColor, long uncheckedContainerColor, long uncheckedContentColor, long uncheckedSecondaryContentColor, long uncheckedSplitContainerColor, long uncheckedThumbColor, long uncheckedTrackColor, long uncheckedTrackBorderColor, long disabledCheckedContainerColor, long disabledCheckedContentColor, long disabledCheckedSecondaryContentColor, long disabledCheckedSplitContainerColor, long disabledCheckedThumbColor, long disabledCheckedThumbIconColor, long disabledCheckedTrackColor, long disabledCheckedTrackBorderColor, long disabledUncheckedContainerColor, long disabledUncheckedContentColor, long disabledUncheckedSecondaryContentColor, long disabledUncheckedSplitContainerColor, long disabledUncheckedThumbColor, long disabledUncheckedTrackBorderColor);
     method public long getCheckedContainerColor();
     method public long getCheckedContentColor();
     method public long getCheckedSecondaryContentColor();
     method public long getCheckedSplitContainerColor();
+    method public long getCheckedThumbColor();
+    method public long getCheckedThumbIconColor();
+    method public long getCheckedTrackBorderColor();
+    method public long getCheckedTrackColor();
     method public long getDisabledCheckedContainerColor();
     method public long getDisabledCheckedContentColor();
     method public long getDisabledCheckedSecondaryContentColor();
     method public long getDisabledCheckedSplitContainerColor();
+    method public long getDisabledCheckedThumbColor();
+    method public long getDisabledCheckedThumbIconColor();
+    method public long getDisabledCheckedTrackBorderColor();
+    method public long getDisabledCheckedTrackColor();
     method public long getDisabledUncheckedContainerColor();
     method public long getDisabledUncheckedContentColor();
     method public long getDisabledUncheckedSecondaryContentColor();
     method public long getDisabledUncheckedSplitContainerColor();
+    method public long getDisabledUncheckedThumbColor();
+    method public long getDisabledUncheckedTrackBorderColor();
     method public long getUncheckedContainerColor();
     method public long getUncheckedContentColor();
     method public long getUncheckedSecondaryContentColor();
     method public long getUncheckedSplitContainerColor();
+    method public long getUncheckedThumbColor();
+    method public long getUncheckedTrackBorderColor();
+    method public long getUncheckedTrackColor();
     property public final long checkedContainerColor;
     property public final long checkedContentColor;
     property public final long checkedSecondaryContentColor;
     property public final long checkedSplitContainerColor;
+    property public final long checkedThumbColor;
+    property public final long checkedThumbIconColor;
+    property public final long checkedTrackBorderColor;
+    property public final long checkedTrackColor;
     property public final long disabledCheckedContainerColor;
     property public final long disabledCheckedContentColor;
     property public final long disabledCheckedSecondaryContentColor;
     property public final long disabledCheckedSplitContainerColor;
+    property public final long disabledCheckedThumbColor;
+    property public final long disabledCheckedThumbIconColor;
+    property public final long disabledCheckedTrackBorderColor;
+    property public final long disabledCheckedTrackColor;
     property public final long disabledUncheckedContainerColor;
     property public final long disabledUncheckedContentColor;
     property public final long disabledUncheckedSecondaryContentColor;
     property public final long disabledUncheckedSplitContainerColor;
+    property public final long disabledUncheckedThumbColor;
+    property public final long disabledUncheckedTrackBorderColor;
     property public final long uncheckedContainerColor;
     property public final long uncheckedContentColor;
     property public final long uncheckedSecondaryContentColor;
     property public final long uncheckedSplitContainerColor;
+    property public final long uncheckedThumbColor;
+    property public final long uncheckedTrackBorderColor;
+    property public final long uncheckedTrackColor;
   }
 
   @SuppressCompatibility @androidx.wear.compose.material3.ExperimentalWearMaterial3Api public final class StepperDefaults {
@@ -816,45 +864,85 @@
     method @androidx.compose.runtime.Composable public static void SwipeToDismissBox(kotlin.jvm.functions.Function0<kotlin.Unit> onDismissed, optional androidx.compose.ui.Modifier modifier, optional androidx.wear.compose.foundation.SwipeToDismissBoxState state, optional long backgroundScrimColor, optional long contentScrimColor, optional Object backgroundKey, optional Object contentKey, optional boolean userSwipeEnabled, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.layout.BoxScope,? super java.lang.Boolean,kotlin.Unit> content);
   }
 
-  @androidx.compose.runtime.Immutable public final class SwitchColors {
-    ctor public SwitchColors(long checkedThumbColor, long checkedThumbIconColor, long checkedTrackColor, long checkedTrackBorderColor, long uncheckedThumbColor, long uncheckedThumbIconColor, long uncheckedTrackColor, long uncheckedTrackBorderColor, long disabledCheckedThumbColor, long disabledCheckedThumbIconColor, long disabledCheckedTrackColor, long disabledCheckedTrackBorderColor, long disabledUncheckedThumbColor, long disabledUncheckedThumbIconColor, long disabledUncheckedTrackColor, long disabledUncheckedTrackBorderColor);
+  @androidx.compose.runtime.Immutable public final class SwitchButtonColors {
+    ctor public SwitchButtonColors(long checkedContainerColor, long checkedContentColor, long checkedSecondaryContentColor, long checkedIconColor, long checkedThumbColor, long checkedThumbIconColor, long checkedTrackBorderColor, long checkedTrackColor, long uncheckedContainerColor, long uncheckedContentColor, long uncheckedSecondaryContentColor, long uncheckedIconColor, long uncheckedThumbColor, long uncheckedTrackColor, long uncheckedTrackBorderColor, long disabledCheckedContainerColor, long disabledCheckedContentColor, long disabledCheckedSecondaryContentColor, long disabledCheckedIconColor, long disabledCheckedThumbColor, long disabledCheckedThumbIconColor, long disabledCheckedTrackColor, long disabledCheckedTrackBorderColor, long disabledUncheckedContainerColor, long disabledUncheckedContentColor, long disabledUncheckedSecondaryContentColor, long disabledUncheckedIconColor, long disabledUncheckedThumbColor, long disabledUncheckedTrackBorderColor);
+    method public long getCheckedContainerColor();
+    method public long getCheckedContentColor();
+    method public long getCheckedIconColor();
+    method public long getCheckedSecondaryContentColor();
     method public long getCheckedThumbColor();
     method public long getCheckedThumbIconColor();
     method public long getCheckedTrackBorderColor();
     method public long getCheckedTrackColor();
+    method public long getDisabledCheckedContainerColor();
+    method public long getDisabledCheckedContentColor();
+    method public long getDisabledCheckedIconColor();
+    method public long getDisabledCheckedSecondaryContentColor();
     method public long getDisabledCheckedThumbColor();
     method public long getDisabledCheckedThumbIconColor();
     method public long getDisabledCheckedTrackBorderColor();
     method public long getDisabledCheckedTrackColor();
+    method public long getDisabledUncheckedContainerColor();
+    method public long getDisabledUncheckedContentColor();
+    method public long getDisabledUncheckedIconColor();
+    method public long getDisabledUncheckedSecondaryContentColor();
     method public long getDisabledUncheckedThumbColor();
-    method public long getDisabledUncheckedThumbIconColor();
     method public long getDisabledUncheckedTrackBorderColor();
-    method public long getDisabledUncheckedTrackColor();
+    method public long getUncheckedContainerColor();
+    method public long getUncheckedContentColor();
+    method public long getUncheckedIconColor();
+    method public long getUncheckedSecondaryContentColor();
     method public long getUncheckedThumbColor();
-    method public long getUncheckedThumbIconColor();
     method public long getUncheckedTrackBorderColor();
     method public long getUncheckedTrackColor();
+    property public final long checkedContainerColor;
+    property public final long checkedContentColor;
+    property public final long checkedIconColor;
+    property public final long checkedSecondaryContentColor;
     property public final long checkedThumbColor;
     property public final long checkedThumbIconColor;
     property public final long checkedTrackBorderColor;
     property public final long checkedTrackColor;
+    property public final long disabledCheckedContainerColor;
+    property public final long disabledCheckedContentColor;
+    property public final long disabledCheckedIconColor;
+    property public final long disabledCheckedSecondaryContentColor;
     property public final long disabledCheckedThumbColor;
     property public final long disabledCheckedThumbIconColor;
     property public final long disabledCheckedTrackBorderColor;
     property public final long disabledCheckedTrackColor;
+    property public final long disabledUncheckedContainerColor;
+    property public final long disabledUncheckedContentColor;
+    property public final long disabledUncheckedIconColor;
+    property public final long disabledUncheckedSecondaryContentColor;
     property public final long disabledUncheckedThumbColor;
-    property public final long disabledUncheckedThumbIconColor;
     property public final long disabledUncheckedTrackBorderColor;
-    property public final long disabledUncheckedTrackColor;
+    property public final long uncheckedContainerColor;
+    property public final long uncheckedContentColor;
+    property public final long uncheckedIconColor;
+    property public final long uncheckedSecondaryContentColor;
     property public final long uncheckedThumbColor;
-    property public final long uncheckedThumbIconColor;
     property public final long uncheckedTrackBorderColor;
     property public final long uncheckedTrackColor;
   }
 
-  public final class SwitchDefaults {
-    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.SwitchColors colors(optional long checkedThumbColor, optional long checkedThumbIconColor, optional long checkedTrackColor, optional long checkedTrackBorderColor, optional long uncheckedThumbColor, optional long uncheckedThumbIconColor, optional long uncheckedTrackColor, optional long uncheckedTrackBorderColor, optional long disabledCheckedThumbColor, optional long disabledCheckedThumbIconColor, optional long disabledCheckedTrackColor, optional long disabledCheckedTrackBorderColor, optional long disabledUncheckedThumbColor, optional long disabledUncheckedThumbIconColor, optional long disabledUncheckedTrackColor, optional long disabledUncheckedTrackBorderColor);
-    field public static final androidx.wear.compose.material3.SwitchDefaults INSTANCE;
+  public final class SwitchButtonDefaults {
+    method public androidx.compose.foundation.layout.PaddingValues getContentPadding();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getSplitSwitchButtonShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getSwitchButtonShape();
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.SplitSwitchButtonColors splitSwitchButtonColors();
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.SplitSwitchButtonColors splitSwitchButtonColors(optional long checkedContainerColor, optional long checkedContentColor, optional long checkedSecondaryContentColor, optional long checkedSplitContainerColor, optional long checkedThumbColor, optional long checkedThumbIconColor, optional long checkedTrackColor, optional long checkedTrackBorderColor, optional long uncheckedContainerColor, optional long uncheckedContentColor, optional long uncheckedSecondaryContentColor, optional long uncheckedSplitContainerColor, optional long uncheckedThumbColor, optional long uncheckedTrackColor, optional long uncheckedTrackBorderColor, optional long disabledCheckedContainerColor, optional long disabledCheckedContentColor, optional long disabledCheckedSecondaryContentColor, optional long disabledCheckedSplitContainerColor, optional long disabledCheckedThumbColor, optional long disabledCheckedThumbIconColor, optional long disabledCheckedTrackColor, optional long disabledCheckedTrackBorderColor, optional long disabledUncheckedContainerColor, optional long disabledUncheckedContentColor, optional long disabledUncheckedSecondaryContentColor, optional long disabledUncheckedSplitContainerColor, optional long disabledUncheckedThumbColor, optional long disabledUncheckedTrackBorderColor);
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.SwitchButtonColors switchButtonColors();
+    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.SwitchButtonColors switchButtonColors(optional long checkedContainerColor, optional long checkedContentColor, optional long checkedSecondaryContentColor, optional long checkedIconColor, optional long checkedThumbColor, optional long checkedThumbIconColor, optional long checkedTrackColor, optional long checkedTrackBorderColor, optional long uncheckedContainerColor, optional long uncheckedContentColor, optional long uncheckedSecondaryContentColor, optional long uncheckedIconColor, optional long uncheckedThumbColor, optional long uncheckedTrackColor, optional long uncheckedTrackBorderColor, optional long disabledCheckedContainerColor, optional long disabledCheckedContentColor, optional long disabledCheckedSecondaryContentColor, optional long disabledCheckedIconColor, optional long disabledCheckedThumbColor, optional long disabledCheckedThumbIconColor, optional long disabledCheckedTrackColor, optional long disabledCheckedTrackBorderColor, optional long disabledUncheckedContainerColor, optional long disabledUncheckedContentColor, optional long disabledUncheckedSecondaryContentColor, optional long disabledUncheckedIconColor, optional long disabledUncheckedThumbColor, optional long disabledUncheckedTrackBorderColor);
+    property public final androidx.compose.foundation.layout.PaddingValues ContentPadding;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape splitSwitchButtonShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape switchButtonShape;
+    field public static final androidx.wear.compose.material3.SwitchButtonDefaults INSTANCE;
+  }
+
+  public final class SwitchButtonKt {
+    method @androidx.compose.runtime.Composable public static void SplitSwitchButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, String? toggleContentDescription, kotlin.jvm.functions.Function0<kotlin.Unit> onContainerClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.SplitSwitchButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? toggleInteractionSource, optional androidx.compose.foundation.interaction.MutableInteractionSource? containerInteractionSource, optional String? containerClickLabel, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit>? secondaryLabel, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> label);
+    method @androidx.compose.runtime.Composable public static void SwitchButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.SwitchButtonColors colors, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit>? icon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit>? secondaryLabel, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> label);
   }
 
   @androidx.compose.runtime.Immutable public final class TextButtonColors {
@@ -939,70 +1027,22 @@
 
   @androidx.compose.runtime.Immutable public final class ToggleButtonColors {
     ctor public ToggleButtonColors(long checkedContainerColor, long checkedContentColor, long uncheckedContainerColor, long uncheckedContentColor, long disabledCheckedContainerColor, long disabledCheckedContentColor, long disabledUncheckedContainerColor, long disabledUncheckedContentColor);
-    ctor public ToggleButtonColors(long checkedContainerColor, long checkedContentColor, long checkedSecondaryContentColor, long checkedIconColor, long uncheckedContainerColor, long uncheckedContentColor, long uncheckedSecondaryContentColor, long uncheckedIconColor, long disabledCheckedContainerColor, long disabledCheckedContentColor, long disabledCheckedSecondaryContentColor, long disabledCheckedIconColor, long disabledUncheckedContainerColor, long disabledUncheckedContentColor, long disabledUncheckedSecondaryContentColor, long disabledUncheckedIconColor);
     method public long getCheckedContainerColor();
     method public long getCheckedContentColor();
-    method public long getCheckedIconColor();
-    method public long getCheckedSecondaryContentColor();
     method public long getDisabledCheckedContainerColor();
     method public long getDisabledCheckedContentColor();
-    method public long getDisabledCheckedIconColor();
-    method public long getDisabledCheckedSecondaryContentColor();
     method public long getDisabledUncheckedContainerColor();
     method public long getDisabledUncheckedContentColor();
-    method public long getDisabledUncheckedIconColor();
-    method public long getDisabledUncheckedSecondaryContentColor();
     method public long getUncheckedContainerColor();
     method public long getUncheckedContentColor();
-    method public long getUncheckedIconColor();
-    method public long getUncheckedSecondaryContentColor();
     property public final long checkedContainerColor;
     property public final long checkedContentColor;
-    property public final long checkedIconColor;
-    property public final long checkedSecondaryContentColor;
     property public final long disabledCheckedContainerColor;
     property public final long disabledCheckedContentColor;
-    property public final long disabledCheckedIconColor;
-    property public final long disabledCheckedSecondaryContentColor;
     property public final long disabledUncheckedContainerColor;
     property public final long disabledUncheckedContentColor;
-    property public final long disabledUncheckedIconColor;
-    property public final long disabledUncheckedSecondaryContentColor;
     property public final long uncheckedContainerColor;
     property public final long uncheckedContentColor;
-    property public final long uncheckedIconColor;
-    property public final long uncheckedSecondaryContentColor;
-  }
-
-  public final class ToggleButtonDefaults {
-    method public androidx.compose.foundation.layout.PaddingValues getContentPadding();
-    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getSplitToggleButtonShape();
-    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getToggleButtonShape();
-    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.SplitToggleButtonColors splitToggleButtonColors();
-    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.SplitToggleButtonColors splitToggleButtonColors(optional long checkedContainerColor, optional long checkedContentColor, optional long checkedSecondaryContentColor, optional long checkedSplitContainerColor, optional long uncheckedContainerColor, optional long uncheckedContentColor, optional long uncheckedSecondaryContentColor, optional long uncheckedSplitContainerColor, optional long disabledCheckedContainerColor, optional long disabledCheckedContentColor, optional long disabledCheckedSecondaryContentColor, optional long disabledCheckedSplitContainerColor, optional long disabledUncheckedContainerColor, optional long disabledUncheckedContentColor, optional long disabledUncheckedSecondaryContentColor, optional long disabledUncheckedSplitContainerColor);
-    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.ToggleButtonColors toggleButtonColors();
-    method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.ToggleButtonColors toggleButtonColors(optional long checkedContainerColor, optional long checkedContentColor, optional long checkedSecondaryContentColor, optional long checkedIconColor, optional long uncheckedContainerColor, optional long uncheckedContentColor, optional long uncheckedSecondaryContentColor, optional long uncheckedIconColor, optional long disabledCheckedContainerColor, optional long disabledCheckedContentColor, optional long disabledCheckedSecondaryContentColor, optional long disabledCheckedIconColor, optional long disabledUncheckedContainerColor, optional long disabledUncheckedContentColor, optional long disabledUncheckedSecondaryContentColor, optional long disabledUncheckedIconColor);
-    property public final androidx.compose.foundation.layout.PaddingValues ContentPadding;
-    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape splitToggleButtonShape;
-    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape toggleButtonShape;
-    field public static final androidx.wear.compose.material3.ToggleButtonDefaults INSTANCE;
-  }
-
-  public final class ToggleButtonKt {
-    method @androidx.compose.runtime.Composable public static void SplitToggleButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, kotlin.jvm.functions.Function1<? super androidx.wear.compose.material3.ToggleControlScope,kotlin.Unit> toggleControl, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.SplitToggleButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? checkedInteractionSource, optional androidx.compose.foundation.interaction.MutableInteractionSource? clickInteractionSource, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit>? secondaryLabel, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> label);
-    method @androidx.compose.runtime.Composable public static void ToggleButton(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, kotlin.jvm.functions.Function1<? super androidx.wear.compose.material3.ToggleControlScope,kotlin.Unit> toggleControl, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional androidx.wear.compose.material3.ToggleButtonColors colors, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit>? icon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit>? secondaryLabel, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> label);
-  }
-
-  public final class ToggleControlScope {
-    ctor public ToggleControlScope(boolean isEnabled, boolean isChecked);
-    method public boolean isChecked();
-    method public boolean isEnabled();
-    property public final boolean isChecked;
-    property public final boolean isEnabled;
-  }
-
-  public final class ToggleControlsKt {
-    method @androidx.compose.runtime.Composable public static void Switch(androidx.wear.compose.material3.ToggleControlScope, optional androidx.compose.ui.Modifier modifier, optional androidx.wear.compose.material3.SwitchColors colors);
   }
 
   public fun interface TouchExplorationStateProvider {
@@ -1014,8 +1054,10 @@
   }
 
   @androidx.compose.runtime.Immutable public final class Typography {
-    ctor public Typography(optional androidx.compose.ui.text.font.FontFamily defaultFontFamily, optional androidx.compose.ui.text.TextStyle displayLarge, optional androidx.compose.ui.text.TextStyle displayMedium, optional androidx.compose.ui.text.TextStyle displaySmall, optional androidx.compose.ui.text.TextStyle titleLarge, optional androidx.compose.ui.text.TextStyle titleMedium, optional androidx.compose.ui.text.TextStyle titleSmall, optional androidx.compose.ui.text.TextStyle labelLarge, optional androidx.compose.ui.text.TextStyle labelMedium, optional androidx.compose.ui.text.TextStyle labelSmall, optional androidx.compose.ui.text.TextStyle bodyLarge, optional androidx.compose.ui.text.TextStyle bodyMedium, optional androidx.compose.ui.text.TextStyle bodySmall, optional androidx.compose.ui.text.TextStyle bodyExtraSmall);
-    method public androidx.wear.compose.material3.Typography copy(optional androidx.compose.ui.text.TextStyle displayLarge, optional androidx.compose.ui.text.TextStyle displayMedium, optional androidx.compose.ui.text.TextStyle displaySmall, optional androidx.compose.ui.text.TextStyle titleLarge, optional androidx.compose.ui.text.TextStyle titleMedium, optional androidx.compose.ui.text.TextStyle titleSmall, optional androidx.compose.ui.text.TextStyle labelLarge, optional androidx.compose.ui.text.TextStyle labelMedium, optional androidx.compose.ui.text.TextStyle labelSmall, optional androidx.compose.ui.text.TextStyle bodyLarge, optional androidx.compose.ui.text.TextStyle bodyMedium, optional androidx.compose.ui.text.TextStyle bodySmall, optional androidx.compose.ui.text.TextStyle bodyExtraSmall);
+    ctor public Typography(optional androidx.compose.ui.text.font.FontFamily defaultFontFamily, optional androidx.compose.ui.text.TextStyle arcMedium, optional androidx.compose.ui.text.TextStyle arcSmall, optional androidx.compose.ui.text.TextStyle displayLarge, optional androidx.compose.ui.text.TextStyle displayMedium, optional androidx.compose.ui.text.TextStyle displaySmall, optional androidx.compose.ui.text.TextStyle titleLarge, optional androidx.compose.ui.text.TextStyle titleMedium, optional androidx.compose.ui.text.TextStyle titleSmall, optional androidx.compose.ui.text.TextStyle labelLarge, optional androidx.compose.ui.text.TextStyle labelMedium, optional androidx.compose.ui.text.TextStyle labelSmall, optional androidx.compose.ui.text.TextStyle bodyLarge, optional androidx.compose.ui.text.TextStyle bodyMedium, optional androidx.compose.ui.text.TextStyle bodySmall, optional androidx.compose.ui.text.TextStyle bodyExtraSmall, optional androidx.compose.ui.text.TextStyle numeralExtraLarge, optional androidx.compose.ui.text.TextStyle numeralLarge, optional androidx.compose.ui.text.TextStyle numeralMedium, optional androidx.compose.ui.text.TextStyle numeralSmall, optional androidx.compose.ui.text.TextStyle numeralExtraSmall);
+    method public androidx.wear.compose.material3.Typography copy(optional androidx.compose.ui.text.TextStyle arcMedium, optional androidx.compose.ui.text.TextStyle arcSmall, optional androidx.compose.ui.text.TextStyle displayLarge, optional androidx.compose.ui.text.TextStyle displayMedium, optional androidx.compose.ui.text.TextStyle displaySmall, optional androidx.compose.ui.text.TextStyle titleLarge, optional androidx.compose.ui.text.TextStyle titleMedium, optional androidx.compose.ui.text.TextStyle titleSmall, optional androidx.compose.ui.text.TextStyle labelLarge, optional androidx.compose.ui.text.TextStyle labelMedium, optional androidx.compose.ui.text.TextStyle labelSmall, optional androidx.compose.ui.text.TextStyle bodyLarge, optional androidx.compose.ui.text.TextStyle bodyMedium, optional androidx.compose.ui.text.TextStyle bodySmall, optional androidx.compose.ui.text.TextStyle bodyExtraSmall, optional androidx.compose.ui.text.TextStyle numeralExtraLarge, optional androidx.compose.ui.text.TextStyle numeralLarge, optional androidx.compose.ui.text.TextStyle numeralMedium, optional androidx.compose.ui.text.TextStyle numeralSmall, optional androidx.compose.ui.text.TextStyle numeralExtraSmall);
+    method public androidx.compose.ui.text.TextStyle getArcMedium();
+    method public androidx.compose.ui.text.TextStyle getArcSmall();
     method public androidx.compose.ui.text.TextStyle getBodyExtraSmall();
     method public androidx.compose.ui.text.TextStyle getBodyLarge();
     method public androidx.compose.ui.text.TextStyle getBodyMedium();
@@ -1026,9 +1068,16 @@
     method public androidx.compose.ui.text.TextStyle getLabelLarge();
     method public androidx.compose.ui.text.TextStyle getLabelMedium();
     method public androidx.compose.ui.text.TextStyle getLabelSmall();
+    method public androidx.compose.ui.text.TextStyle getNumeralExtraLarge();
+    method public androidx.compose.ui.text.TextStyle getNumeralExtraSmall();
+    method public androidx.compose.ui.text.TextStyle getNumeralLarge();
+    method public androidx.compose.ui.text.TextStyle getNumeralMedium();
+    method public androidx.compose.ui.text.TextStyle getNumeralSmall();
     method public androidx.compose.ui.text.TextStyle getTitleLarge();
     method public androidx.compose.ui.text.TextStyle getTitleMedium();
     method public androidx.compose.ui.text.TextStyle getTitleSmall();
+    property public final androidx.compose.ui.text.TextStyle arcMedium;
+    property public final androidx.compose.ui.text.TextStyle arcSmall;
     property public final androidx.compose.ui.text.TextStyle bodyExtraSmall;
     property public final androidx.compose.ui.text.TextStyle bodyLarge;
     property public final androidx.compose.ui.text.TextStyle bodyMedium;
@@ -1039,6 +1088,11 @@
     property public final androidx.compose.ui.text.TextStyle labelLarge;
     property public final androidx.compose.ui.text.TextStyle labelMedium;
     property public final androidx.compose.ui.text.TextStyle labelSmall;
+    property public final androidx.compose.ui.text.TextStyle numeralExtraLarge;
+    property public final androidx.compose.ui.text.TextStyle numeralExtraSmall;
+    property public final androidx.compose.ui.text.TextStyle numeralLarge;
+    property public final androidx.compose.ui.text.TextStyle numeralMedium;
+    property public final androidx.compose.ui.text.TextStyle numeralSmall;
     property public final androidx.compose.ui.text.TextStyle titleLarge;
     property public final androidx.compose.ui.text.TextStyle titleMedium;
     property public final androidx.compose.ui.text.TextStyle titleSmall;
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ButtonDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ButtonDemo.kt
index c734bf8..a2384c5 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ButtonDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ButtonDemo.kt
@@ -18,16 +18,13 @@
 
 import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.foundation.layout.RowScope
-import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.size
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Favorite
 import androidx.compose.runtime.Composable
-import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.text.style.TextOverflow
-import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
 import androidx.wear.compose.material3.Button
 import androidx.wear.compose.material3.ButtonColors
 import androidx.wear.compose.material3.ButtonDefaults
@@ -58,10 +55,7 @@
 @Composable
 fun ButtonDemo() {
     val context = LocalContext.current
-    ScalingLazyColumn(
-        modifier = Modifier.fillMaxSize(),
-        horizontalAlignment = Alignment.CenterHorizontally,
-    ) {
+    ScalingLazyDemo {
         item { ListHeader { Text("1 slot button") } }
         item { SimpleButtonSample() }
         item {
@@ -95,10 +89,7 @@
 @Composable
 fun FilledTonalButtonDemo() {
     val context = LocalContext.current
-    ScalingLazyColumn(
-        modifier = Modifier.fillMaxSize(),
-        horizontalAlignment = Alignment.CenterHorizontally,
-    ) {
+    ScalingLazyDemo {
         item { ListHeader { Text("1 slot button") } }
         item { SimpleFilledTonalButtonSample() }
         item {
@@ -136,10 +127,7 @@
 @Composable
 fun OutlinedButtonDemo() {
     val context = LocalContext.current
-    ScalingLazyColumn(
-        modifier = Modifier.fillMaxSize(),
-        horizontalAlignment = Alignment.CenterHorizontally,
-    ) {
+    ScalingLazyDemo {
         item { ListHeader { Text("1 slot button") } }
         item { SimpleOutlinedButtonSample() }
         item {
@@ -177,10 +165,7 @@
 @Composable
 fun ChildButtonDemo() {
     val context = LocalContext.current
-    ScalingLazyColumn(
-        modifier = Modifier.fillMaxSize(),
-        horizontalAlignment = Alignment.CenterHorizontally,
-    ) {
+    ScalingLazyDemo {
         item { ListHeader { Text("1 slot button") } }
         item { SimpleChildButtonSample() }
         item {
@@ -218,10 +203,7 @@
 @Composable
 fun CompactButtonDemo() {
     val context = LocalContext.current
-    ScalingLazyColumn(
-        modifier = Modifier.fillMaxSize(),
-        horizontalAlignment = Alignment.CenterHorizontally,
-    ) {
+    ScalingLazyDemo {
         item { ListHeader { Text("2 slot compact button") } }
         item { CompactButtonSample() }
         item {
@@ -307,10 +289,7 @@
 
 @Composable
 fun MultilineButtonDemo() {
-    ScalingLazyColumn(
-        modifier = Modifier.fillMaxSize(),
-        horizontalAlignment = Alignment.CenterHorizontally,
-    ) {
+    ScalingLazyDemo {
         item { ListHeader { Text("3 line label") } }
         item { MultilineButton(enabled = true) }
         item { MultilineButton(enabled = false) }
@@ -330,10 +309,7 @@
 
 @Composable
 fun AvatarButtonDemo() {
-    ScalingLazyColumn(
-        modifier = Modifier.fillMaxSize(),
-        horizontalAlignment = Alignment.CenterHorizontally,
-    ) {
+    ScalingLazyDemo {
         item { ListHeader { Text("Label + Avatar") } }
         item { AvatarButton(enabled = true) }
         item { AvatarButton(enabled = false) }
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/CardDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/CardDemo.kt
index a74ee30..b19fcd2 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/CardDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/CardDemo.kt
@@ -16,12 +16,8 @@
 
 package androidx.wear.compose.material3.demos
 
-import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.runtime.Composable
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.LocalContext
-import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
 import androidx.wear.compose.material3.CardDefaults
 import androidx.wear.compose.material3.ListHeader
 import androidx.wear.compose.material3.Text
@@ -42,21 +38,16 @@
 @Composable
 fun CardDemo() {
     val context = LocalContext.current
-    ScalingLazyColumn(
-        modifier = Modifier.fillMaxSize(),
-        horizontalAlignment = Alignment.CenterHorizontally,
-    ) {
+    ScalingLazyDemo {
         item { ListHeader { Text("Card") } }
         item { CardSample() }
         item { CardWithOnLongClickSample { showOnLongClickToast(context) } }
         item { OutlinedCardSample() }
-
         item { ListHeader { Text("App card") } }
         item { AppCardSample() }
         item { AppCardWithIconSample() }
         item { AppCardWithImageSample() }
         item { OutlinedAppCardSample() }
-
         item { ListHeader { Text("Title card") } }
         item { TitleCardSample() }
         item { TitleCardWithSubtitleDemo() }
@@ -66,7 +57,6 @@
         item { OutlinedTitleCardSample() }
         item { OutlinedTitleCardWithSubtitleDemo() }
         item { OutlinedTitleCardWithSubtitleAndTimeDemo() }
-
         item { ListHeader { Text("Image card") } }
         item { TitleCardWithImageBackgroundSample() }
     }
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/CheckboxButtonDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/CheckboxButtonDemo.kt
index 9cbb677..7478ace 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/CheckboxButtonDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/CheckboxButtonDemo.kt
@@ -17,7 +17,6 @@
 package androidx.wear.compose.material3.demos
 
 import androidx.compose.foundation.layout.BoxScope
-import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Favorite
@@ -26,11 +25,9 @@
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.setValue
-import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.text.style.TextOverflow
-import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
 import androidx.wear.compose.material3.CheckboxButton
 import androidx.wear.compose.material3.Icon
 import androidx.wear.compose.material3.ListHeader
@@ -38,10 +35,7 @@
 
 @Composable
 fun CheckboxButtonDemo() {
-    ScalingLazyColumn(
-        modifier = Modifier.fillMaxSize(),
-        horizontalAlignment = Alignment.CenterHorizontally,
-    ) {
+    ScalingLazyDemo {
         item { ListHeader { Text("Checkbox") } }
         item { DemoCheckboxButton(enabled = true, initiallyChecked = true) }
         item { DemoCheckboxButton(enabled = true, initiallyChecked = false) }
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/EdgeButtonDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/EdgeButtonDemo.kt
new file mode 100644
index 0000000..6c02d1e
--- /dev/null
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/EdgeButtonDemo.kt
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.material3.demos
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.RowScope
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.State
+import androidx.compose.runtime.derivedStateOf
+import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.LocalConfiguration
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.util.fastForEach
+import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
+import androidx.wear.compose.foundation.lazy.ScalingLazyListItemInfo
+import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
+import androidx.wear.compose.integration.demos.common.AdaptiveScreen
+import androidx.wear.compose.material3.ButtonDefaults
+import androidx.wear.compose.material3.ButtonDefaults.buttonColors
+import androidx.wear.compose.material3.Card
+import androidx.wear.compose.material3.CompactButton
+import androidx.wear.compose.material3.EdgeButton
+import androidx.wear.compose.material3.Text
+
+@Composable
+fun EdgeButtonBelowListDemo() {
+    // NOTE: This demo recomposes the Edge Button when it's appearing / disappearing.
+    AdaptiveScreen {
+        val state = rememberScalingLazyListState()
+        val screenHeightPx =
+            with(LocalDensity.current) { LocalConfiguration.current.screenHeightDp.dp.toPx() }
+        val heightPx = remember {
+            derivedStateOf {
+                val marginPx = 5f // !?
+                var lastItemInfo: ScalingLazyListItemInfo? = null
+                state.layoutInfo.visibleItemsInfo.fastForEach { ii ->
+                    if (ii.index == state.layoutInfo.totalItemsCount - 1) lastItemInfo = ii
+                }
+                lastItemInfo?.let {
+                    val bottomEdge = it.offset + screenHeightPx / 2 + it.size / 2
+                    (screenHeightPx - bottomEdge - marginPx).coerceAtLeast(0f)
+                } ?: 0f
+            }
+        }
+
+        val labels =
+            listOf(
+                "Hi",
+                "Hello World",
+                "Hello world again?",
+                "More content as we add stuff",
+                "I don't know if this will fit now, testing",
+                "Really long text that it's going to take multiple lines",
+                "And now we are really pushing it because the screen is really small",
+            )
+        val selectedLabel = remember { mutableIntStateOf(0) }
+
+        Box(Modifier.fillMaxSize(), contentAlignment = Alignment.BottomCenter) {
+            ScalingLazyColumn(
+                state = state,
+                modifier = Modifier.fillMaxSize(),
+                autoCentering = null,
+                contentPadding = PaddingValues(10.dp, 20.dp, 10.dp, 100.dp)
+            ) {
+                items(labels.size) {
+                    Card(
+                        onClick = { selectedLabel.intValue = it },
+                        modifier = Modifier.fillMaxWidth(0.9f)
+                    ) {
+                        Text(labels[it])
+                    }
+                }
+            }
+            // We isolate the call to EdgeButton to a function so only that is recomposed when the
+            // height changes.
+            EdgeButtonCall(heightPx) {
+                Text(
+                    labels[selectedLabel.intValue],
+                    color = Color.White,
+                    textAlign = TextAlign.Center,
+                    maxLines = 3,
+                )
+            }
+        }
+    }
+}
+
+@Composable
+private fun EdgeButtonCall(heightPx: State<Float>, content: @Composable RowScope.() -> Unit) {
+    val heightDp = with(LocalDensity.current) { heightPx.value.toDp() }
+    EdgeButton(
+        onClick = {},
+        buttonHeight = ButtonDefaults.EdgeButtonHeightLarge,
+        colors = buttonColors(containerColor = Color.DarkGray),
+        modifier = Modifier.height(heightDp),
+        content = content
+    )
+}
+
+@Suppress("PrimitiveInCollection")
+@Composable
+fun EdgeButtonSizeDemo() {
+    val sizes =
+        listOf(
+            ButtonDefaults.EdgeButtonHeightExtraSmall,
+            ButtonDefaults.EdgeButtonHeightSmall,
+            ButtonDefaults.EdgeButtonHeightMedium,
+            ButtonDefaults.EdgeButtonHeightLarge
+        )
+    val sizesNames = listOf("XS", "S", "M", "L")
+    val size = remember { mutableIntStateOf(0) }
+
+    AdaptiveScreen {
+        Column(
+            Modifier.align(Alignment.TopCenter).fillMaxSize().padding(top = 0.dp),
+            verticalArrangement = Arrangement.spacedBy(0.dp),
+            horizontalAlignment = Alignment.CenterHorizontally
+        ) {
+            repeat(2) { row ->
+                Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) {
+                    repeat(2) { column ->
+                        val ix = row * 2 + column
+                        CompactButton(
+                            onClick = { size.intValue = ix },
+                            colors =
+                                if (ix == size.intValue) ButtonDefaults.filledTonalButtonColors()
+                                else ButtonDefaults.outlinedButtonColors(),
+                            border =
+                                if (ix == size.intValue) null
+                                else ButtonDefaults.outlinedButtonBorder(true),
+                        ) {
+                            Text(sizesNames[ix])
+                        }
+                    }
+                }
+            }
+            Box(modifier = Modifier.weight(1f), contentAlignment = Alignment.Center) {
+                Text("Content")
+            }
+            EdgeButton(
+                onClick = {},
+                buttonHeight = sizes[size.intValue],
+                colors = ButtonDefaults.outlinedButtonColors(),
+                border = ButtonDefaults.outlinedButtonBorder(enabled = true)
+            ) {
+                CheckIcon()
+            }
+        }
+    }
+}
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/IconButtonDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/IconButtonDemo.kt
index ec46327..3be24a8 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/IconButtonDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/IconButtonDemo.kt
@@ -18,7 +18,6 @@
 
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.width
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
@@ -26,7 +25,6 @@
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
-import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
 import androidx.wear.compose.material3.ButtonDefaults
 import androidx.wear.compose.material3.FilledIconButton
 import androidx.wear.compose.material3.FilledTonalIconButton
@@ -45,10 +43,7 @@
 @Composable
 fun IconButtonDemo() {
     val context = LocalContext.current
-    ScalingLazyColumn(
-        modifier = Modifier.fillMaxSize(),
-        horizontalAlignment = Alignment.CenterHorizontally,
-    ) {
+    ScalingLazyDemo {
         item { ListHeader { Text("Icon button") } }
         item {
             Row {
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/IconToggleButtonDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/IconToggleButtonDemo.kt
index 6a9babb..be9de41 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/IconToggleButtonDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/IconToggleButtonDemo.kt
@@ -18,7 +18,6 @@
 
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.layout.width
 import androidx.compose.material.icons.Icons
@@ -33,7 +32,6 @@
 import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
-import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
 import androidx.wear.compose.material3.Icon
 import androidx.wear.compose.material3.IconButtonDefaults
 import androidx.wear.compose.material3.IconToggleButton
@@ -44,10 +42,7 @@
 
 @Composable
 fun IconToggleButtonDemo() {
-    ScalingLazyColumn(
-        modifier = Modifier.fillMaxSize(),
-        horizontalAlignment = Alignment.CenterHorizontally,
-    ) {
+    ScalingLazyDemo {
         item { ListHeader { Text("Icon Toggle Button", textAlign = TextAlign.Center) } }
         item {
             Row {
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/Icons.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/Icons.kt
index 79aa8d2..b791a52 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/Icons.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/Icons.kt
@@ -19,6 +19,7 @@
 import androidx.compose.foundation.layout.size
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.AccountCircle
+import androidx.compose.material.icons.filled.Check
 import androidx.compose.material.icons.filled.Favorite
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
@@ -43,3 +44,12 @@
         modifier = Modifier.size(ButtonDefaults.LargeIconSize)
     )
 }
+
+@Composable
+internal fun CheckIcon() {
+    Icon(
+        Icons.Filled.Check,
+        contentDescription = "Check",
+        modifier = Modifier.size(ButtonDefaults.IconSize)
+    )
+}
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ListHeaderDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ListHeaderDemo.kt
index e8ceee4..6cdcf30 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ListHeaderDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ListHeaderDemo.kt
@@ -16,17 +16,14 @@
 
 package androidx.wear.compose.material3.demos
 
-import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
 import androidx.wear.compose.material3.samples.ListHeaderSample
 import androidx.wear.compose.material3.samples.ListSubheaderSample
 import androidx.wear.compose.material3.samples.ListSubheaderWithIconSample
 
 @Composable
 fun ListHeaderDemo() {
-    ScalingLazyColumn(modifier = Modifier.fillMaxWidth()) {
+    ScalingLazyDemo {
         item { ListHeaderSample() }
         item { ListSubheaderSample() }
         item { ListSubheaderWithIconSample() }
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/Material3Demos.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/Material3Demos.kt
new file mode 100644
index 0000000..e2f16b1
--- /dev/null
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/Material3Demos.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.material3.demos
+
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
+import androidx.wear.compose.foundation.lazy.ScalingLazyListScope
+import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
+import androidx.wear.compose.material3.ScreenScaffold
+
+@Composable
+fun ScalingLazyDemo(content: ScalingLazyListScope.() -> Unit) {
+    val scrollState = rememberScalingLazyListState()
+    ScreenScaffold(scrollState = scrollState) {
+        ScalingLazyColumn(
+            state = scrollState,
+            modifier = Modifier.fillMaxSize(),
+            horizontalAlignment = Alignment.CenterHorizontally,
+            content = content
+        )
+    }
+}
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ScrollAwayDemos.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ScrollAwayDemos.kt
new file mode 100644
index 0000000..7dc240b
--- /dev/null
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ScrollAwayDemos.kt
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.material3.demos
+
+import androidx.compose.foundation.gestures.ScrollableDefaults
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.rememberLazyListState
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.dp
+import androidx.wear.compose.foundation.ExperimentalWearFoundationApi
+import androidx.wear.compose.foundation.rememberActiveFocusRequester
+import androidx.wear.compose.foundation.rotary.RotaryScrollableDefaults
+import androidx.wear.compose.foundation.rotary.rotaryScrollable
+import androidx.wear.compose.foundation.toScrollAwayInfoProvider
+import androidx.wear.compose.integration.demos.common.Centralize
+import androidx.wear.compose.integration.demos.common.ComposableDemo
+import androidx.wear.compose.material3.FilledTonalButton
+import androidx.wear.compose.material3.ListHeader
+import androidx.wear.compose.material3.ScreenStage
+import androidx.wear.compose.material3.Text
+import androidx.wear.compose.material3.TimeText
+import androidx.wear.compose.material3.samples.ScrollAwaySample
+import androidx.wear.compose.material3.scrollAway
+
+val ScrollAwayDemos =
+    listOf(
+        ComposableDemo("Scaling Lazy Column") { ScrollAwaySample() },
+        ComposableDemo("LazyColumn") { Centralize { ScrollAwayLazyColumn() } },
+        ComposableDemo("Column") { Centralize { ScrollAwayColumn() } }
+    )
+
+@OptIn(ExperimentalWearFoundationApi::class)
+@Composable
+fun ScrollAwayLazyColumn() {
+    val scrollState = rememberLazyListState()
+    val focusRequester = rememberActiveFocusRequester()
+
+    Box(modifier = Modifier.fillMaxSize()) {
+        LazyColumn(
+            state = scrollState,
+            modifier =
+                Modifier.fillMaxSize()
+                    .rotaryScrollable(
+                        RotaryScrollableDefaults.behavior(
+                            scrollableState = scrollState,
+                            flingBehavior = ScrollableDefaults.flingBehavior()
+                        ),
+                        focusRequester = focusRequester
+                    )
+        ) {
+            item {
+                ListHeader {
+                    Text(
+                        modifier = Modifier.fillMaxWidth().padding(top = 12.dp),
+                        text = "Lazy Column",
+                        textAlign = TextAlign.Center
+                    )
+                }
+            }
+            items(5) {
+                FilledTonalButton(
+                    modifier = Modifier.fillMaxWidth().padding(horizontal = 36.dp, vertical = 2.dp),
+                    onClick = {},
+                    label = { Text("Item ${it + 1}") },
+                )
+            }
+        }
+
+        TimeText(
+            // It is recommended to use the [AppScaffold] and [ScreenScaffold] with [TimeText],
+            // so that the correct scroll-away behavior is provided by default.
+            // This demo shows how [Modifier.scrollAway] can be applied to an item if the
+            // default handling is unsuitable.
+            modifier =
+                Modifier.scrollAway(
+                    scrollInfoProvider = scrollState.toScrollAwayInfoProvider(),
+                    screenStage = {
+                        if (scrollState.isScrollInProgress) ScreenStage.Scrolling
+                        else ScreenStage.Idle
+                    }
+                ),
+            content = { text("ScrollAway") }
+        )
+    }
+}
+
+@OptIn(ExperimentalWearFoundationApi::class)
+@Composable
+fun ScrollAwayColumn() {
+    val scrollState = rememberScrollState()
+    val focusRequester = rememberActiveFocusRequester()
+
+    Box(modifier = Modifier.fillMaxSize()) {
+        Column(
+            modifier =
+                Modifier.verticalScroll(scrollState)
+                    .rotaryScrollable(
+                        RotaryScrollableDefaults.behavior(
+                            scrollableState = scrollState,
+                            flingBehavior = ScrollableDefaults.flingBehavior()
+                        ),
+                        focusRequester = focusRequester
+                    )
+        ) {
+            ListHeader {
+                Text(
+                    modifier = Modifier.fillMaxWidth().padding(top = 12.dp),
+                    text = "Column",
+                    textAlign = TextAlign.Center
+                )
+            }
+            repeat(5) {
+                FilledTonalButton(
+                    modifier = Modifier.fillMaxWidth().padding(horizontal = 36.dp, vertical = 2.dp),
+                    onClick = {},
+                    label = { Text("Item ${it + 1}") },
+                )
+            }
+        }
+
+        TimeText(
+            // It is recommended to use the [AppScaffold] and [ScreenScaffold] with [TimeText],
+            // so that the correct scroll-away behavior is provided by default.
+            // This demo shows how [Modifier.scrollAway] can be applied to an item if the
+            // default handling is unsuitable.
+            modifier =
+                Modifier.scrollAway(
+                    scrollInfoProvider = scrollState.toScrollAwayInfoProvider(),
+                    screenStage = {
+                        if (scrollState.isScrollInProgress) ScreenStage.Scrolling
+                        else ScreenStage.Idle
+                    }
+                ),
+            content = { text("ScrollAway") }
+        )
+    }
+}
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SettingsDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SettingsDemo.kt
index bef1e8b..0605fee 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SettingsDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SettingsDemo.kt
@@ -19,11 +19,8 @@
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.runtime.Composable
-import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.res.painterResource
-import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
-import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
 import androidx.wear.compose.material3.Button
 import androidx.wear.compose.material3.ButtonDefaults
 import androidx.wear.compose.material3.Icon
@@ -32,13 +29,7 @@
 
 @Composable
 fun SettingsDemo() {
-    // TODO: Add Scaffold and TimeText when available
-    val scalingLazyListState = rememberScalingLazyListState()
-    ScalingLazyColumn(
-        state = scalingLazyListState,
-        modifier = Modifier.fillMaxSize(),
-        horizontalAlignment = Alignment.CenterHorizontally
-    ) {
+    ScalingLazyDemo {
         item { ListHeader(modifier = Modifier.fillMaxWidth()) { Text("Settings") } }
         // Connectivity
         item {
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SliderDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SliderDemo.kt
index e849251..469c7d2 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SliderDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SliderDemo.kt
@@ -35,6 +35,7 @@
 import androidx.compose.ui.unit.dp
 import androidx.wear.compose.foundation.lazy.AutoCenteringParams
 import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
+import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
 import androidx.wear.compose.integration.demos.common.Centralize
 import androidx.wear.compose.integration.demos.common.ComposableDemo
 import androidx.wear.compose.material3.ExperimentalWearMaterial3Api
@@ -42,6 +43,7 @@
 import androidx.wear.compose.material3.InlineSlider
 import androidx.wear.compose.material3.InlineSliderColors
 import androidx.wear.compose.material3.InlineSliderDefaults
+import androidx.wear.compose.material3.ScreenScaffold
 import androidx.wear.compose.material3.Text
 import androidx.wear.compose.material3.samples.InlineSliderSample
 import androidx.wear.compose.material3.samples.InlineSliderSegmentedSample
@@ -70,35 +72,38 @@
 fun InlineSliderDemo(segmented: Boolean = false) {
     var enabledValue by remember { mutableFloatStateOf(5f) }
     var disabledValue by remember { mutableFloatStateOf(5f) }
-
-    ScalingLazyColumn(
-        horizontalAlignment = Alignment.CenterHorizontally,
-        verticalArrangement =
-            Arrangement.spacedBy(space = 4.dp, alignment = Alignment.CenterVertically),
-        modifier = Modifier.fillMaxSize(),
-        autoCentering = AutoCenteringParams(itemIndex = 0)
-    ) {
-        item { Text("Enabled Slider, value = $enabledValue") }
-        item {
-            DefaultInlineSlider(
-                value = enabledValue,
-                enabled = true,
-                valueRange = 1f..9f,
-                steps = 7,
-                segmented = segmented,
-                onValueChange = { enabledValue = it }
-            )
-        }
-        item { Text("Disabled Slider, value = $disabledValue") }
-        item {
-            DefaultInlineSlider(
-                value = disabledValue,
-                enabled = false,
-                onValueChange = { disabledValue = it },
-                valueRange = 1f..9f,
-                segmented = segmented,
-                steps = 7
-            )
+    val scrollState = rememberScalingLazyListState()
+    ScreenScaffold(scrollState = scrollState) {
+        ScalingLazyColumn(
+            state = scrollState,
+            horizontalAlignment = Alignment.CenterHorizontally,
+            verticalArrangement =
+                Arrangement.spacedBy(space = 4.dp, alignment = Alignment.CenterVertically),
+            modifier = Modifier.fillMaxSize(),
+            autoCentering = AutoCenteringParams(itemIndex = 0)
+        ) {
+            item { Text("Enabled Slider, value = $enabledValue") }
+            item {
+                DefaultInlineSlider(
+                    value = enabledValue,
+                    enabled = true,
+                    valueRange = 1f..9f,
+                    steps = 7,
+                    segmented = segmented,
+                    onValueChange = { enabledValue = it }
+                )
+            }
+            item { Text("Disabled Slider, value = $disabledValue") }
+            item {
+                DefaultInlineSlider(
+                    value = disabledValue,
+                    enabled = false,
+                    onValueChange = { disabledValue = it },
+                    valueRange = 1f..9f,
+                    segmented = segmented,
+                    steps = 7
+                )
+            }
         }
     }
 }
@@ -108,31 +113,34 @@
 fun InlineSliderWithIntegersDemo() {
     var valueWithoutSegments by remember { mutableIntStateOf(5) }
     var valueWithSegments by remember { mutableIntStateOf(5) }
-
-    ScalingLazyColumn(
-        horizontalAlignment = Alignment.CenterHorizontally,
-        verticalArrangement =
-            Arrangement.spacedBy(space = 4.dp, alignment = Alignment.CenterVertically),
-        modifier = Modifier.fillMaxSize(),
-        autoCentering = AutoCenteringParams(itemIndex = 0)
-    ) {
-        item { Text("No segments, value = $valueWithoutSegments") }
-        item {
-            DefaultInlineSlider(
-                value = valueWithoutSegments,
-                valueProgression = IntProgression.fromClosedRange(0, 15, 3),
-                segmented = false,
-                onValueChange = { valueWithoutSegments = it }
-            )
-        }
-        item { Text("With segments, value = $valueWithSegments") }
-        item {
-            DefaultInlineSlider(
-                value = valueWithSegments,
-                onValueChange = { valueWithSegments = it },
-                valueProgression = IntProgression.fromClosedRange(0, 15, 3),
-                segmented = true
-            )
+    val scrollState = rememberScalingLazyListState()
+    ScreenScaffold(scrollState = scrollState) {
+        ScalingLazyColumn(
+            state = scrollState,
+            horizontalAlignment = Alignment.CenterHorizontally,
+            verticalArrangement =
+                Arrangement.spacedBy(space = 4.dp, alignment = Alignment.CenterVertically),
+            modifier = Modifier.fillMaxSize(),
+            autoCentering = AutoCenteringParams(itemIndex = 0)
+        ) {
+            item { Text("No segments, value = $valueWithoutSegments") }
+            item {
+                DefaultInlineSlider(
+                    value = valueWithoutSegments,
+                    valueProgression = IntProgression.fromClosedRange(0, 15, 3),
+                    segmented = false,
+                    onValueChange = { valueWithoutSegments = it }
+                )
+            }
+            item { Text("With segments, value = $valueWithSegments") }
+            item {
+                DefaultInlineSlider(
+                    value = valueWithSegments,
+                    onValueChange = { valueWithSegments = it },
+                    valueProgression = IntProgression.fromClosedRange(0, 15, 3),
+                    segmented = true
+                )
+            }
         }
     }
 }
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SplitCheckboxButtonDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SplitCheckboxButtonDemo.kt
index 905d97a..ef5ee4c 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SplitCheckboxButtonDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SplitCheckboxButtonDemo.kt
@@ -17,29 +17,23 @@
 package androidx.wear.compose.material3.demos
 
 import android.widget.Toast
-import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.setValue
-import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.text.style.TextOverflow
-import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
 import androidx.wear.compose.material3.ListHeader
 import androidx.wear.compose.material3.SplitCheckboxButton
 import androidx.wear.compose.material3.Text
 
 @Composable
 fun SplitCheckboxButtonDemo() {
-    ScalingLazyColumn(
-        modifier = Modifier.fillMaxSize(),
-        horizontalAlignment = Alignment.CenterHorizontally,
-    ) {
+    ScalingLazyDemo {
         item { ListHeader { Text("Checkbox") } }
         item { DemoSplitCheckboxButton(enabled = true, initiallyChecked = true) }
         item { DemoSplitCheckboxButton(enabled = true, initiallyChecked = false) }
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SplitRadioButtonDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SplitRadioButtonDemo.kt
index 57d5a63..92c7587 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SplitRadioButtonDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SplitRadioButtonDemo.kt
@@ -17,19 +17,16 @@
 package androidx.wear.compose.material3.demos
 
 import android.widget.Toast
-import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableIntStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.setValue
-import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.text.style.TextOverflow
-import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
 import androidx.wear.compose.material3.ListHeader
 import androidx.wear.compose.material3.SplitRadioButton
 import androidx.wear.compose.material3.Text
@@ -39,10 +36,7 @@
     var selectedRadioIndex by remember { mutableIntStateOf(0) }
     var selectedMultiLineRadioIndex by remember { mutableIntStateOf(0) }
 
-    ScalingLazyColumn(
-        modifier = Modifier.fillMaxSize(),
-        horizontalAlignment = Alignment.CenterHorizontally,
-    ) {
+    ScalingLazyDemo {
         item { ListHeader { Text("Split Radio Button") } }
         item {
             DemoSplitRadioButton(enabled = true, (selectedRadioIndex == 0)) {
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SplitToggleButtonDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SplitToggleButtonDemo.kt
index a0f8651..b148145 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SplitToggleButtonDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SplitToggleButtonDemo.kt
@@ -17,41 +17,32 @@
 package androidx.wear.compose.material3.demos
 
 import android.widget.Toast
-import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.setValue
-import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.semantics.contentDescription
-import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.text.style.TextOverflow
-import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
 import androidx.wear.compose.material3.ListHeader
-import androidx.wear.compose.material3.SplitToggleButton
-import androidx.wear.compose.material3.Switch
+import androidx.wear.compose.material3.SplitSwitchButton
 import androidx.wear.compose.material3.Text
 
 @Composable
-fun SplitToggleButtonDemo() {
-    ScalingLazyColumn(
-        modifier = Modifier.fillMaxSize(),
-        horizontalAlignment = Alignment.CenterHorizontally,
-    ) {
+fun SplitSwitchButtonDemo() {
+    ScalingLazyDemo() {
         item { ListHeader { Text("Switch") } }
-        item { DemoSplitToggleSwitch(enabled = true, initiallyChecked = true) }
-        item { DemoSplitToggleSwitch(enabled = true, initiallyChecked = false) }
+        item { DemoSplitSwitchButton(enabled = true, initiallyChecked = true) }
+        item { DemoSplitSwitchButton(enabled = true, initiallyChecked = false) }
         item { ListHeader { Text("Disabled Switch") } }
-        item { DemoSplitToggleSwitch(enabled = false, initiallyChecked = true) }
-        item { DemoSplitToggleSwitch(enabled = false, initiallyChecked = false) }
+        item { DemoSplitSwitchButton(enabled = false, initiallyChecked = true) }
+        item { DemoSplitSwitchButton(enabled = false, initiallyChecked = false) }
         item { ListHeader { Text("Multi-line") } }
         item {
-            DemoSplitToggleSwitch(
+            DemoSplitSwitchButton(
                 enabled = true,
                 initiallyChecked = true,
                 primary = "8:15AM",
@@ -59,14 +50,14 @@
             )
         }
         item {
-            DemoSplitToggleSwitch(
+            DemoSplitSwitchButton(
                 enabled = true,
                 initiallyChecked = true,
                 primary = "Primary Label with 3 lines of content max"
             )
         }
         item {
-            DemoSplitToggleSwitch(
+            DemoSplitSwitchButton(
                 enabled = true,
                 initiallyChecked = true,
                 primary = "Primary Label with 3 lines of content max",
@@ -77,7 +68,7 @@
 }
 
 @Composable
-private fun DemoSplitToggleSwitch(
+private fun DemoSplitSwitchButton(
     enabled: Boolean,
     initiallyChecked: Boolean,
     primary: String = "Primary label",
@@ -85,7 +76,7 @@
 ) {
     var checked by remember { mutableStateOf(initiallyChecked) }
     val context = LocalContext.current
-    SplitToggleButton(
+    SplitSwitchButton(
         modifier = Modifier.fillMaxWidth(),
         label = {
             Text(
@@ -109,12 +100,13 @@
                 }
             },
         checked = checked,
-        toggleControl = { Switch(modifier = Modifier.semantics { contentDescription = primary }) },
         onCheckedChange = { checked = it },
-        onClick = {
+        toggleContentDescription = primary,
+        onContainerClick = {
             val toastText = if (checked) "Checked" else "Not Checked"
             Toast.makeText(context, toastText, Toast.LENGTH_SHORT).show()
         },
+        containerClickLabel = "click",
         enabled = enabled,
     )
 }
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SwitchButtonDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SwitchButtonDemo.kt
new file mode 100644
index 0000000..876a797
--- /dev/null
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SwitchButtonDemo.kt
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.material3.demos
+
+import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Favorite
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.wear.compose.material3.Icon
+import androidx.wear.compose.material3.ListHeader
+import androidx.wear.compose.material3.SwitchButton
+import androidx.wear.compose.material3.Text
+
+@Composable
+fun SwitchButtonDemo() {
+    ScalingLazyDemo() {
+        item { ListHeader { Text("Switch") } }
+        item { DemoSwitchButton(enabled = true, initiallyChecked = true) }
+        item { DemoSwitchButton(enabled = true, initiallyChecked = false) }
+        item { ListHeader { Text("Disabled Switch") } }
+        item { DemoSwitchButton(enabled = false, initiallyChecked = true) }
+        item { DemoSwitchButton(enabled = false, initiallyChecked = false) }
+        item { ListHeader { Text("Icon") } }
+        item {
+            DemoSwitchButton(
+                enabled = true,
+                initiallyChecked = true,
+                primary = "Primary label",
+            ) {
+                Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Favorite icon")
+            }
+        }
+        item {
+            DemoSwitchButton(
+                enabled = true,
+                initiallyChecked = true,
+                primary = "Primary label",
+                secondary = "Secondary label"
+            ) {
+                Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Favorite icon")
+            }
+        }
+        item { ListHeader { Text("Multi-line") } }
+        item {
+            DemoSwitchButton(
+                enabled = true,
+                initiallyChecked = true,
+                primary = "8:15AM",
+                secondary = "Monday"
+            )
+        }
+        item {
+            DemoSwitchButton(
+                enabled = true,
+                initiallyChecked = true,
+                primary = "Primary Label with 3 lines of content max"
+            )
+        }
+        item {
+            DemoSwitchButton(
+                enabled = true,
+                initiallyChecked = true,
+                primary = "Primary Label with 3 lines of content max",
+                secondary = "Secondary label with 2 lines"
+            )
+        }
+    }
+}
+
+@Composable
+private fun DemoSwitchButton(
+    enabled: Boolean,
+    initiallyChecked: Boolean,
+    primary: String = "Primary label",
+    secondary: String = "",
+    content: (@Composable BoxScope.() -> Unit)? = null,
+) {
+    var checked by remember { mutableStateOf(initiallyChecked) }
+    SwitchButton(
+        modifier = Modifier.fillMaxWidth(),
+        icon = content,
+        label = {
+            Text(
+                primary,
+                modifier = Modifier.fillMaxWidth(),
+                maxLines = 3,
+                textAlign = TextAlign.Start,
+                overflow = TextOverflow.Ellipsis
+            )
+        },
+        secondaryLabel = {
+            if (secondary.isNotEmpty()) {
+                Text(
+                    secondary,
+                    modifier = Modifier.fillMaxWidth(),
+                    maxLines = 2,
+                    textAlign = TextAlign.Start,
+                    overflow = TextOverflow.Ellipsis
+                )
+            }
+        },
+        checked = checked,
+        onCheckedChange = { checked = it },
+        enabled = enabled,
+    )
+}
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/TextButtonDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/TextButtonDemo.kt
index 314073e..9f3d934 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/TextButtonDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/TextButtonDemo.kt
@@ -18,7 +18,6 @@
 
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.width
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
@@ -27,7 +26,6 @@
 import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
-import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
 import androidx.wear.compose.material3.ButtonDefaults
 import androidx.wear.compose.material3.ListHeader
 import androidx.wear.compose.material3.Text
@@ -44,10 +42,7 @@
 @Composable
 fun TextButtonDemo() {
     val context = LocalContext.current
-    ScalingLazyColumn(
-        modifier = Modifier.fillMaxSize(),
-        horizontalAlignment = Alignment.CenterHorizontally,
-    ) {
+    ScalingLazyDemo {
         item { ListHeader { Text("Text Button") } }
         item {
             Row {
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/TextToggleButtonDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/TextToggleButtonDemo.kt
index 0b3c923..9e4337f 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/TextToggleButtonDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/TextToggleButtonDemo.kt
@@ -18,7 +18,6 @@
 
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.width
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
@@ -30,7 +29,6 @@
 import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
-import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
 import androidx.wear.compose.material3.ListHeader
 import androidx.wear.compose.material3.Text
 import androidx.wear.compose.material3.TextButtonDefaults
@@ -41,10 +39,7 @@
 
 @Composable
 fun TextToggleButtonDemo() {
-    ScalingLazyColumn(
-        modifier = Modifier.fillMaxSize(),
-        horizontalAlignment = Alignment.CenterHorizontally,
-    ) {
+    ScalingLazyDemo {
         item { ListHeader { Text("Text Toggle Button", textAlign = TextAlign.Center) } }
         item {
             Row {
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/TimeTextDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/TimeTextDemo.kt
index a71965d..a32b271 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/TimeTextDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/TimeTextDemo.kt
@@ -33,11 +33,21 @@
     listOf(
         ComposableDemo("Clock only") { TimeTextClockOnly() },
         ComposableDemo("Clock with Status") { TimeTextWithStatus() },
+        ComposableDemo("Clock with long Status") { TimeTextWithLongStatus() },
         ComposableDemo("Clock with Icon") { TimeTextWithIcon() },
         ComposableDemo("Clock with custom colors") { TimeTextWithCustomColors() }
     )
 
 @Composable
+fun TimeTextWithLongStatus() {
+    TimeText {
+        text("Some long leading text")
+        separator()
+        time()
+    }
+}
+
+@Composable
 fun TimeTextWithCustomColors() {
     val customStyle = TimeTextDefaults.timeTextStyle(color = Color.Red)
 
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ToggleButtonDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ToggleButtonDemo.kt
deleted file mode 100644
index dd526d1..0000000
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ToggleButtonDemo.kt
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.wear.compose.material3.demos
-
-import androidx.compose.foundation.layout.BoxScope
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Favorite
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.text.style.TextAlign
-import androidx.compose.ui.text.style.TextOverflow
-import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
-import androidx.wear.compose.material3.Icon
-import androidx.wear.compose.material3.ListHeader
-import androidx.wear.compose.material3.Switch
-import androidx.wear.compose.material3.Text
-import androidx.wear.compose.material3.ToggleButton
-
-@Composable
-fun ToggleButtonDemo() {
-    ScalingLazyColumn(
-        modifier = Modifier.fillMaxSize(),
-        horizontalAlignment = Alignment.CenterHorizontally,
-    ) {
-        item { ListHeader { Text("Switch") } }
-        item { DemoToggleSwitch(enabled = true, initiallyChecked = true) }
-        item { DemoToggleSwitch(enabled = true, initiallyChecked = false) }
-        item { ListHeader { Text("Disabled Switch") } }
-        item { DemoToggleSwitch(enabled = false, initiallyChecked = true) }
-        item { DemoToggleSwitch(enabled = false, initiallyChecked = false) }
-        item { ListHeader { Text("Icon") } }
-        item {
-            DemoToggleSwitch(
-                enabled = true,
-                initiallyChecked = true,
-                primary = "Primary label",
-            ) {
-                Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Favorite icon")
-            }
-        }
-        item {
-            DemoToggleSwitch(
-                enabled = true,
-                initiallyChecked = true,
-                primary = "Primary label",
-                secondary = "Secondary label"
-            ) {
-                Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Favorite icon")
-            }
-        }
-        item { ListHeader { Text("Multi-line") } }
-        item {
-            DemoToggleSwitch(
-                enabled = true,
-                initiallyChecked = true,
-                primary = "8:15AM",
-                secondary = "Monday"
-            )
-        }
-        item {
-            DemoToggleSwitch(
-                enabled = true,
-                initiallyChecked = true,
-                primary = "Primary Label with 3 lines of content max"
-            )
-        }
-        item {
-            DemoToggleSwitch(
-                enabled = true,
-                initiallyChecked = true,
-                primary = "Primary Label with 3 lines of content max",
-                secondary = "Secondary label with 2 lines"
-            )
-        }
-    }
-}
-
-@Composable
-private fun DemoToggleSwitch(
-    enabled: Boolean,
-    initiallyChecked: Boolean,
-    primary: String = "Primary label",
-    secondary: String = "",
-    content: (@Composable BoxScope.() -> Unit)? = null,
-) {
-    var checked by remember { mutableStateOf(initiallyChecked) }
-    ToggleButton(
-        modifier = Modifier.fillMaxWidth(),
-        icon = content,
-        label = {
-            Text(
-                primary,
-                modifier = Modifier.fillMaxWidth(),
-                maxLines = 3,
-                textAlign = TextAlign.Start,
-                overflow = TextOverflow.Ellipsis
-            )
-        },
-        secondaryLabel = {
-            if (secondary.isNotEmpty()) {
-                Text(
-                    secondary,
-                    modifier = Modifier.fillMaxWidth(),
-                    maxLines = 2,
-                    textAlign = TextAlign.Start,
-                    overflow = TextOverflow.Ellipsis
-                )
-            }
-        },
-        checked = checked,
-        toggleControl = { Switch() },
-        onCheckedChange = { checked = it },
-        enabled = enabled,
-    )
-}
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ToggleControlsDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ToggleControlsDemo.kt
deleted file mode 100644
index 2d26578..0000000
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ToggleControlsDemo.kt
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.wear.compose.material3.demos
-
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.LocalLayoutDirection
-import androidx.compose.ui.text.style.TextOverflow
-import androidx.compose.ui.unit.LayoutDirection
-import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
-import androidx.wear.compose.material3.ListHeader
-import androidx.wear.compose.material3.Switch
-import androidx.wear.compose.material3.Text
-import androidx.wear.compose.material3.ToggleButton
-
-@Composable
-fun SwitchDemos() {
-    ScalingLazyColumn(
-        modifier = Modifier.fillMaxSize(),
-        horizontalAlignment = Alignment.CenterHorizontally,
-    ) {
-        item { ListHeader { Text(text = "Switch") } }
-        item { SwitchDemo(initialChecked = false, enabled = true) }
-        item { SwitchDemo(initialChecked = true, enabled = true) }
-        item { ListHeader { Text(text = "Disabled Switch") } }
-        item { SwitchDemo(initialChecked = false, enabled = false) }
-        item { SwitchDemo(initialChecked = true, enabled = false) }
-        item { ListHeader { Text(text = "RTL Switch") } }
-        item {
-            CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
-                SwitchDemo(initialChecked = false, enabled = true)
-            }
-        }
-        item {
-            CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
-                SwitchDemo(initialChecked = true, enabled = true)
-            }
-        }
-    }
-}
-
-@Composable
-private fun SwitchDemo(initialChecked: Boolean, enabled: Boolean) {
-    var checked by remember { mutableStateOf(initialChecked) }
-    ToggleButton(
-        label = { Text("Primary label", maxLines = 1, overflow = TextOverflow.Ellipsis) },
-        checked = checked,
-        toggleControl = { Switch() },
-        onCheckedChange = { checked = it },
-        enabled = enabled,
-    )
-}
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/TypographyDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/TypographyDemo.kt
new file mode 100644
index 0000000..631150f
--- /dev/null
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/TypographyDemo.kt
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.material3.demos
+
+import androidx.compose.foundation.layout.Column
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.text.style.TextAlign
+import androidx.wear.compose.foundation.CurvedLayout
+import androidx.wear.compose.foundation.CurvedTextStyle
+import androidx.wear.compose.integration.demos.common.Centralize
+import androidx.wear.compose.integration.demos.common.ComposableDemo
+import androidx.wear.compose.integration.demos.common.DemoCategory
+import androidx.wear.compose.material3.MaterialTheme
+import androidx.wear.compose.material3.Text
+import androidx.wear.compose.material3.curvedText
+
+var TypographyDemos =
+    listOf(
+        DemoCategory(
+            "Arc",
+            listOf(
+                ComposableDemo("Arc Small") {
+                    val curvedStyle = CurvedTextStyle(MaterialTheme.typography.arcSmall)
+                    CurvedLayout { curvedText("Arc Small", style = curvedStyle) }
+                },
+                ComposableDemo("Arc Medium") {
+                    val curvedStyle = CurvedTextStyle(MaterialTheme.typography.arcMedium)
+                    CurvedLayout { curvedText("Arc Medium", style = curvedStyle) }
+                }
+            )
+        ),
+        DemoCategory(
+            "Display",
+            listOf(
+                ComposableDemo("Display Small") {
+                    Centralize {
+                        Text(
+                            "Display Small",
+                            textAlign = TextAlign.Center,
+                            style = MaterialTheme.typography.displaySmall
+                        )
+                    }
+                },
+                ComposableDemo("Display Medium") {
+                    Centralize {
+                        Text(
+                            "Display Medium",
+                            textAlign = TextAlign.Center,
+                            style = MaterialTheme.typography.displayMedium
+                        )
+                    }
+                },
+                ComposableDemo("Display Large") {
+                    Centralize {
+                        Text(
+                            "Display Large",
+                            textAlign = TextAlign.Center,
+                            style = MaterialTheme.typography.displayLarge
+                        )
+                    }
+                }
+            )
+        ),
+        ComposableDemo("Title") {
+            Centralize {
+                Column(horizontalAlignment = Alignment.CenterHorizontally) {
+                    Text("Title Small", style = MaterialTheme.typography.titleSmall)
+                    Text("Title Medium", style = MaterialTheme.typography.titleMedium)
+                    Text("Title Large", style = MaterialTheme.typography.titleLarge)
+                }
+            }
+        },
+        ComposableDemo("Label") {
+            Centralize {
+                Column(horizontalAlignment = Alignment.CenterHorizontally) {
+                    Text("Label Small", style = MaterialTheme.typography.labelSmall)
+                    Text("Label Medium", style = MaterialTheme.typography.labelMedium)
+                    Text("Label Large", style = MaterialTheme.typography.labelLarge)
+                }
+            }
+        },
+        ComposableDemo("Body") {
+            Centralize {
+                Column(horizontalAlignment = Alignment.CenterHorizontally) {
+                    Text("Body Extra Small", style = MaterialTheme.typography.bodyExtraSmall)
+                    Text("Body Small", style = MaterialTheme.typography.bodySmall)
+                    Text("Body Medium", style = MaterialTheme.typography.bodyMedium)
+                    Text("Body Large", style = MaterialTheme.typography.bodyLarge)
+                }
+            }
+        },
+        DemoCategory(
+            "Numeral",
+            listOf(
+                ComposableDemo("Extra Small") {
+                    Centralize { Text("0123", style = MaterialTheme.typography.numeralExtraSmall) }
+                },
+                ComposableDemo("Small") {
+                    Centralize { Text("0123", style = MaterialTheme.typography.numeralSmall) }
+                },
+                ComposableDemo("Medium") {
+                    Centralize { Text("0123", style = MaterialTheme.typography.numeralMedium) }
+                },
+                ComposableDemo("Large") {
+                    Centralize { Text("0123", style = MaterialTheme.typography.numeralLarge) }
+                },
+                ComposableDemo("Extra Large") {
+                    Centralize { Text("0123", style = MaterialTheme.typography.numeralExtraLarge) }
+                }
+            )
+        ),
+    )
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/WearMaterial3Demos.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/WearMaterial3Demos.kt
index 3134ff2..b7e97ab 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/WearMaterial3Demos.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/WearMaterial3Demos.kt
@@ -17,14 +17,20 @@
 package androidx.wear.compose.material3.demos
 
 import android.content.Context
+import android.os.Build
 import android.widget.Toast
 import androidx.wear.compose.integration.demos.common.Centralize
 import androidx.wear.compose.integration.demos.common.ComposableDemo
 import androidx.wear.compose.integration.demos.common.Material3DemoCategory
+import androidx.wear.compose.material3.samples.AnimatedTextSample
+import androidx.wear.compose.material3.samples.AnimatedTextSampleButtonResponse
+import androidx.wear.compose.material3.samples.AnimatedTextSampleSharedFontRegistry
+import androidx.wear.compose.material3.samples.EdgeButtonSample
 import androidx.wear.compose.material3.samples.EdgeSwipeForSwipeToDismiss
 import androidx.wear.compose.material3.samples.FixedFontSize
 import androidx.wear.compose.material3.samples.HorizontalPageIndicatorSample
 import androidx.wear.compose.material3.samples.HorizontalPageIndicatorWithPagerSample
+import androidx.wear.compose.material3.samples.ScaffoldSample
 import androidx.wear.compose.material3.samples.SimpleSwipeToDismissBox
 import androidx.wear.compose.material3.samples.StatefulSwipeToDismissBox
 import androidx.wear.compose.material3.samples.StepperSample
@@ -35,9 +41,19 @@
     Material3DemoCategory(
         "Material 3",
         listOf(
+            ComposableDemo("Scaffold") { ScaffoldSample() },
+            Material3DemoCategory("ScrollAway", ScrollAwayDemos),
             Material3DemoCategory(
                 "Button",
                 listOf(
+                    Material3DemoCategory(
+                        "Edge Button",
+                        listOf(
+                            ComposableDemo("Simple Edge Button") { EdgeButtonSample() },
+                            ComposableDemo("Edge Button Sizes") { EdgeButtonSizeDemo() },
+                            ComposableDemo("Edge Button Below List") { EdgeButtonBelowListDemo() },
+                        )
+                    ),
                     ComposableDemo("Button") { ButtonDemo() },
                     ComposableDemo("Filled Tonal Button") { FilledTonalButtonDemo() },
                     ComposableDemo("Outlined Button") { OutlinedButtonDemo() },
@@ -54,13 +70,12 @@
             ComposableDemo("Icon Button") { IconButtonDemo() },
             ComposableDemo("Text Toggle Button") { TextToggleButtonDemo() },
             ComposableDemo("Icon Toggle Button") { IconToggleButtonDemo() },
-            ComposableDemo("Switch") { SwitchDemos() },
             ComposableDemo("Checkbox Button") { CheckboxButtonDemo() },
             ComposableDemo("Split Checkbox Button") { SplitCheckboxButtonDemo() },
             ComposableDemo("Radio Button") { RadioButtonDemo() },
             ComposableDemo("Split Radio Button") { SplitRadioButtonDemo() },
-            ComposableDemo("Toggle Button") { ToggleButtonDemo() },
-            ComposableDemo("Split Toggle Button") { SplitToggleButtonDemo() },
+            ComposableDemo("Switch Button") { SwitchButtonDemo() },
+            ComposableDemo("Split Switch Button") { SplitSwitchButtonDemo() },
             Material3DemoCategory(
                 "Stepper",
                 listOf(
@@ -103,6 +118,23 @@
                     },
                 )
             ),
+            Material3DemoCategory(title = "Typography", TypographyDemos),
+            Material3DemoCategory(
+                "Animated Text",
+                if (Build.VERSION.SDK_INT > 31) {
+                    listOf(
+                        ComposableDemo("Simple animation") { Centralize { AnimatedTextSample() } },
+                        ComposableDemo("Animation with button click") {
+                            Centralize { AnimatedTextSampleButtonResponse() }
+                        },
+                        ComposableDemo("Shared Font Registry") {
+                            Centralize { AnimatedTextSampleSharedFontRegistry() }
+                        },
+                    )
+                } else {
+                    emptyList()
+                }
+            ),
             ComposableDemo("Settings Demo") { SettingsDemo() }
         )
     )
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/AnimatedTextSample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/AnimatedTextSample.kt
new file mode 100644
index 0000000..e3389e9
--- /dev/null
+++ b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/AnimatedTextSample.kt
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.material3.samples
+
+import androidx.annotation.Sampled
+import androidx.compose.animation.core.Animatable
+import androidx.compose.foundation.layout.Column
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.text.font.FontVariation
+import androidx.compose.ui.unit.sp
+import androidx.wear.compose.material3.AnimatedText
+import androidx.wear.compose.material3.Button
+import androidx.wear.compose.material3.Text
+import androidx.wear.compose.material3.rememberAnimatedTextFontRegistry
+import kotlinx.coroutines.launch
+
+@Sampled
+@Composable
+fun AnimatedTextSample() {
+    val animatable = remember { Animatable(0f) }
+    val animatedTextFontRegistry =
+        rememberAnimatedTextFontRegistry(
+            // Variation axes at the start of the animation, width 10, weight 200
+            startFontVariationSettings =
+                FontVariation.Settings(
+                    FontVariation.width(10f),
+                    FontVariation.weight(200),
+                ),
+            // Variation axes at the end of the animation, width 100, weight 500
+            endFontVariationSettings =
+                FontVariation.Settings(
+                    FontVariation.width(100f),
+                    FontVariation.weight(500),
+                ),
+            startFontSize = 30.sp,
+            endFontSize = 40.sp,
+        )
+    AnimatedText(
+        text = "Hello!",
+        fontRegistry = animatedTextFontRegistry,
+        // Content alignment anchors the animation at the vertical center, expanding horizontally
+        contentAlignment = Alignment.CenterStart,
+        progressFraction = { animatable.value },
+    )
+    LaunchedEffect(Unit) {
+        // Animate from 0 to 1 and then back to 0.
+        animatable.animateTo(1f)
+        animatable.animateTo(0f)
+    }
+}
+
+@Sampled
+@Composable
+fun AnimatedTextSampleButtonResponse() {
+    val scope = rememberCoroutineScope()
+    val animatedTextFontRegistry =
+        rememberAnimatedTextFontRegistry(
+            // Variation axes at the start of the animation, width 10, weight 200
+            startFontVariationSettings =
+                FontVariation.Settings(
+                    FontVariation.width(10f),
+                    FontVariation.weight(200),
+                ),
+            // Variation axes at the end of the animation, width 100, weight 500
+            endFontVariationSettings =
+                FontVariation.Settings(
+                    FontVariation.width(100f),
+                    FontVariation.weight(500),
+                ),
+            startFontSize = 30.sp,
+            endFontSize = 40.sp,
+        )
+    val firstNumber = remember { mutableIntStateOf(0) }
+    val firstAnimatable = remember { Animatable(0f) }
+    val secondNumber = remember { mutableIntStateOf(0) }
+    val secondAnimatable = remember { Animatable(0f) }
+    Column(horizontalAlignment = Alignment.CenterHorizontally) {
+        AnimatedText(
+            text = "${firstNumber.value}",
+            fontRegistry = animatedTextFontRegistry,
+            progressFraction = { firstAnimatable.value },
+        )
+        Button(
+            onClick = {
+                firstNumber.value += 1
+                scope.launch {
+                    firstAnimatable.animateTo(1f)
+                    firstAnimatable.animateTo(0f)
+                }
+            },
+            label = { Text("+") }
+        )
+        AnimatedText(
+            text = "${secondNumber.value}",
+            fontRegistry = animatedTextFontRegistry,
+            progressFraction = { secondAnimatable.value },
+        )
+        Button(
+            onClick = {
+                secondNumber.value += 1
+                scope.launch {
+                    secondAnimatable.animateTo(1f)
+                    secondAnimatable.animateTo(0f)
+                }
+            },
+            label = { Text("+") }
+        )
+    }
+}
+
+@Sampled
+@Composable
+fun AnimatedTextSampleSharedFontRegistry() {
+    val animatedTextFontRegistry =
+        rememberAnimatedTextFontRegistry(
+            // Variation axes at the start of the animation, width 10, weight 200
+            startFontVariationSettings =
+                FontVariation.Settings(
+                    FontVariation.width(10f),
+                    FontVariation.weight(200),
+                ),
+            // Variation axes at the end of the animation, width 100, weight 500
+            endFontVariationSettings =
+                FontVariation.Settings(
+                    FontVariation.width(100f),
+                    FontVariation.weight(500),
+                ),
+            startFontSize = 15.sp,
+            endFontSize = 25.sp,
+        )
+    val firstAnimatable = remember { Animatable(0f) }
+    val secondAnimatable = remember { Animatable(0f) }
+    Column(horizontalAlignment = Alignment.CenterHorizontally) {
+        AnimatedText(
+            text = "Top Text",
+            fontRegistry = animatedTextFontRegistry,
+            progressFraction = { firstAnimatable.value },
+        )
+        AnimatedText(
+            text = "Bottom Text",
+            fontRegistry = animatedTextFontRegistry,
+            progressFraction = { secondAnimatable.value },
+        )
+    }
+    LaunchedEffect(Unit) {
+        firstAnimatable.animateTo(1f)
+        firstAnimatable.animateTo(0f)
+        secondAnimatable.animateTo(1f)
+        secondAnimatable.animateTo(0f)
+    }
+}
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/CheckboxButtonSample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/CheckboxButtonSample.kt
index 01d8ea1..5b32171 100644
--- a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/CheckboxButtonSample.kt
+++ b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/CheckboxButtonSample.kt
@@ -54,7 +54,7 @@
         label = { Text("Split Checkbox Button", maxLines = 3, overflow = TextOverflow.Ellipsis) },
         checked = checked,
         onCheckedChange = { checked = it },
-        toggleContentDescription = "Split Checkbox Sample",
+        toggleContentDescription = "Split Checkbox Button Sample",
         onContainerClick = {
             /* Do something */
         },
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/EdgeButtonSample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/EdgeButtonSample.kt
new file mode 100644
index 0000000..0d49823
--- /dev/null
+++ b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/EdgeButtonSample.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.material3.samples
+
+import androidx.annotation.Sampled
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.size
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Check
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.wear.compose.material3.ButtonDefaults
+import androidx.wear.compose.material3.EdgeButton
+import androidx.wear.compose.material3.Icon
+import androidx.wear.compose.material3.Text
+
+@Sampled
+@Composable
+fun EdgeButtonSample() {
+    Box(Modifier.fillMaxSize()) {
+        Text("Confirm", Modifier.align(Alignment.Center))
+        EdgeButton(
+            onClick = { /* Do something */ },
+            buttonHeight = ButtonDefaults.EdgeButtonHeightMedium,
+            modifier = Modifier.align(Alignment.BottomEnd)
+        ) {
+            Icon(
+                Icons.Filled.Check,
+                contentDescription = "Check icon",
+                modifier = Modifier.size(ButtonDefaults.IconSize)
+            )
+        }
+    }
+}
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/ScaffoldSample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/ScaffoldSample.kt
new file mode 100644
index 0000000..6db4fb0
--- /dev/null
+++ b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/ScaffoldSample.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.material3.samples
+
+import androidx.annotation.Sampled
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
+import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
+import androidx.wear.compose.material3.AppScaffold
+import androidx.wear.compose.material3.Button
+import androidx.wear.compose.material3.ScreenScaffold
+import androidx.wear.compose.material3.Text
+
+@Sampled
+@Composable
+fun ScaffoldSample() {
+    // Declare just one [AppScaffold] per app such as in the activity.
+    // [AppScaffold] allows static screen elements (i.e. [TimeText]) to remain visible
+    // during in-app transitions such as swipe-to-dismiss.
+    AppScaffold {
+        // Define the navigation hierarchy within the AppScaffold,
+        // such as using SwipeDismissableNavHost.
+        // For this sample, we will define a single screen inline.
+        val listState = rememberScalingLazyListState()
+
+        // By default, ScreenScaffold will handle transitions showing/hiding ScrollIndicator
+        // and showing/hiding/scrolling away TimeText.
+        ScreenScaffold(scrollState = listState) {
+            ScalingLazyColumn(state = listState, modifier = Modifier.fillMaxSize()) {
+                items(10) {
+                    Button(
+                        onClick = {},
+                        label = { Text("Item ${it + 1}") },
+                    )
+                }
+            }
+        }
+    }
+}
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/ScrollAwaySample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/ScrollAwaySample.kt
new file mode 100644
index 0000000..0d8de7d
--- /dev/null
+++ b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/ScrollAwaySample.kt
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.material3.samples
+
+import androidx.annotation.Sampled
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.dp
+import androidx.wear.compose.foundation.lazy.AutoCenteringParams
+import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
+import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
+import androidx.wear.compose.foundation.toScrollAwayInfoProvider
+import androidx.wear.compose.material3.FilledTonalButton
+import androidx.wear.compose.material3.ListHeader
+import androidx.wear.compose.material3.ScreenStage
+import androidx.wear.compose.material3.Text
+import androidx.wear.compose.material3.TimeText
+import androidx.wear.compose.material3.scrollAway
+
+@Sampled
+@Composable
+fun ScrollAwaySample() {
+    val state = rememberScalingLazyListState()
+
+    Box(modifier = Modifier.fillMaxSize()) {
+        ScalingLazyColumn(
+            state = state,
+            modifier = Modifier.fillMaxSize(),
+            autoCentering = AutoCenteringParams(itemIndex = 10)
+        ) {
+            item {
+                ListHeader {
+                    Text(
+                        modifier = Modifier.fillMaxWidth(),
+                        text = "ScalingLazyColumn",
+                        textAlign = TextAlign.Center
+                    )
+                }
+            }
+            items(50) {
+                FilledTonalButton(
+                    modifier = Modifier.fillMaxWidth().padding(horizontal = 36.dp),
+                    onClick = {},
+                    label = { Text("Item ${it + 1}") },
+                )
+            }
+        }
+        TimeText(
+            // In practice, it is recommended to use the [AppScaffold] and [ScreenScaffold],
+            // so that the Material3 scroll away behavior is provided by default, rather than using
+            // [Modifier.scrollAway] directly.
+            modifier =
+                Modifier.scrollAway(
+                    scrollInfoProvider = state.toScrollAwayInfoProvider(),
+                    screenStage = {
+                        if (state.isScrollInProgress) ScreenStage.Scrolling else ScreenStage.Idle
+                    }
+                ),
+            content = {
+                text("ScrollAway")
+                separator()
+                time()
+            }
+        )
+    }
+}
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/SwitchButtonSample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/SwitchButtonSample.kt
new file mode 100644
index 0000000..3953b1b
--- /dev/null
+++ b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/SwitchButtonSample.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.material3.samples
+
+import androidx.annotation.Sampled
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Favorite
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.wear.compose.material3.Icon
+import androidx.wear.compose.material3.SplitSwitchButton
+import androidx.wear.compose.material3.SwitchButton
+import androidx.wear.compose.material3.Text
+
+@Sampled
+@Composable
+fun SwitchButtonSample() {
+    var checked by remember { mutableStateOf(true) }
+    SwitchButton(
+        label = { Text("Switch Button", maxLines = 3, overflow = TextOverflow.Ellipsis) },
+        secondaryLabel = {
+            Text("With secondary label", maxLines = 2, overflow = TextOverflow.Ellipsis)
+        },
+        checked = checked,
+        onCheckedChange = { checked = it },
+        icon = { Icon(Icons.Filled.Favorite, contentDescription = "Favorite icon") },
+        enabled = true,
+    )
+}
+
+@Sampled
+@Composable
+fun SplitSwitchButtonSample() {
+    var checked by remember { mutableStateOf(true) }
+    SplitSwitchButton(
+        label = { Text("Split Switch Button", maxLines = 3, overflow = TextOverflow.Ellipsis) },
+        checked = checked,
+        onCheckedChange = { checked = it },
+        toggleContentDescription = "Split Switch Button Sample",
+        onContainerClick = {
+            /* Do something */
+        },
+        enabled = true,
+    )
+}
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/ToggleButtonSample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/ToggleButtonSample.kt
deleted file mode 100644
index b835b30..0000000
--- a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/ToggleButtonSample.kt
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.wear.compose.material3.samples
-
-import androidx.annotation.Sampled
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Favorite
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.text.style.TextOverflow
-import androidx.wear.compose.material3.Icon
-import androidx.wear.compose.material3.SplitToggleButton
-import androidx.wear.compose.material3.Switch
-import androidx.wear.compose.material3.Text
-import androidx.wear.compose.material3.ToggleButton
-
-@Sampled
-@Composable
-fun ToggleButtonWithSwitch() {
-    var checked by remember { mutableStateOf(true) }
-    ToggleButton(
-        label = { Text("Switch", maxLines = 3, overflow = TextOverflow.Ellipsis) },
-        secondaryLabel = {
-            Text("With secondary label", maxLines = 2, overflow = TextOverflow.Ellipsis)
-        },
-        checked = checked,
-        toggleControl = { Switch() },
-        onCheckedChange = { checked = it },
-        icon = { Icon(Icons.Filled.Favorite, contentDescription = "Favorite icon") },
-        enabled = true,
-    )
-}
-
-@Sampled
-@Composable
-fun SplitToggleButtonWithSwitch() {
-    var checked by remember { mutableStateOf(true) }
-    SplitToggleButton(
-        label = { Text("Split with CheckboxIcon", maxLines = 3, overflow = TextOverflow.Ellipsis) },
-        checked = checked,
-        toggleControl = { Switch() },
-        onCheckedChange = { checked = it },
-        onClick = {
-            /* Do something */
-        },
-        enabled = true,
-    )
-}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/AnimatedTextScreenshotTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/AnimatedTextScreenshotTest.kt
new file mode 100644
index 0000000..9c0a09d
--- /dev/null
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/AnimatedTextScreenshotTest.kt
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.material3
+
+import android.os.Build
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.runtime.Composable
+import androidx.compose.testutils.assertAgainstGolden
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.captureToImage
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.text.font.FontVariation
+import androidx.compose.ui.unit.sp
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.screenshot.AndroidXScreenshotTestRule
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TestName
+import org.junit.runner.RunWith
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
+class AnimatedTextScreenshotTest {
+
+    @get:Rule val rule = createComposeRule()
+
+    @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+
+    @get:Rule val testName = TestName()
+
+    @Test fun animatedText_0f() = verifyScreenshot { BaseAnimatedText(0f) }
+
+    @Test fun animatedText_0_25f() = verifyScreenshot { BaseAnimatedText(0.25f) }
+
+    @Test fun animatedText_0_5f() = verifyScreenshot { BaseAnimatedText(0.5f) }
+
+    @Test fun animatedText_0_75f() = verifyScreenshot { BaseAnimatedText(0.75f) }
+
+    @Test fun animatedText_1f() = verifyScreenshot { BaseAnimatedText(1f) }
+
+    @Composable
+    private fun BaseAnimatedText(progressFraction: Float) {
+        val animatedTextFontRegistry =
+            rememberAnimatedTextFontRegistry(
+                // Variation axes at the start of the animation, width 10, weight 200
+                startFontVariationSettings =
+                    FontVariation.Settings(
+                        FontVariation.width(10f),
+                        FontVariation.weight(200),
+                    ),
+                // Variation axes at the end of the animation, width 100, weight 500
+                endFontVariationSettings =
+                    FontVariation.Settings(
+                        FontVariation.width(100f),
+                        FontVariation.weight(500),
+                    ),
+                startFontSize = 10.sp,
+                endFontSize = 50.sp,
+            )
+        AnimatedText(
+            text = "Hello!",
+            fontRegistry = animatedTextFontRegistry,
+            contentAlignment = Alignment.Center,
+            progressFraction = { progressFraction },
+            modifier = Modifier.testTag(TEST_TAG),
+        )
+    }
+
+    private fun verifyScreenshot(content: @Composable () -> Unit) {
+        rule.setContentWithTheme {
+            Box(
+                modifier = Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background)
+            ) {
+                content()
+            }
+        }
+
+        rule
+            .onNodeWithTag(TEST_TAG)
+            .captureToImage()
+            .assertAgainstGolden(screenshotRule, testName.methodName)
+    }
+}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ButtonTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ButtonTest.kt
index 5e725adf..2cc30f4 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ButtonTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ButtonTest.kt
@@ -558,7 +558,7 @@
         val status = Status.Disabled
         rule.verifyButtonBorderColor(
             expectedBorderColor = {
-                MaterialTheme.colorScheme.outline.copy(alpha = DisabledBorderAlpha)
+                MaterialTheme.colorScheme.onSurface.copy(alpha = DisabledBorderAlpha)
             },
             content = { modifier: Modifier ->
                 OutlinedButton(
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CurvedTextTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CurvedTextTest.kt
index 036c740..f42a497 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CurvedTextTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CurvedTextTest.kt
@@ -30,6 +30,7 @@
 import androidx.wear.compose.foundation.CurvedLayout
 import androidx.wear.compose.foundation.CurvedTextStyle
 import androidx.wear.compose.foundation.curvedRow
+import androidx.wear.compose.material3.tokens.TypographyTokens
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -97,4 +98,25 @@
             .captureToImage()
             .assertContainsColor(Color.Yellow)
     }
+
+    @Test
+    fun uses_ArcMedium_style() {
+        rule.setContent {
+            MaterialTheme(
+                typography =
+                    Typography(arcMedium = TypographyTokens.ArcMedium.copy(color = Color.Yellow))
+            ) {
+                CurvedLayout {
+                    curvedText(
+                        text = testText,
+                    )
+                }
+            }
+        }
+
+        rule
+            .onNodeWithContentDescription(testText)
+            .captureToImage()
+            .assertContainsColor(Color.Yellow)
+    }
 }
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/EdgeButtonScreenshotTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/EdgeButtonScreenshotTest.kt
new file mode 100644
index 0000000..eee671e
--- /dev/null
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/EdgeButtonScreenshotTest.kt
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.material3
+
+import android.os.Build
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.text.BasicText
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.testutils.assertAgainstGolden
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalLayoutDirection
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.captureToImage
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.LayoutDirection
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.screenshot.AndroidXScreenshotTestRule
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TestName
+import org.junit.runner.RunWith
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+class EdgeButtonScreenshotTest {
+    @get:Rule val rule = createComposeRule()
+
+    @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+
+    @get:Rule val testName = TestName()
+
+    @Test
+    fun edge_button_default() =
+        verifyScreenshot() {
+            Box(Modifier.fillMaxSize(), contentAlignment = Alignment.BottomCenter) {
+                EdgeButton(
+                    onClick = { /* Do something */ },
+                    modifier = Modifier.testTag(TEST_TAG)
+                ) {
+                    BasicText("Text")
+                }
+            }
+        }
+
+    @Test
+    fun edge_button_xsmall() =
+        verifyScreenshot() { BasicEdgeButton(height = ButtonDefaults.EdgeButtonHeightExtraSmall) }
+
+    @Test
+    fun edge_button_small() =
+        verifyScreenshot() { BasicEdgeButton(height = ButtonDefaults.EdgeButtonHeightSmall) }
+
+    @Test
+    fun edge_button_medium() =
+        verifyScreenshot() { BasicEdgeButton(height = ButtonDefaults.EdgeButtonHeightMedium) }
+
+    @Test
+    fun edge_button_large() =
+        verifyScreenshot() { BasicEdgeButton(height = ButtonDefaults.EdgeButtonHeightLarge) }
+
+    @Test
+    fun edge_button_disabled() =
+        verifyScreenshot() {
+            BasicEdgeButton(height = ButtonDefaults.EdgeButtonHeightMedium, enabled = false)
+        }
+
+    private val LONG_TEXT =
+        "Lorem ipsum dolor sit amet, consectetur adipiscing elit, " +
+            "sed do eiusmod tempor incididunt ut labore et dolore."
+
+    @Test
+    fun edge_button_xsmall_long_text() =
+        verifyScreenshot() {
+            BasicEdgeButton(height = ButtonDefaults.EdgeButtonHeightExtraSmall, text = LONG_TEXT)
+        }
+
+    @Test
+    fun edge_button_large_long_text() =
+        verifyScreenshot() {
+            BasicEdgeButton(height = ButtonDefaults.EdgeButtonHeightLarge, text = LONG_TEXT)
+        }
+
+    @Composable
+    private fun BasicEdgeButton(height: Dp, enabled: Boolean = true, text: String = "Text") {
+        Box(Modifier.fillMaxSize()) {
+            EdgeButton(
+                onClick = { /* Do something */ },
+                enabled = enabled,
+                buttonHeight = height,
+                modifier = Modifier.align(Alignment.BottomEnd).testTag(TEST_TAG)
+            ) {
+                BasicText(text)
+            }
+        }
+    }
+
+    private fun verifyScreenshot(
+        layoutDirection: LayoutDirection = LayoutDirection.Ltr,
+        content: @Composable () -> Unit
+    ) {
+        rule.setContentWithTheme {
+            CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
+                Box(
+                    modifier =
+                        Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background)
+                ) {
+                    content()
+                }
+            }
+        }
+
+        rule
+            .onNodeWithTag(TEST_TAG)
+            .captureToImage()
+            .assertAgainstGolden(screenshotRule, testName.methodName)
+    }
+}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconButtonTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconButtonTest.kt
index b2ff8c8..55a0bad 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconButtonTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconButtonTest.kt
@@ -450,7 +450,7 @@
         val status = Status.Disabled
         rule.verifyButtonBorderColor(
             expectedBorderColor = {
-                MaterialTheme.colorScheme.outline.copy(alpha = DisabledBorderAlpha)
+                MaterialTheme.colorScheme.onSurface.copy(alpha = DisabledBorderAlpha)
             },
             content = { modifier: Modifier ->
                 OutlinedIconButton(onClick = {}, modifier = modifier, enabled = status.enabled()) {}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ProgressIndicatorTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ProgressIndicatorTest.kt
index f0f5b16..329c719 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ProgressIndicatorTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ProgressIndicatorTest.kt
@@ -26,6 +26,8 @@
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.semantics.ProgressBarRangeInfo
+import androidx.compose.ui.semantics.progressBarRangeInfo
+import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.test.assertRangeInfoEquals
 import androidx.compose.ui.test.captureToImage
 import androidx.compose.ui.test.junit4.createComposeRule
@@ -49,12 +51,15 @@
     }
 
     @Test
-    fun changes_progress() {
+    fun allows_semantics_to_be_added_correctly() {
         val progress = mutableStateOf(0f)
 
         setContentWithTheme {
             CircularProgressIndicator(
-                modifier = Modifier.testTag(TEST_TAG),
+                modifier =
+                    Modifier.testTag(TEST_TAG).semantics {
+                        progressBarRangeInfo = ProgressBarRangeInfo(progress.value, 0f..1f)
+                    },
                 progress = { progress.value }
             )
         }
@@ -141,38 +146,6 @@
             .assertColorInPercentageRange(Color.Red, 4f..8f)
     }
 
-    @Test
-    fun coerces_highest_out_of_bound_progress() {
-        val progress = mutableStateOf(0f)
-
-        setContentWithTheme {
-            CircularProgressIndicator(
-                modifier = Modifier.testTag(TEST_TAG),
-                progress = { progress.value }
-            )
-        }
-
-        rule.runOnIdle { progress.value = 1.5f }
-
-        rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(1f, 0f..1f))
-    }
-
-    @Test
-    fun coerces_lowest_out_of_bound_progress() {
-        val progress = mutableStateOf(0f)
-
-        setContentWithTheme {
-            CircularProgressIndicator(
-                modifier = Modifier.testTag(TEST_TAG),
-                progress = { progress.value }
-            )
-        }
-
-        rule.runOnIdle { progress.value = -1.5f }
-
-        rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(0f, 0f..1f))
-    }
-
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
     @Test
     fun set_small_progress_value() {
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ScaffoldTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ScaffoldTest.kt
new file mode 100644
index 0000000..a5f4bc9
--- /dev/null
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ScaffoldTest.kt
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.material3
+
+import android.os.Build
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.size
+import androidx.compose.runtime.Composable
+import androidx.compose.testutils.assertContainsColor
+import androidx.compose.testutils.assertDoesNotContainColor
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.captureToImage
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.onNodeWithText
+import androidx.compose.ui.test.performTouchInput
+import androidx.compose.ui.test.swipeUp
+import androidx.compose.ui.unit.dp
+import androidx.test.filters.SdkSuppress
+import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
+import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
+import org.junit.Rule
+import org.junit.Test
+
+class ScaffoldTest {
+    @get:Rule val rule = createComposeRule()
+
+    @Test
+    fun app_scaffold_supports_testtag() {
+        rule.setContentWithTheme { AppScaffold(modifier = Modifier.testTag(TEST_TAG)) {} }
+
+        rule.onNodeWithTag(TEST_TAG).assertExists()
+    }
+
+    @Test
+    fun screen_scaffold_supports_testtag() {
+        rule.setContentWithTheme { ScreenScaffold(modifier = Modifier.testTag(TEST_TAG)) {} }
+
+        rule.onNodeWithTag(TEST_TAG).assertExists()
+    }
+
+    @Test
+    fun app_scaffold_displays_content() {
+        rule.setContentWithTheme {
+            AppScaffold(modifier = Modifier.testTag(TEST_TAG)) { Text(CONTENT_MESSAGE) }
+        }
+
+        rule.onNodeWithText(CONTENT_MESSAGE).assertIsDisplayed()
+    }
+
+    @Test
+    fun screen_scaffold_displays_content() {
+        rule.setContentWithTheme {
+            ScreenScaffold(modifier = Modifier.testTag(TEST_TAG)) { Text(CONTENT_MESSAGE) }
+        }
+
+        rule.onNodeWithText(CONTENT_MESSAGE).assertIsDisplayed()
+    }
+
+    @Test
+    fun displays_app_time_text_by_default() {
+        rule.setContentWithTheme {
+            AppScaffold(timeText = { Text(TIME_TEXT_MESSAGE) }) { ScreenScaffold {} }
+        }
+
+        rule.onNodeWithText(TIME_TEXT_MESSAGE).assertIsDisplayed()
+    }
+
+    @Test
+    fun displays_screen_time_text_when_provided() {
+        rule.setContentWithTheme {
+            AppScaffold(timeText = { Text("App Time Text") }) {
+                ScreenScaffold(timeText = { Text(TIME_TEXT_MESSAGE) }) {}
+            }
+        }
+
+        rule.onNodeWithText(TIME_TEXT_MESSAGE).assertIsDisplayed()
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    @Test
+    fun displays_scroll_indicator_initially_when_scrollable() {
+        val scrollIndicatorColor = Color.Red
+
+        rule.setContentWithTheme {
+            TestScreenScaffold(
+                scrollIndicatorColor = scrollIndicatorColor,
+                timeTextColor = Color.Blue
+            )
+        }
+
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(scrollIndicatorColor)
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    @Test
+    fun hides_scroll_indicator_after_delay() {
+        val scrollIndicatorColor = Color.Red
+
+        rule.setContentWithTheme {
+            TestScreenScaffold(
+                scrollIndicatorColor = scrollIndicatorColor,
+                timeTextColor = Color.Blue
+            )
+        }
+
+        // After a 2500 delay, the scroll indicator is animated away. Allow a little longer for the
+        // animation to complete.
+        rule.mainClock.autoAdvance = false
+        rule.mainClock.advanceTimeBy(4000)
+
+        rule
+            .onNodeWithTag(TEST_TAG)
+            .captureToImage()
+            .assertDoesNotContainColor(scrollIndicatorColor)
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    @Test
+    fun shows_time_text_after_delay() {
+        val timeTextColor = Color.Red
+
+        rule.setContentWithTheme {
+            TestScreenScaffold(scrollIndicatorColor = Color.Blue, timeTextColor = timeTextColor)
+        }
+
+        rule.onNodeWithTag(SCROLL_TAG).performTouchInput { swipeUp() }
+
+        // After a 2500 delay, the time text is animated back in. Allow a little longer for the
+        // animation to complete.
+        rule.mainClock.autoAdvance = false
+        rule.mainClock.advanceTimeBy(4000)
+
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(timeTextColor)
+    }
+
+    @Composable
+    private fun TestScreenScaffold(scrollIndicatorColor: Color, timeTextColor: Color) {
+        AppScaffold {
+            val scrollState = rememberScalingLazyListState()
+            ScreenScaffold(
+                modifier = Modifier.testTag(TEST_TAG),
+                scrollState = scrollState,
+                scrollIndicator = {
+                    Box(
+                        modifier =
+                            Modifier.size(20.dp)
+                                .align(Alignment.CenterEnd)
+                                .background(scrollIndicatorColor)
+                    )
+                },
+                timeText = { Box(Modifier.size(20.dp).background(timeTextColor)) }
+            ) {
+                ScalingLazyColumn(
+                    state = scrollState,
+                    modifier = Modifier.fillMaxSize().background(Color.Black).testTag(SCROLL_TAG)
+                ) {
+                    items(10) {
+                        Button(
+                            onClick = {},
+                            label = { Text("Item ${it + 1}") },
+                        )
+                    }
+                }
+            }
+        }
+    }
+}
+
+private const val CONTENT_MESSAGE = "The Content"
+private const val TIME_TEXT_MESSAGE = "The Time Text"
+private const val SCROLL_TAG = "ScrollTag"
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ScrollAwayTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ScrollAwayTest.kt
new file mode 100644
index 0000000..5dfc424
--- /dev/null
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ScrollAwayTest.kt
@@ -0,0 +1,289 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.material3
+
+import android.os.Build
+import androidx.annotation.RequiresApi
+import androidx.compose.foundation.ScrollState
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyListState
+import androidx.compose.foundation.lazy.rememberLazyListState
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.runtime.Composable
+import androidx.compose.testutils.WithTouchSlop
+import androidx.compose.testutils.assertContainsColor
+import androidx.compose.testutils.assertDoesNotContainColor
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.captureToImage
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.performTouchInput
+import androidx.compose.ui.test.swipeUp
+import androidx.compose.ui.unit.dp
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import androidx.wear.compose.foundation.lazy.AutoCenteringParams
+import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
+import androidx.wear.compose.foundation.lazy.ScalingLazyListState
+import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
+import androidx.wear.compose.foundation.toScrollAwayInfoProvider
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+class ScrollAwayTest {
+    @get:Rule val rule = createComposeRule()
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun showsTimeTextWithScalingLazyColumnInitially() {
+        val timeTextColor = Color.Red
+
+        rule.setContentWithTheme {
+            val scrollState = rememberScalingLazyListState()
+            ScalingLazyColumnTest(scrollState, timeTextColor)
+        }
+
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(timeTextColor)
+    }
+
+    @Test
+    fun showsTimeTextWithScalingLazyColumnIfItemIndexInvalid() {
+        val timeTextColor = Color.Red
+        lateinit var scrollState: ScalingLazyListState
+        rule.setContentWithTheme {
+            scrollState =
+                rememberScalingLazyListState(
+                    initialCenterItemIndex = 1,
+                    initialCenterItemScrollOffset = 0
+                )
+            ScalingLazyColumnTest(scrollState, itemIndex = 100, timeTextColor = timeTextColor)
+        }
+
+        rule.onNodeWithTag(SCROLL_TAG).performTouchInput { swipeUp() }
+
+        rule.onNodeWithTag(TIME_TEXT_TAG).assertIsDisplayed()
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun showsTimeTextWithLazyColumnInitially() {
+        val timeTextColor = Color.Red
+
+        rule.setContentWithTheme {
+            val scrollState = rememberLazyListState()
+            LazyColumnTest(scrollState, timeTextColor)
+        }
+
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(timeTextColor)
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun showsTimeTextWithColumnInitially() {
+        val timeTextColor = Color.Red
+
+        rule.setContentWithTheme {
+            val scrollState = rememberLazyListState()
+            LazyColumnTest(scrollState, timeTextColor)
+        }
+
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(timeTextColor)
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun hidesTimeTextAfterScrollingScalingLazyColumn() {
+        val timeTextColor = Color.Red
+        rule.setContentWithTheme {
+            val scrollState = rememberScalingLazyListState()
+            ScalingLazyColumnTest(scrollState, timeTextColor = timeTextColor)
+        }
+
+        rule.onNodeWithTag(SCROLL_TAG).performTouchInput { swipeUp() }
+
+        // Allow slight delay for TimeText to scroll off, but not long enough for it to come
+        // back onto the screen after the idle timeout.
+        rule.mainClock.autoAdvance = false
+        rule.mainClock.advanceTimeBy(500)
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertDoesNotContainColor(timeTextColor)
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun hidesTimeTextWithLazyColumn() {
+        val timeTextColor = Color.Red
+        lateinit var scrollState: LazyListState
+        rule.setContentWithTheme {
+            scrollState =
+                rememberLazyListState(
+                    initialFirstVisibleItemIndex = 1,
+                )
+
+            LazyColumnTest(scrollState, timeTextColor = timeTextColor)
+        }
+
+        rule.onNodeWithTag(SCROLL_TAG).performTouchInput { swipeUp() }
+
+        // Allow slight delay for TimeText to scroll off, but not long enough for it to come
+        // back onto the screen after the idle timeout.
+        rule.mainClock.autoAdvance = false
+        rule.mainClock.advanceTimeBy(500)
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertDoesNotContainColor(timeTextColor)
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun hidesTimeTextWithColumn() {
+        val timeTextColor = Color.Red
+        lateinit var scrollState: ScrollState
+        rule.setContentWithTheme {
+            scrollState = rememberScrollState()
+
+            ColumnTest(scrollState, timeTextColor = timeTextColor)
+        }
+
+        rule.onNodeWithTag(SCROLL_TAG).performTouchInput { swipeUp() }
+
+        // Allow slight delay for TimeText to scroll off, but not long enough for it to come
+        // back onto the screen after the idle timeout.
+        rule.mainClock.autoAdvance = false
+        rule.mainClock.advanceTimeBy(500)
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertDoesNotContainColor(timeTextColor)
+    }
+
+    @Composable
+    private fun ScalingLazyColumnTest(
+        scrollState: ScalingLazyListState,
+        timeTextColor: Color,
+        itemIndex: Int = 1
+    ) {
+        WithTouchSlop(0f) {
+            Box(modifier = Modifier.fillMaxSize().testTag(TEST_TAG)) {
+                ScalingLazyColumn(
+                    state = scrollState,
+                    autoCentering = AutoCenteringParams(itemIndex = itemIndex),
+                    modifier = Modifier.fillMaxSize().testTag(SCROLL_TAG)
+                ) {
+                    item { ListHeader { Text("Buttons") } }
+
+                    items(10) { i -> TestButton(i, Modifier.fillParentMaxHeight(0.5f)) }
+                }
+                TimeText(
+                    modifier =
+                        Modifier.scrollAway(
+                                scrollInfoProvider = scrollState.toScrollAwayInfoProvider(),
+                                screenStage = {
+                                    if (scrollState.isScrollInProgress) ScreenStage.Scrolling
+                                    else ScreenStage.Idle
+                                }
+                            )
+                            .testTag(TIME_TEXT_TAG),
+                ) {
+                    composable { Box(Modifier.size(20.dp).background(timeTextColor)) }
+                }
+            }
+        }
+    }
+
+    @Composable
+    private fun LazyColumnTest(scrollState: LazyListState, timeTextColor: Color) {
+        WithTouchSlop(0f) {
+            Box(
+                modifier =
+                    Modifier.fillMaxSize()
+                        .background(MaterialTheme.colorScheme.background)
+                        .testTag(TEST_TAG)
+            ) {
+                TimeText(
+                    modifier =
+                        Modifier.scrollAway(
+                                scrollInfoProvider = scrollState.toScrollAwayInfoProvider(),
+                                screenStage = {
+                                    if (scrollState.isScrollInProgress) ScreenStage.Scrolling
+                                    else ScreenStage.Idle
+                                }
+                            )
+                            .testTag(TIME_TEXT_TAG)
+                ) {
+                    composable { Box(Modifier.size(20.dp).background(timeTextColor)) }
+                }
+                LazyColumn(state = scrollState, modifier = Modifier.testTag(SCROLL_TAG)) {
+                    item { ListHeader { Text("Buttons") } }
+                    items(5) { i -> TestButton(i, Modifier.fillParentMaxHeight(0.5f)) }
+                }
+            }
+        }
+    }
+
+    @Composable
+    private fun ColumnTest(scrollState: ScrollState, timeTextColor: Color) {
+        WithTouchSlop(0f) {
+            Box(
+                modifier =
+                    Modifier.fillMaxSize()
+                        .background(MaterialTheme.colorScheme.background)
+                        .testTag(TEST_TAG)
+            ) {
+                TimeText(
+                    contentColor = timeTextColor,
+                    modifier =
+                        Modifier.scrollAway(
+                                scrollInfoProvider = scrollState.toScrollAwayInfoProvider(),
+                                screenStage = {
+                                    if (scrollState.isScrollInProgress) ScreenStage.Scrolling
+                                    else ScreenStage.Idle
+                                }
+                            )
+                            .testTag(TIME_TEXT_TAG)
+                ) {
+                    composable { Box(Modifier.size(20.dp).background(timeTextColor)) }
+                }
+                Column(modifier = Modifier.verticalScroll(scrollState).testTag(SCROLL_TAG)) {
+                    ListHeader { Text("Buttons") }
+                    repeat(20) { i -> TestButton(i) }
+                }
+            }
+        }
+    }
+
+    @Composable
+    private fun TestButton(i: Int, modifier: Modifier = Modifier) {
+        Button(
+            modifier = modifier.fillMaxWidth().padding(horizontal = 36.dp),
+            onClick = {},
+        ) {
+            Text(text = "Button $i")
+        }
+    }
+}
+
+private const val SCROLL_TAG = "ScrollTag"
+private const val TIME_TEXT_TAG = "TimeTextTag"
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SwitchButtonTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SwitchButtonTest.kt
new file mode 100644
index 0000000..aa70256
--- /dev/null
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SwitchButtonTest.kt
@@ -0,0 +1,854 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.material3
+
+import android.os.Build
+import androidx.annotation.RequiresApi
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.foundation.layout.RowScope
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.testutils.assertContainsColor
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.compositeOver
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.semantics.Role
+import androidx.compose.ui.semantics.SemanticsProperties
+import androidx.compose.ui.semantics.role
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.test.SemanticsMatcher
+import androidx.compose.ui.test.assert
+import androidx.compose.ui.test.assertHasClickAction
+import androidx.compose.ui.test.assertHeightIsAtLeast
+import androidx.compose.ui.test.assertIsEnabled
+import androidx.compose.ui.test.assertIsNotEnabled
+import androidx.compose.ui.test.assertIsOff
+import androidx.compose.ui.test.assertIsOn
+import androidx.compose.ui.test.captureToImage
+import androidx.compose.ui.test.isToggleable
+import androidx.compose.ui.test.junit4.ComposeContentTestRule
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onChildAt
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.onNodeWithText
+import androidx.compose.ui.test.performClick
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import androidx.wear.compose.material3.samples.SplitSwitchButtonSample
+import androidx.wear.compose.material3.samples.SwitchButtonSample
+import org.junit.Assert
+import org.junit.Rule
+import org.junit.Test
+
+class SwitchButtonTest {
+    @get:Rule val rule = createComposeRule()
+
+    @Test
+    fun supports_testtag() {
+        rule.setContentWithTheme { SwitchButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG)) }
+
+        rule.onNodeWithTag(TEST_TAG).assertExists()
+    }
+
+    @Test
+    fun split_button_supports_testtag() {
+        rule.setContentWithTheme {
+            SplitSwitchButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG))
+        }
+
+        rule.onNodeWithTag(TEST_TAG).assertExists()
+    }
+
+    @Test
+    fun switch_button_samples_build() {
+        rule.setContentWithTheme { SwitchButtonSample() }
+    }
+
+    @Test
+    fun split_switch_button_samples_build() {
+        rule.setContentWithTheme { SplitSwitchButtonSample() }
+    }
+
+    @Test
+    fun has_clickaction_when_enabled() {
+        rule.setContentWithTheme {
+            SwitchButtonWithDefaults(enabled = true, modifier = Modifier.testTag(TEST_TAG))
+        }
+
+        rule.onNodeWithTag(TEST_TAG).assertHasClickAction()
+    }
+
+    @Test
+    fun split_button_has_clickaction_when_enabled() {
+        rule.setContentWithTheme {
+            SplitSwitchButtonWithDefaults(enabled = true, modifier = Modifier.testTag(TEST_TAG))
+        }
+
+        rule.onNodeWithTag(TEST_TAG).onChildAt(0).assertHasClickAction()
+    }
+
+    @Test
+    fun has_clickaction_when_disabled() {
+        rule.setContentWithTheme {
+            SwitchButtonWithDefaults(enabled = false, modifier = Modifier.testTag(TEST_TAG))
+        }
+
+        rule.onNodeWithTag(TEST_TAG).assertHasClickAction()
+    }
+
+    @Test
+    fun split_button_has_clickaction_when_disabled() {
+        rule.setContentWithTheme {
+            SplitSwitchButtonWithDefaults(enabled = false, modifier = Modifier.testTag(TEST_TAG))
+        }
+
+        rule.onNodeWithTag(TEST_TAG).onChildAt(0).assertHasClickAction()
+    }
+
+    @Test
+    fun is_toggleable() {
+        rule.setContentWithTheme { SwitchButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG)) }
+
+        rule.onNode(isToggleable()).assertExists()
+    }
+
+    @Test
+    fun split_button_is_toggleable() {
+        rule.setContentWithTheme {
+            SplitSwitchButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG))
+        }
+
+        rule.onNode(isToggleable()).assertExists()
+    }
+
+    @Test
+    fun split_button_is_clickable() {
+        rule.setContentWithTheme {
+            SplitSwitchButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG))
+        }
+        rule.onNodeWithTag(TEST_TAG).onChildAt(0).assertHasClickAction()
+    }
+
+    @Test
+    fun is_correctly_enabled() {
+        rule.setContentWithTheme {
+            SwitchButtonWithDefaults(enabled = true, modifier = Modifier.testTag(TEST_TAG))
+        }
+
+        rule.onNodeWithTag(TEST_TAG).assertIsEnabled()
+    }
+
+    @Test
+    fun split_button_is_correctly_enabled() {
+        rule.setContentWithTheme {
+            SplitSwitchButtonWithDefaults(enabled = true, modifier = Modifier.testTag(TEST_TAG))
+        }
+
+        rule.onNodeWithTag(TEST_TAG).assertIsEnabled()
+    }
+
+    @Test
+    fun is_correctly_disabled() {
+        rule.setContentWithTheme {
+            SwitchButtonWithDefaults(enabled = false, modifier = Modifier.testTag(TEST_TAG))
+        }
+
+        rule.onNodeWithTag(TEST_TAG).assertIsNotEnabled()
+    }
+
+    @Test
+    fun split_button_is_correctly_disabled() {
+        rule.setContentWithTheme {
+            SplitSwitchButtonWithDefaults(enabled = false, modifier = Modifier.testTag(TEST_TAG))
+        }
+
+        rule.onNodeWithTag(TEST_TAG).onChildAt(0).assertIsNotEnabled()
+    }
+
+    @Test
+    fun is_on_when_checked() {
+        rule.setContentWithTheme {
+            SwitchButtonWithDefaults(checked = true, modifier = Modifier.testTag(TEST_TAG))
+        }
+
+        rule.onNodeWithTag(TEST_TAG).assertIsOn()
+    }
+
+    @Test
+    fun split_button_is_on_when_checked() {
+        rule.setContentWithTheme {
+            SplitSwitchButtonWithDefaults(checked = true, modifier = Modifier.testTag(TEST_TAG))
+        }
+
+        rule.onNodeWithTag(TEST_TAG).onChildAt(1).assertIsOn()
+    }
+
+    @Test
+    fun is_off_when_unchecked() {
+        rule.setContentWithTheme {
+            SwitchButtonWithDefaults(checked = false, modifier = Modifier.testTag(TEST_TAG))
+        }
+
+        rule.onNodeWithTag(TEST_TAG).assertIsOff()
+    }
+
+    @Test
+    fun split_button_is_off_when_unchecked() {
+        rule.setContentWithTheme {
+            SplitSwitchButtonWithDefaults(checked = false, modifier = Modifier.testTag(TEST_TAG))
+        }
+
+        rule.onNodeWithTag(TEST_TAG).onChildAt(1).assertIsOff()
+    }
+
+    @Test
+    fun responds_to_toggle_on() {
+        rule.setContentWithTheme {
+            val (checked, onCheckedChange) = remember { mutableStateOf(false) }
+            SwitchButtonWithDefaults(
+                checked = checked,
+                onCheckedChange = onCheckedChange,
+                enabled = true,
+                modifier = Modifier.testTag(TEST_TAG)
+            )
+        }
+
+        rule.onNodeWithTag(TEST_TAG).assertIsOff().performClick().assertIsOn()
+    }
+
+    @Test
+    fun split_button_responds_to_toggle_on() {
+        rule.setContentWithTheme {
+            val (checked, onCheckedChange) = remember { mutableStateOf(false) }
+            SplitSwitchButtonWithDefaults(
+                checked = checked,
+                onCheckedChange = onCheckedChange,
+                enabled = true,
+                modifier = Modifier.testTag(TEST_TAG)
+            )
+        }
+
+        rule.onNodeWithTag(TEST_TAG).onChildAt(1).assertIsOff().performClick().assertIsOn()
+    }
+
+    @Test
+    fun responds_to_toggle_off() {
+        rule.setContentWithTheme {
+            val (checked, onCheckedChange) = remember { mutableStateOf(true) }
+            SwitchButtonWithDefaults(
+                checked = checked,
+                onCheckedChange = onCheckedChange,
+                enabled = true,
+                modifier = Modifier.testTag(TEST_TAG)
+            )
+        }
+
+        rule.onNodeWithTag(TEST_TAG).assertIsOn().performClick().assertIsOff()
+    }
+
+    @Test
+    fun split_button_responds_to_toggle_off() {
+        rule.setContentWithTheme {
+            val (checked, onCheckedChange) = remember { mutableStateOf(true) }
+            SplitSwitchButtonWithDefaults(
+                checked = checked,
+                onCheckedChange = onCheckedChange,
+                enabled = true,
+                modifier = Modifier.testTag(TEST_TAG)
+            )
+        }
+
+        rule.onNodeWithTag(TEST_TAG).onChildAt(1).assertIsOn().performClick().assertIsOff()
+    }
+
+    @Test
+    fun does_not_toggle_when_disabled() {
+        rule.setContentWithTheme {
+            val (checked, onCheckedChange) = remember { mutableStateOf(false) }
+            SwitchButtonWithDefaults(
+                checked = checked,
+                onCheckedChange = onCheckedChange,
+                enabled = false,
+                modifier = Modifier.testTag(TEST_TAG)
+            )
+        }
+
+        rule.onNodeWithTag(TEST_TAG).assertIsOff().performClick().assertIsOff()
+    }
+
+    @Test
+    fun split_button_does_not_toggle_when_disabled() {
+        rule.setContentWithTheme {
+            val (checked, onCheckedChange) = remember { mutableStateOf(false) }
+            SplitSwitchButtonWithDefaults(
+                checked = checked,
+                onCheckedChange = onCheckedChange,
+                enabled = false,
+                modifier = Modifier.testTag(TEST_TAG)
+            )
+        }
+
+        rule.onNodeWithTag(TEST_TAG).onChildAt(1).assertIsOff().performClick().assertIsOff()
+    }
+
+    @Test
+    fun can_override_role() {
+        rule.setContentWithTheme {
+            SwitchButtonWithDefaults(
+                modifier = Modifier.testTag(TEST_TAG).semantics { role = Role.Button }
+            )
+        }
+
+        rule
+            .onNodeWithTag(TEST_TAG)
+            .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Button))
+    }
+
+    @Test
+    fun split_button_clickable_has_role_button() {
+        rule.setContentWithTheme {
+            SplitSwitchButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG))
+        }
+
+        // NB The Switch provides its own role,
+        // but the main clickable section is a Button.
+        rule
+            .onNodeWithTag(TEST_TAG)
+            .onChildAt(0)
+            .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Button))
+    }
+
+    @Test
+    fun displays_label_content() {
+        val textContent = "abc"
+
+        rule.setContentWithTheme {
+            SwitchButtonWithDefaults(
+                checked = true,
+                onCheckedChange = {},
+                label = { Text(text = textContent) }
+            )
+        }
+
+        rule.onNodeWithText(textContent).assertExists()
+    }
+
+    @Test
+    fun split_button_displays_label_content() {
+        val textContent = "abc"
+
+        rule.setContentWithTheme {
+            SplitSwitchButtonWithDefaults(
+                checked = true,
+                onCheckedChange = {},
+                label = { Text(text = textContent) }
+            )
+        }
+
+        rule.onNodeWithText(textContent).assertExists()
+    }
+
+    @Test
+    fun switch_button_hasAdjustableHeight() {
+        val minHeight: Dp = 53.dp
+
+        rule
+            .setContentWithThemeForSizeAssertions {
+                SwitchButtonWithDefaults(
+                    label = {
+                        Text(
+                            text =
+                                "SwitchButton text spanning over multiple lines of text " +
+                                    "to test height is adjustable. This should exceed the minimum " +
+                                    "height for the SwitchButton."
+                        )
+                    },
+                    secondaryLabel = { Text(text = "Secondary label with text.") }
+                )
+            }
+            .assertHeightIsAtLeast(minHeight)
+    }
+
+    @Test
+    fun split_switch_button_hasAdjustableHeight() {
+        val minHeight: Dp = 53.dp
+
+        rule
+            .setContentWithThemeForSizeAssertions {
+                SplitSwitchButtonWithDefaults(
+                    label = { Text(text = "Primary label with 3 lines of text.") },
+                    secondaryLabel = {
+                        Text(
+                            text =
+                                "SplitSwitchButton text spanning over multiple lines of text " +
+                                    "to test height is adjustable. This should exceed the " +
+                                    "minimum height for the SplitSwitchButton."
+                        )
+                    }
+                )
+            }
+            .assertHeightIsAtLeast(minHeight)
+    }
+
+    @Test
+    fun switch_button_height_defaults_52dp() {
+        rule
+            .setContentWithThemeForSizeAssertions {
+                SwitchButtonWithDefaults(secondaryLabel = { Text("Secondary label") })
+            }
+            .assertHeightIsEqualTo(52.dp)
+    }
+
+    @Test
+    fun split_switch_button_height_defaults_52dp() {
+        rule
+            .setContentWithThemeForSizeAssertions { SplitSwitchButtonWithDefaults() }
+            .assertHeightIsEqualTo(52.dp)
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun switch_button_allows_checked_background_color_override() =
+        verifySwitchButtonBackgroundColor(
+            checked = true,
+            enabled = true,
+            expectedColor = CHECKED_COLOR
+        )
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun switch_button_allows_unchecked_background_color_override() =
+        verifySwitchButtonBackgroundColor(
+            checked = false,
+            enabled = true,
+            expectedColor = UNCHECKED_COLOR
+        )
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun split_switch_button_allows_checked_background_color_override() =
+        verifySplitSwitchButtonBackgroundColor(
+            checked = true,
+            enabled = true,
+            expectedColor = CHECKED_COLOR
+        )
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun split_switch_button_allows_unchecked_background_color_override() =
+        verifySplitSwitchButtonBackgroundColor(
+            checked = false,
+            enabled = true,
+            expectedColor = UNCHECKED_COLOR
+        )
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun verify_switch_button_colors_enabled_and_checked() {
+        rule.verifySwitchButtonColors(checked = true, enabled = true)
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun verify_switch_button_colors_enabled_and_unchecked() {
+        rule.verifySwitchButtonColors(checked = false, enabled = true)
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun verify_switch_button_colors_disabled_and_checked() {
+        rule.verifySwitchButtonColors(checked = true, enabled = false)
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun verify_switch_button_colors_disabled_and_unchecked() {
+        rule.verifySwitchButtonColors(checked = false, enabled = false)
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun verify_split_switch_button_colors_enabled_and_checked() {
+        rule.verifySplitToggleButtonColors(checked = true, enabled = true)
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun verify_split_switch_button_colors_enabled_and_unchecked() {
+        rule.verifySplitToggleButtonColors(checked = false, enabled = true)
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun verify_split_switch_button_colors_disabled_and_checked() {
+        rule.verifySplitToggleButtonColors(checked = true, enabled = false)
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun verify_split_toggle_button_colors_disabled_and_unchecked() {
+        rule.verifySplitToggleButtonColors(checked = false, enabled = false)
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun switch_checked_colors_are_customisable() {
+        val thumbColor = Color.Green
+        val thumbIconColor = Color.Yellow
+        val trackColor = Color.Blue
+        val trackBorderColor = Color.Red
+        rule.setContentWithTheme {
+            SwitchButtonWithDefaults(
+                enabled = true,
+                checked = true,
+                colors =
+                    SwitchButtonDefaults.switchButtonColors(
+                        checkedThumbColor = thumbColor,
+                        checkedThumbIconColor = thumbIconColor,
+                        checkedTrackColor = trackColor,
+                        checkedTrackBorderColor = trackBorderColor
+                    ),
+                modifier = Modifier.testTag(TEST_TAG)
+            )
+        }
+
+        val image = rule.onNodeWithTag(TEST_TAG).captureToImage()
+        image.assertContainsColor(thumbColor)
+        image.assertContainsColor(thumbIconColor)
+        image.assertContainsColor(trackColor)
+        image.assertContainsColor(trackBorderColor)
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun switch_unchecked_colors_are_customisable() {
+        val thumbColor = Color.Green
+        val trackColor = Color.Blue
+        val trackBorderColor = Color.Red
+        rule.setContentWithTheme {
+            // NB thumb icon is erased during animation, so unchecked thumb icon color
+            // is not tested here.
+            SwitchButtonWithDefaults(
+                enabled = true,
+                checked = false,
+                colors =
+                    SwitchButtonDefaults.switchButtonColors(
+                        uncheckedThumbColor = thumbColor,
+                        uncheckedTrackColor = trackColor,
+                        uncheckedTrackBorderColor = trackBorderColor
+                    ),
+                modifier = Modifier.testTag(TEST_TAG)
+            )
+        }
+
+        val image = rule.onNodeWithTag(TEST_TAG).captureToImage()
+        image.assertContainsColor(thumbColor)
+        image.assertContainsColor(trackColor)
+        image.assertContainsColor(trackBorderColor)
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun disabled_switch_checked_colors_are_customisable() {
+        val thumbColor = Color.Green
+        val thumbIconColor = Color.Yellow
+        val trackColor = Color.Blue
+        val trackBorderColor = Color.Red
+        rule.setContentWithTheme {
+            SwitchButtonWithDefaults(
+                enabled = false,
+                checked = true,
+                colors =
+                    SwitchButtonDefaults.switchButtonColors(
+                        disabledCheckedThumbColor = thumbColor,
+                        disabledCheckedThumbIconColor = thumbIconColor,
+                        disabledCheckedTrackColor = trackColor,
+                        disabledCheckedTrackBorderColor = trackBorderColor
+                    ),
+                modifier = Modifier.testTag(TEST_TAG)
+            )
+        }
+
+        val image = rule.onNodeWithTag(TEST_TAG).captureToImage()
+        image.assertContainsColor(thumbColor)
+        image.assertContainsColor(thumbIconColor)
+        image.assertContainsColor(trackColor)
+        image.assertContainsColor(trackBorderColor)
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun disabled_switch_unchecked_colors_are_customisable() {
+        val thumbColor = Color.Green
+        val trackBorderColor = Color.Red
+        rule.setContentWithTheme {
+            // NB thumb icon and track are omitted for unchecked + disabled
+            // so are not tested here.
+            SwitchButtonWithDefaults(
+                enabled = false,
+                checked = false,
+                colors =
+                    SwitchButtonDefaults.switchButtonColors(
+                        disabledUncheckedThumbColor = thumbColor,
+                        disabledUncheckedTrackBorderColor = trackBorderColor
+                    ),
+                modifier = Modifier.testTag(TEST_TAG)
+            )
+        }
+
+        val image = rule.onNodeWithTag(TEST_TAG).captureToImage()
+        image.assertContainsColor(thumbColor)
+        image.assertContainsColor(trackBorderColor)
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    private fun verifySwitchButtonBackgroundColor(
+        checked: Boolean,
+        enabled: Boolean,
+        expectedColor: Color
+    ) {
+        rule.setContentWithTheme {
+            SwitchButtonWithDefaults(
+                checked = checked,
+                colors =
+                    SwitchButtonDefaults.switchButtonColors(
+                        checkedContainerColor = CHECKED_COLOR,
+                        uncheckedContainerColor = UNCHECKED_COLOR
+                    ),
+                onCheckedChange = {},
+                enabled = enabled,
+                modifier = Modifier.testTag(TEST_TAG),
+            )
+        }
+
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(expectedColor)
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
+    private fun verifySplitSwitchButtonBackgroundColor(
+        checked: Boolean,
+        enabled: Boolean,
+        expectedColor: Color
+    ) {
+        rule.setContentWithTheme {
+            SplitSwitchButtonWithDefaults(
+                checked = checked,
+                colors =
+                    SwitchButtonDefaults.splitSwitchButtonColors(
+                        checkedContainerColor = CHECKED_COLOR,
+                        uncheckedContainerColor = UNCHECKED_COLOR
+                    ),
+                onCheckedChange = {},
+                enabled = enabled,
+                modifier = Modifier.testTag(TEST_TAG),
+            )
+        }
+
+        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(expectedColor)
+    }
+}
+
+@Composable
+private fun SwitchButtonWithDefaults(
+    modifier: Modifier = Modifier,
+    checked: Boolean = true,
+    enabled: Boolean = true,
+    colors: SwitchButtonColors = SwitchButtonDefaults.switchButtonColors(),
+    onCheckedChange: (Boolean) -> Unit = {},
+    label: @Composable RowScope.() -> Unit = { Text("Primary") },
+    secondaryLabel: @Composable (RowScope.() -> Unit)? = null,
+    icon: @Composable (BoxScope.() -> Unit)? = null,
+) =
+    SwitchButton(
+        modifier = modifier,
+        checked = checked,
+        enabled = enabled,
+        colors = colors,
+        onCheckedChange = onCheckedChange,
+        label = label,
+        secondaryLabel = secondaryLabel,
+        icon = icon,
+    )
+
+@Composable
+private fun SplitSwitchButtonWithDefaults(
+    modifier: Modifier = Modifier,
+    checked: Boolean = true,
+    enabled: Boolean = true,
+    colors: SplitSwitchButtonColors = SwitchButtonDefaults.splitSwitchButtonColors(),
+    onCheckedChange: (Boolean) -> Unit = {},
+    onClick: () -> Unit = {},
+    label: @Composable RowScope.() -> Unit = { Text("Primary") },
+    secondaryLabel: @Composable (RowScope.() -> Unit)? = null,
+) =
+    SplitSwitchButton(
+        modifier = modifier,
+        colors = colors,
+        checked = checked,
+        enabled = enabled,
+        onCheckedChange = onCheckedChange,
+        label = label,
+        secondaryLabel = secondaryLabel,
+        onContainerClick = onClick,
+        toggleContentDescription = "description",
+    )
+
+@RequiresApi(Build.VERSION_CODES.O)
+private fun ComposeContentTestRule.verifySwitchButtonColors(enabled: Boolean, checked: Boolean) {
+    val testBackgroundColor = Color.White
+    var expectedContainerColor = Color.Transparent
+    var expectedLabelColor = Color.Transparent
+    var expectedIconColor = Color.Transparent
+    var expectedSecondaryLabelColor = Color.Transparent
+    var actualLabelColor = Color.Transparent
+    var actualIconColor = Color.Transparent
+    var actualSecondaryLabelColor = Color.Transparent
+    setContentWithTheme {
+        expectedContainerColor =
+            switch_button_container_color(checked, enabled).compositeOver(testBackgroundColor)
+        expectedLabelColor = switch_button_content_color(checked, enabled)
+        expectedSecondaryLabelColor = switch_button_secondary_label_color(checked, enabled)
+        expectedIconColor = switch_button_icon_color(enabled)
+        Box(Modifier.fillMaxSize().background(testBackgroundColor)) {
+            SwitchButton(
+                modifier = Modifier.testTag(TEST_TAG),
+                checked = checked,
+                onCheckedChange = {},
+                enabled = enabled,
+                label = { actualLabelColor = LocalContentColor.current },
+                secondaryLabel = { actualSecondaryLabelColor = LocalContentColor.current },
+                icon = { actualIconColor = LocalContentColor.current }
+            )
+        }
+    }
+    Assert.assertEquals(expectedLabelColor, actualLabelColor)
+    Assert.assertEquals(expectedSecondaryLabelColor, actualSecondaryLabelColor)
+    Assert.assertEquals(expectedIconColor, actualIconColor)
+
+    onNodeWithTag(TEST_TAG)
+        .captureToImage()
+        .assertContainsColor(
+            if (expectedContainerColor != Color.Transparent) expectedContainerColor
+            else testBackgroundColor,
+        )
+}
+
+@RequiresApi(Build.VERSION_CODES.O)
+private fun ComposeContentTestRule.verifySplitToggleButtonColors(
+    enabled: Boolean,
+    checked: Boolean
+) {
+    val testBackgroundColor = Color.White
+    var expectedContainerColor = Color.Transparent
+    var expectedLabelColor = Color.Transparent
+    var expectedSecondaryLabelColor = Color.Transparent
+    var actualLabelColor = Color.Transparent
+    var actualSecondaryLabelColor = Color.Transparent
+    setContentWithTheme {
+        expectedContainerColor =
+            split_switch_button_container_color(checked)
+                .withDisabledAlphaApplied(enabled = enabled)
+                .compositeOver(testBackgroundColor)
+        expectedLabelColor =
+            split_switch_button_content_color(checked).withDisabledAlphaApplied(enabled = enabled)
+        expectedSecondaryLabelColor =
+            split_switch_button_secondary_label_color(checked)
+                .withDisabledAlphaApplied(enabled = enabled)
+        Box(Modifier.fillMaxSize().background(testBackgroundColor)) {
+            SplitSwitchButton(
+                modifier = Modifier.testTag(TEST_TAG),
+                checked = checked,
+                onCheckedChange = {},
+                onContainerClick = {},
+                toggleContentDescription = "description",
+                enabled = enabled,
+                label = { actualLabelColor = LocalContentColor.current },
+                secondaryLabel = { actualSecondaryLabelColor = LocalContentColor.current },
+            )
+        }
+    }
+    Assert.assertEquals(expectedLabelColor, actualLabelColor)
+    Assert.assertEquals(expectedSecondaryLabelColor, actualSecondaryLabelColor)
+
+    onNodeWithTag(TEST_TAG)
+        .captureToImage()
+        .assertContainsColor(
+            if (expectedContainerColor != Color.Transparent) expectedContainerColor
+            else testBackgroundColor,
+        )
+}
+
+@Composable
+private fun switch_button_container_color(
+    checked: Boolean,
+    enabled: Boolean,
+): Color {
+    return if (checked && enabled) MaterialTheme.colorScheme.primaryContainer
+    else if (!checked && enabled) MaterialTheme.colorScheme.surfaceContainer
+    else MaterialTheme.colorScheme.onSurface.toDisabledColor(disabledAlpha = 0.12f)
+}
+
+@Composable
+private fun switch_button_content_color(checked: Boolean, enabled: Boolean): Color {
+    return if (checked && enabled) MaterialTheme.colorScheme.onPrimaryContainer
+    else if (!checked && enabled) MaterialTheme.colorScheme.onSurface
+    else MaterialTheme.colorScheme.onSurface.toDisabledColor(disabledAlpha = 0.38f)
+}
+
+@Composable
+private fun switch_button_secondary_label_color(checked: Boolean, enabled: Boolean): Color {
+    return if (checked && enabled) MaterialTheme.colorScheme.onPrimaryContainer.copy(alpha = 0.8f)
+    else if (!checked && enabled) MaterialTheme.colorScheme.onSurfaceVariant
+    else MaterialTheme.colorScheme.onSurface.toDisabledColor(disabledAlpha = 0.38f)
+}
+
+@Composable
+private fun switch_button_icon_color(enabled: Boolean): Color {
+    return if (enabled) MaterialTheme.colorScheme.primary
+    else MaterialTheme.colorScheme.onSurface.toDisabledColor(disabledAlpha = 0.38f)
+}
+
+@Composable
+private fun split_switch_button_container_color(checked: Boolean): Color {
+    return if (checked) MaterialTheme.colorScheme.primaryContainer
+    else MaterialTheme.colorScheme.surfaceContainer
+}
+
+@Composable
+private fun split_switch_button_content_color(checked: Boolean): Color {
+    return if (checked) MaterialTheme.colorScheme.onPrimaryContainer
+    else MaterialTheme.colorScheme.onSurface
+}
+
+@Composable
+private fun split_switch_button_secondary_label_color(checked: Boolean): Color {
+    return if (checked) MaterialTheme.colorScheme.onPrimaryContainer.copy(alpha = 0.8f)
+    else MaterialTheme.colorScheme.onSurfaceVariant
+}
+
+@Composable
+private fun Color.withDisabledAlphaApplied(enabled: Boolean): Color {
+    return if (!enabled) toDisabledColor(disabledAlpha = 0.38f) else this
+}
+
+private val CHECKED_COLOR = Color(0xFFA020F0)
+private val UNCHECKED_COLOR = Color(0xFFFFA500)
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextButtonTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextButtonTest.kt
index 9b37fc3..d1dd12d 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextButtonTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextButtonTest.kt
@@ -459,7 +459,7 @@
         val status = Status.Disabled
         rule.verifyButtonBorderColor(
             expectedBorderColor = {
-                MaterialTheme.colorScheme.outline.copy(alpha = DisabledBorderAlpha)
+                MaterialTheme.colorScheme.onSurface.copy(alpha = DisabledBorderAlpha)
             },
             content = { modifier: Modifier ->
                 TextButton(
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TimeTextScreenshotTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TimeTextScreenshotTest.kt
index 16065ea..d7fe226 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TimeTextScreenshotTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TimeTextScreenshotTest.kt
@@ -148,6 +148,20 @@
     }
 
     @Test
+    fun time_text_with_long_status_on_round_device() = verifyScreenshot {
+        val timeTextStyle = TimeTextDefaults.timeTextStyle(color = Color.Green)
+        TimeText(
+            contentColor = Color.Green,
+            timeTextStyle = timeTextStyle,
+            modifier = Modifier.testTag(TEST_TAG),
+        ) {
+            text("Long status that should be ellipsized.")
+            composable { Spacer(modifier = Modifier.size(4.dp)) }
+            time()
+        }
+    }
+
+    @Test
     fun time_text_with_custom_colors_on_non_round_device() =
         verifyScreenshot(false) {
             val customStyle = TimeTextDefaults.timeTextStyle(color = Color.Red)
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TimeTextTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TimeTextTest.kt
index 4594542..7720a01 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TimeTextTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TimeTextTest.kt
@@ -243,7 +243,7 @@
                 fontFamily = FontFamily.SansSerif
             )
         rule.setContent {
-            MaterialTheme(typography = MaterialTheme.typography.copy(labelSmall = testTextStyle)) {
+            MaterialTheme(typography = MaterialTheme.typography.copy(arcMedium = testTextStyle)) {
                 DeviceConfigurationOverride(DeviceConfigurationOverride.RoundScreen(false)) {
                     TimeText(
                         timeSource =
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleButtonScreenshotTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleButtonScreenshotTest.kt
index 1625337..fa66e67 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleButtonScreenshotTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleButtonScreenshotTest.kt
@@ -60,14 +60,10 @@
     }
 
     @Test
-    fun toggle_button_checked_switch() = verifyScreenshot {
-        sampleToggleButton(checked = true, toggleControl = { Switch() })
-    }
+    fun toggle_button_checked_switch() = verifyScreenshot { sampleSwitchButton(checked = true) }
 
     @Test
-    fun toggle_button_unchecked_switch() = verifyScreenshot {
-        sampleToggleButton(checked = false, toggleControl = { Switch() })
-    }
+    fun toggle_button_unchecked_switch() = verifyScreenshot { sampleSwitchButton(checked = false) }
 
     @Test
     fun toggle_button_checked_checkbox_rtl() =
@@ -84,13 +80,13 @@
     @Test
     fun toggle_button_checked_switch_rtl() =
         verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
-            sampleToggleButton(checked = true, toggleControl = { Switch() })
+            sampleSwitchButton(checked = true)
         }
 
     @Test
     fun toggle_button_unchecked_switch_rtl() =
         verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
-            sampleToggleButton(checked = false, toggleControl = { Switch() })
+            sampleSwitchButton(checked = false)
         }
 
     @Test
@@ -105,12 +101,12 @@
 
     @Test
     fun disabled_toggle_button_checked_switch() = verifyScreenshot {
-        sampleToggleButton(checked = true, enabled = false, toggleControl = { Switch() })
+        sampleSwitchButton(checked = true, enabled = false)
     }
 
     @Test
     fun disabled_toggle_button_unchecked_switch() = verifyScreenshot {
-        sampleToggleButton(checked = false, enabled = false, toggleControl = { Switch() })
+        sampleSwitchButton(checked = false, enabled = false)
     }
 
     @Test
@@ -128,13 +124,13 @@
     @Test
     fun disabled_toggle_button_checked_switch_rtl() =
         verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
-            sampleToggleButton(checked = true, enabled = false, toggleControl = { Switch() })
+            sampleSwitchButton(checked = true, enabled = false)
         }
 
     @Test
     fun disabled_toggle_button_unchecked_switch_rtl() =
         verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
-            sampleToggleButton(checked = false, enabled = false, toggleControl = { Switch() })
+            sampleSwitchButton(checked = false, enabled = false)
         }
 
     @Test
@@ -149,12 +145,12 @@
 
     @Test
     fun split_toggle_button_checked_switch() = verifyScreenshot {
-        sampleSplitToggleButton(checked = true, toggleControl = { Switch() })
+        sampleSplitSwitchButton(checked = true)
     }
 
     @Test
     fun split_toggle_button_unchecked_switch() = verifyScreenshot {
-        sampleSplitToggleButton(checked = false, toggleControl = { Switch() })
+        sampleSplitSwitchButton(checked = false)
     }
 
     @Test
@@ -172,13 +168,13 @@
     @Test
     fun split_toggle_button_checked_switch_rtl() =
         verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
-            sampleSplitToggleButton(checked = true, toggleControl = { Switch() })
+            sampleSplitSwitchButton(checked = true)
         }
 
     @Test
     fun split_toggle_button_unchecked_switch_rtl() =
         verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
-            sampleSplitToggleButton(checked = false, toggleControl = { Switch() })
+            sampleSplitSwitchButton(checked = false)
         }
 
     @Test
@@ -193,12 +189,12 @@
 
     @Test
     fun disabled_split_toggle_button_checked_switch() = verifyScreenshot {
-        sampleSplitToggleButton(checked = true, enabled = false, toggleControl = { Switch() })
+        sampleSplitSwitchButton(checked = true, enabled = false)
     }
 
     @Test
     fun disabled_split_toggle_button_unchecked_switch() = verifyScreenshot {
-        sampleSplitToggleButton(checked = false, enabled = false, toggleControl = { Switch() })
+        sampleSplitSwitchButton(checked = false, enabled = false)
     }
 
     @Test
@@ -216,13 +212,13 @@
     @Test
     fun disabled_split_toggle_button_checked_switch_rtl() =
         verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
-            sampleSplitToggleButton(checked = true, enabled = false, toggleControl = { Switch() })
+            sampleSplitSwitchButton(checked = true, enabled = false)
         }
 
     @Test
     fun disabled_split_toggle_button_unchecked_switch_rtl() =
         verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
-            sampleSplitToggleButton(checked = false, enabled = false, toggleControl = { Switch() })
+            sampleSplitSwitchButton(checked = false, enabled = false)
         }
 
     @Composable
@@ -259,37 +255,34 @@
     }
 
     @Composable
-    private fun sampleToggleButton(
+    private fun sampleSwitchButton(
         enabled: Boolean = true,
         checked: Boolean = true,
-        toggleControl: @Composable ToggleControlScope.() -> Unit = { Switch() },
     ) {
-        ToggleButton(
+        SwitchButton(
             icon = { TestIcon() },
             label = { Text("ToggleButton") },
             secondaryLabel = { Text("Secondary label") },
             checked = checked,
             enabled = enabled,
-            toggleControl = toggleControl,
             onCheckedChange = {},
             modifier = Modifier.testTag(TEST_TAG),
         )
     }
 
     @Composable
-    private fun sampleSplitToggleButton(
+    private fun sampleSplitSwitchButton(
         checked: Boolean = true,
         enabled: Boolean = true,
-        toggleControl: @Composable ToggleControlScope.() -> Unit = {}
     ) {
-        SplitToggleButton(
+        SplitSwitchButton(
             label = { Text("SplitToggleButton") },
             secondaryLabel = { Text("Secondary label") },
             checked = checked,
             enabled = enabled,
-            toggleControl = toggleControl,
             onCheckedChange = {},
-            onClick = {},
+            onContainerClick = {},
+            toggleContentDescription = "",
             modifier = Modifier.testTag(TEST_TAG),
         )
     }
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleButtonTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleButtonTest.kt
deleted file mode 100644
index 2bcee0c..0000000
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleButtonTest.kt
+++ /dev/null
@@ -1,747 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.wear.compose.material3
-
-import android.os.Build
-import androidx.annotation.RequiresApi
-import androidx.compose.foundation.background
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.BoxScope
-import androidx.compose.foundation.layout.RowScope
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.testutils.assertContainsColor
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.compositeOver
-import androidx.compose.ui.platform.testTag
-import androidx.compose.ui.semantics.Role
-import androidx.compose.ui.semantics.SemanticsProperties
-import androidx.compose.ui.semantics.role
-import androidx.compose.ui.semantics.semantics
-import androidx.compose.ui.test.SemanticsMatcher
-import androidx.compose.ui.test.assert
-import androidx.compose.ui.test.assertHasClickAction
-import androidx.compose.ui.test.assertHeightIsAtLeast
-import androidx.compose.ui.test.assertIsEnabled
-import androidx.compose.ui.test.assertIsNotEnabled
-import androidx.compose.ui.test.assertIsOff
-import androidx.compose.ui.test.assertIsOn
-import androidx.compose.ui.test.captureToImage
-import androidx.compose.ui.test.isToggleable
-import androidx.compose.ui.test.junit4.ComposeContentTestRule
-import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.compose.ui.test.onChildAt
-import androidx.compose.ui.test.onNodeWithTag
-import androidx.compose.ui.test.onNodeWithText
-import androidx.compose.ui.test.performClick
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.dp
-import androidx.wear.compose.material3.samples.SplitToggleButtonWithSwitch
-import androidx.wear.compose.material3.samples.ToggleButtonWithSwitch
-import org.junit.Assert
-import org.junit.Rule
-import org.junit.Test
-
-class ToggleButtonTest {
-    @get:Rule val rule = createComposeRule()
-
-    @Test
-    fun supports_testtag() {
-        rule.setContentWithTheme { ToggleButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG)) }
-
-        rule.onNodeWithTag(TEST_TAG).assertExists()
-    }
-
-    @Test
-    fun split_button_supports_testtag() {
-        rule.setContentWithTheme {
-            SplitToggleButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG))
-        }
-
-        rule.onNodeWithTag(TEST_TAG).assertExists()
-    }
-
-    @Test
-    fun toggle_button_samples_build() {
-        rule.setContentWithTheme { ToggleButtonWithSwitch() }
-    }
-
-    @Test
-    fun split_toggle_button_samples_build() {
-        rule.setContentWithTheme { SplitToggleButtonWithSwitch() }
-    }
-
-    @Test
-    fun has_clickaction_when_enabled() {
-        rule.setContentWithTheme {
-            ToggleButtonWithDefaults(enabled = true, modifier = Modifier.testTag(TEST_TAG))
-        }
-
-        rule.onNodeWithTag(TEST_TAG).assertHasClickAction()
-    }
-
-    @Test
-    fun split_button_has_clickaction_when_enabled() {
-        rule.setContentWithTheme {
-            SplitToggleButtonWithDefaults(enabled = true, modifier = Modifier.testTag(TEST_TAG))
-        }
-
-        rule.onNodeWithTag(TEST_TAG).onChildAt(0).assertHasClickAction()
-    }
-
-    @Test
-    fun has_clickaction_when_disabled() {
-        rule.setContentWithTheme {
-            ToggleButtonWithDefaults(enabled = false, modifier = Modifier.testTag(TEST_TAG))
-        }
-
-        rule.onNodeWithTag(TEST_TAG).assertHasClickAction()
-    }
-
-    @Test
-    fun split_button_has_clickaction_when_disabled() {
-        rule.setContentWithTheme {
-            SplitToggleButtonWithDefaults(enabled = false, modifier = Modifier.testTag(TEST_TAG))
-        }
-
-        rule.onNodeWithTag(TEST_TAG).onChildAt(0).assertHasClickAction()
-    }
-
-    @Test
-    fun is_toggleable() {
-        rule.setContentWithTheme { ToggleButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG)) }
-
-        rule.onNode(isToggleable()).assertExists()
-    }
-
-    @Test
-    fun split_button_is_toggleable() {
-        rule.setContentWithTheme {
-            SplitToggleButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG))
-        }
-
-        rule.onNode(isToggleable()).assertExists()
-    }
-
-    @Test
-    fun split_button_is_clickable() {
-        rule.setContentWithTheme {
-            SplitToggleButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG))
-        }
-        rule.onNodeWithTag(TEST_TAG).onChildAt(0).assertHasClickAction()
-    }
-
-    @Test
-    fun is_correctly_enabled() {
-        rule.setContentWithTheme {
-            ToggleButtonWithDefaults(enabled = true, modifier = Modifier.testTag(TEST_TAG))
-        }
-
-        rule.onNodeWithTag(TEST_TAG).assertIsEnabled()
-    }
-
-    @Test
-    fun split_button_is_correctly_enabled() {
-        rule.setContentWithTheme {
-            SplitToggleButtonWithDefaults(enabled = true, modifier = Modifier.testTag(TEST_TAG))
-        }
-
-        rule.onNodeWithTag(TEST_TAG).assertIsEnabled()
-    }
-
-    @Test
-    fun is_correctly_disabled() {
-        rule.setContentWithTheme {
-            ToggleButtonWithDefaults(enabled = false, modifier = Modifier.testTag(TEST_TAG))
-        }
-
-        rule.onNodeWithTag(TEST_TAG).assertIsNotEnabled()
-    }
-
-    @Test
-    fun split_button_is_correctly_disabled() {
-        rule.setContentWithTheme {
-            SplitToggleButtonWithDefaults(enabled = false, modifier = Modifier.testTag(TEST_TAG))
-        }
-
-        rule.onNodeWithTag(TEST_TAG).onChildAt(0).assertIsNotEnabled()
-    }
-
-    @Test
-    fun is_on_when_checked() {
-        rule.setContentWithTheme {
-            ToggleButtonWithDefaults(checked = true, modifier = Modifier.testTag(TEST_TAG))
-        }
-
-        rule.onNodeWithTag(TEST_TAG).assertIsOn()
-    }
-
-    @Test
-    fun split_button_is_on_when_checked() {
-        rule.setContentWithTheme {
-            SplitToggleButtonWithDefaults(checked = true, modifier = Modifier.testTag(TEST_TAG))
-        }
-
-        rule.onNodeWithTag(TEST_TAG).onChildAt(1).assertIsOn()
-    }
-
-    @Test
-    fun is_off_when_unchecked() {
-        rule.setContentWithTheme {
-            ToggleButtonWithDefaults(checked = false, modifier = Modifier.testTag(TEST_TAG))
-        }
-
-        rule.onNodeWithTag(TEST_TAG).assertIsOff()
-    }
-
-    @Test
-    fun split_button_is_off_when_unchecked() {
-        rule.setContentWithTheme {
-            SplitToggleButtonWithDefaults(checked = false, modifier = Modifier.testTag(TEST_TAG))
-        }
-
-        rule.onNodeWithTag(TEST_TAG).onChildAt(1).assertIsOff()
-    }
-
-    @Test
-    fun responds_to_toggle_on() {
-        rule.setContentWithTheme {
-            val (checked, onCheckedChange) = remember { mutableStateOf(false) }
-            ToggleButtonWithDefaults(
-                checked = checked,
-                onCheckedChange = onCheckedChange,
-                enabled = true,
-                modifier = Modifier.testTag(TEST_TAG)
-            )
-        }
-
-        rule.onNodeWithTag(TEST_TAG).assertIsOff().performClick().assertIsOn()
-    }
-
-    @Test
-    fun split_button_responds_to_toggle_on() {
-        rule.setContentWithTheme {
-            val (checked, onCheckedChange) = remember { mutableStateOf(false) }
-            SplitToggleButtonWithDefaults(
-                checked = checked,
-                onCheckedChange = onCheckedChange,
-                enabled = true,
-                modifier = Modifier.testTag(TEST_TAG)
-            )
-        }
-
-        rule.onNodeWithTag(TEST_TAG).onChildAt(1).assertIsOff().performClick().assertIsOn()
-    }
-
-    @Test
-    fun responds_to_toggle_off() {
-        rule.setContentWithTheme {
-            val (checked, onCheckedChange) = remember { mutableStateOf(true) }
-            ToggleButtonWithDefaults(
-                checked = checked,
-                onCheckedChange = onCheckedChange,
-                enabled = true,
-                modifier = Modifier.testTag(TEST_TAG)
-            )
-        }
-
-        rule.onNodeWithTag(TEST_TAG).assertIsOn().performClick().assertIsOff()
-    }
-
-    @Test
-    fun split_button_responds_to_toggle_off() {
-        rule.setContentWithTheme {
-            val (checked, onCheckedChange) = remember { mutableStateOf(true) }
-            SplitToggleButtonWithDefaults(
-                checked = checked,
-                onCheckedChange = onCheckedChange,
-                enabled = true,
-                modifier = Modifier.testTag(TEST_TAG)
-            )
-        }
-
-        rule.onNodeWithTag(TEST_TAG).onChildAt(1).assertIsOn().performClick().assertIsOff()
-    }
-
-    @Test
-    fun does_not_toggle_when_disabled() {
-        rule.setContentWithTheme {
-            val (checked, onCheckedChange) = remember { mutableStateOf(false) }
-            ToggleButtonWithDefaults(
-                checked = checked,
-                onCheckedChange = onCheckedChange,
-                enabled = false,
-                modifier = Modifier.testTag(TEST_TAG)
-            )
-        }
-
-        rule.onNodeWithTag(TEST_TAG).assertIsOff().performClick().assertIsOff()
-    }
-
-    @Test
-    fun split_button_does_not_toggle_when_disabled() {
-        rule.setContentWithTheme {
-            val (checked, onCheckedChange) = remember { mutableStateOf(false) }
-            SplitToggleButtonWithDefaults(
-                checked = checked,
-                onCheckedChange = onCheckedChange,
-                enabled = false,
-                modifier = Modifier.testTag(TEST_TAG)
-            )
-        }
-
-        rule.onNodeWithTag(TEST_TAG).onChildAt(1).assertIsOff().performClick().assertIsOff()
-    }
-
-    @Test
-    fun can_override_role() {
-        rule.setContentWithTheme {
-            ToggleButtonWithDefaults(
-                modifier = Modifier.testTag(TEST_TAG).semantics { role = Role.Button }
-            )
-        }
-
-        rule
-            .onNodeWithTag(TEST_TAG)
-            .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Button))
-    }
-
-    @Test
-    fun split_button_clickable_has_role_button() {
-        rule.setContentWithTheme {
-            SplitToggleButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG))
-        }
-
-        // NB The toggle control (Checkbox or Switch) provides its own role,
-        // but the main clickable section is a Button.
-        rule
-            .onNodeWithTag(TEST_TAG)
-            .onChildAt(0)
-            .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Button))
-    }
-
-    @Test
-    fun displays_label_content() {
-        val textContent = "abc"
-
-        rule.setContentWithTheme {
-            ToggleButtonWithDefaults(
-                checked = true,
-                onCheckedChange = {},
-                label = { Text(text = textContent) }
-            )
-        }
-
-        rule.onNodeWithText(textContent).assertExists()
-    }
-
-    @Test
-    fun split_button_displays_label_content() {
-        val textContent = "abc"
-
-        rule.setContentWithTheme {
-            SplitToggleButtonWithDefaults(
-                checked = true,
-                onCheckedChange = {},
-                label = { Text(text = textContent) }
-            )
-        }
-
-        rule.onNodeWithText(textContent).assertExists()
-    }
-
-    @Test
-    fun toggle_button_hasAdjustableHeight() {
-        val minHeight: Dp = 53.dp
-
-        rule
-            .setContentWithThemeForSizeAssertions {
-                ToggleButtonWithDefaults(
-                    label = {
-                        Text(
-                            text =
-                                "ToggleButton text spanning over multiple lines of text " +
-                                    "to test height is adjustable. This should exceed the minimum height" +
-                                    " for the ToggleButton."
-                        )
-                    },
-                    secondaryLabel = { Text(text = "Secondary label with text.") }
-                )
-            }
-            .assertHeightIsAtLeast(minHeight)
-    }
-
-    @Test
-    fun split_toggle_button_hasAdjustableHeight() {
-        val minHeight: Dp = 53.dp
-
-        rule
-            .setContentWithThemeForSizeAssertions {
-                SplitToggleButtonWithDefaults(
-                    label = { Text(text = "Primary label with 3 lines of text.") },
-                    secondaryLabel = {
-                        Text(
-                            text =
-                                "SplitToggleButton text spanning over multiple lines of text " +
-                                    "to test height is adjustable. This should exceed the minimum height" +
-                                    " for the SplitToggleButton."
-                        )
-                    }
-                )
-            }
-            .assertHeightIsAtLeast(minHeight)
-    }
-
-    @Test
-    fun toggle_button_height_defaults_52dp() {
-        rule
-            .setContentWithThemeForSizeAssertions {
-                ToggleButtonWithDefaults(secondaryLabel = { Text("Secondary label") })
-            }
-            .assertHeightIsEqualTo(52.dp)
-    }
-
-    @Test
-    fun split_toggle_button_height_defaults_52dp() {
-        rule
-            .setContentWithThemeForSizeAssertions { SplitToggleButtonWithDefaults() }
-            .assertHeightIsEqualTo(52.dp)
-    }
-
-    @RequiresApi(Build.VERSION_CODES.O)
-    @Test
-    fun toggle_button_allows_checked_background_color_override() =
-        verifyToggleButtonBackgroundColor(
-            checked = true,
-            enabled = true,
-            expectedColor = CHECKED_COLOR
-        )
-
-    @RequiresApi(Build.VERSION_CODES.O)
-    @Test
-    fun toggle_button_allows_unchecked_background_color_override() =
-        verifyToggleButtonBackgroundColor(
-            checked = false,
-            enabled = true,
-            expectedColor = UNCHECKED_COLOR
-        )
-
-    @RequiresApi(Build.VERSION_CODES.O)
-    @Test
-    fun split_toggle_button_allows_checked_background_color_override() =
-        verifySplitToggleButtonBackgroundColor(
-            checked = true,
-            enabled = true,
-            expectedColor = CHECKED_COLOR
-        )
-
-    @RequiresApi(Build.VERSION_CODES.O)
-    @Test
-    fun split_toggle_button_allows_unchecked_background_color_override() =
-        verifySplitToggleButtonBackgroundColor(
-            checked = false,
-            enabled = true,
-            expectedColor = UNCHECKED_COLOR
-        )
-
-    @RequiresApi(Build.VERSION_CODES.O)
-    @Test
-    fun verify_toggle_button_colors_enabled_and_checked() {
-        rule.verifyToggleButtonColors(checked = true, enabled = true)
-    }
-
-    @RequiresApi(Build.VERSION_CODES.O)
-    @Test
-    fun verify_toggle_button_colors_enabled_and_unchecked() {
-        rule.verifyToggleButtonColors(checked = false, enabled = true)
-    }
-
-    @RequiresApi(Build.VERSION_CODES.O)
-    @Test
-    fun verify_toggle_button_colors_disabled_and_checked() {
-        rule.verifyToggleButtonColors(checked = true, enabled = false)
-    }
-
-    @RequiresApi(Build.VERSION_CODES.O)
-    @Test
-    fun verify_toggle_button_colors_disabled_and_unchecked() {
-        rule.verifyToggleButtonColors(checked = false, enabled = false)
-    }
-
-    @RequiresApi(Build.VERSION_CODES.O)
-    @Test
-    fun verify_split_toggle_button_colors_enabled_and_checked() {
-        rule.verifySplitToggleButtonColors(checked = true, enabled = true)
-    }
-
-    @RequiresApi(Build.VERSION_CODES.O)
-    @Test
-    fun verify_split_toggle_button_colors_enabled_and_unchecked() {
-        rule.verifySplitToggleButtonColors(checked = false, enabled = true)
-    }
-
-    @RequiresApi(Build.VERSION_CODES.O)
-    @Test
-    fun verify_split_toggle_button_colors_disabled_and_checked() {
-        rule.verifySplitToggleButtonColors(checked = true, enabled = false)
-    }
-
-    @RequiresApi(Build.VERSION_CODES.O)
-    @Test
-    fun verify_split_toggle_button_colors_disabled_and_unchecked() {
-        rule.verifySplitToggleButtonColors(checked = false, enabled = false)
-    }
-
-    @RequiresApi(Build.VERSION_CODES.O)
-    private fun verifyToggleButtonBackgroundColor(
-        checked: Boolean,
-        enabled: Boolean,
-        expectedColor: Color
-    ) {
-        rule.setContentWithTheme {
-            ToggleButtonWithDefaults(
-                checked = checked,
-                colors =
-                    ToggleButtonDefaults.toggleButtonColors(
-                        checkedContainerColor = CHECKED_COLOR,
-                        uncheckedContainerColor = UNCHECKED_COLOR
-                    ),
-                onCheckedChange = {},
-                enabled = enabled,
-                modifier = Modifier.testTag(TEST_TAG),
-            )
-        }
-
-        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(expectedColor)
-    }
-
-    @RequiresApi(Build.VERSION_CODES.O)
-    private fun verifySplitToggleButtonBackgroundColor(
-        checked: Boolean,
-        enabled: Boolean,
-        expectedColor: Color
-    ) {
-        rule.setContentWithTheme {
-            SplitToggleButtonWithDefaults(
-                checked = checked,
-                colors =
-                    ToggleButtonDefaults.splitToggleButtonColors(
-                        checkedContainerColor = CHECKED_COLOR,
-                        uncheckedContainerColor = UNCHECKED_COLOR
-                    ),
-                onCheckedChange = {},
-                enabled = enabled,
-                modifier = Modifier.testTag(TEST_TAG),
-            )
-        }
-
-        rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(expectedColor)
-    }
-}
-
-@Composable
-private fun ToggleButtonWithDefaults(
-    modifier: Modifier = Modifier,
-    checked: Boolean = true,
-    enabled: Boolean = true,
-    colors: ToggleButtonColors = ToggleButtonDefaults.toggleButtonColors(),
-    onCheckedChange: (Boolean) -> Unit = {},
-    label: @Composable RowScope.() -> Unit = { Text("Primary") },
-    secondaryLabel: @Composable (RowScope.() -> Unit)? = null,
-    icon: @Composable (BoxScope.() -> Unit)? = null,
-    toggleControl: @Composable ToggleControlScope.() -> Unit = { Switch() }
-) =
-    ToggleButton(
-        modifier = modifier,
-        checked = checked,
-        enabled = enabled,
-        colors = colors,
-        onCheckedChange = onCheckedChange,
-        label = label,
-        secondaryLabel = secondaryLabel,
-        icon = icon,
-        toggleControl = toggleControl
-    )
-
-@Composable
-private fun SplitToggleButtonWithDefaults(
-    modifier: Modifier = Modifier,
-    checked: Boolean = true,
-    enabled: Boolean = true,
-    colors: SplitToggleButtonColors = ToggleButtonDefaults.splitToggleButtonColors(),
-    onCheckedChange: (Boolean) -> Unit = {},
-    onClick: () -> Unit = {},
-    label: @Composable RowScope.() -> Unit = { Text("Primary") },
-    secondaryLabel: @Composable (RowScope.() -> Unit)? = null,
-    toggleControl: @Composable ToggleControlScope.() -> Unit = { Switch() }
-) =
-    SplitToggleButton(
-        modifier = modifier,
-        colors = colors,
-        checked = checked,
-        enabled = enabled,
-        onCheckedChange = onCheckedChange,
-        label = label,
-        secondaryLabel = secondaryLabel,
-        onClick = onClick,
-        toggleControl = toggleControl,
-    )
-
-@RequiresApi(Build.VERSION_CODES.O)
-private fun ComposeContentTestRule.verifyToggleButtonColors(enabled: Boolean, checked: Boolean) {
-    val testBackgroundColor = Color.White
-    var expectedContainerColor = Color.Transparent
-    var expectedLabelColor = Color.Transparent
-    var expectedIconColor = Color.Transparent
-    var expectedSecondaryLabelColor = Color.Transparent
-    var actualLabelColor = Color.Transparent
-    var actualIconColor = Color.Transparent
-    var actualSecondaryLabelColor = Color.Transparent
-    setContentWithTheme {
-        expectedContainerColor =
-            toggle_button_container_color(checked, enabled).compositeOver(testBackgroundColor)
-        expectedLabelColor = toggle_button_content_color(checked, enabled)
-        expectedSecondaryLabelColor = toggle_button_secondary_label_color(checked, enabled)
-        expectedIconColor = toggle_button_icon_color(enabled)
-        Box(Modifier.fillMaxSize().background(testBackgroundColor)) {
-            ToggleButton(
-                modifier = Modifier.testTag(TEST_TAG),
-                checked = checked,
-                onCheckedChange = {},
-                enabled = enabled,
-                toggleControl = { Switch() },
-                label = { actualLabelColor = LocalContentColor.current },
-                secondaryLabel = { actualSecondaryLabelColor = LocalContentColor.current },
-                icon = { actualIconColor = LocalContentColor.current }
-            )
-        }
-    }
-    Assert.assertEquals(expectedLabelColor, actualLabelColor)
-    Assert.assertEquals(expectedSecondaryLabelColor, actualSecondaryLabelColor)
-    Assert.assertEquals(expectedIconColor, actualIconColor)
-
-    onNodeWithTag(TEST_TAG)
-        .captureToImage()
-        .assertContainsColor(
-            if (expectedContainerColor != Color.Transparent) expectedContainerColor
-            else testBackgroundColor,
-        )
-}
-
-@RequiresApi(Build.VERSION_CODES.O)
-private fun ComposeContentTestRule.verifySplitToggleButtonColors(
-    enabled: Boolean,
-    checked: Boolean
-) {
-    val testBackgroundColor = Color.White
-    var expectedContainerColor = Color.Transparent
-    var expectedLabelColor = Color.Transparent
-    var expectedSecondaryLabelColor = Color.Transparent
-    var actualLabelColor = Color.Transparent
-    var actualSecondaryLabelColor = Color.Transparent
-    setContentWithTheme {
-        expectedContainerColor =
-            split_toggle_button_container_color(checked)
-                .withDisabledAlphaApplied(enabled = enabled)
-                .compositeOver(testBackgroundColor)
-        expectedLabelColor =
-            split_toggle_button_content_color(checked).withDisabledAlphaApplied(enabled = enabled)
-        expectedSecondaryLabelColor =
-            split_toggle_button_secondary_label_color(checked)
-                .withDisabledAlphaApplied(enabled = enabled)
-        Box(Modifier.fillMaxSize().background(testBackgroundColor)) {
-            SplitToggleButton(
-                modifier = Modifier.testTag(TEST_TAG),
-                checked = checked,
-                onCheckedChange = {},
-                onClick = {},
-                enabled = enabled,
-                toggleControl = { Switch() },
-                label = { actualLabelColor = LocalContentColor.current },
-                secondaryLabel = { actualSecondaryLabelColor = LocalContentColor.current },
-            )
-        }
-    }
-    Assert.assertEquals(expectedLabelColor, actualLabelColor)
-    Assert.assertEquals(expectedSecondaryLabelColor, actualSecondaryLabelColor)
-
-    onNodeWithTag(TEST_TAG)
-        .captureToImage()
-        .assertContainsColor(
-            if (expectedContainerColor != Color.Transparent) expectedContainerColor
-            else testBackgroundColor,
-        )
-}
-
-@Composable
-private fun toggle_button_container_color(
-    checked: Boolean,
-    enabled: Boolean,
-): Color {
-    return if (checked && enabled) MaterialTheme.colorScheme.primaryContainer
-    else if (!checked && enabled) MaterialTheme.colorScheme.surfaceContainer
-    else MaterialTheme.colorScheme.onSurface.toDisabledColor(disabledAlpha = 0.12f)
-}
-
-@Composable
-private fun toggle_button_content_color(checked: Boolean, enabled: Boolean): Color {
-    return if (checked && enabled) MaterialTheme.colorScheme.onPrimaryContainer
-    else if (!checked && enabled) MaterialTheme.colorScheme.onSurface
-    else MaterialTheme.colorScheme.onSurface.toDisabledColor(disabledAlpha = 0.38f)
-}
-
-@Composable
-private fun toggle_button_secondary_label_color(checked: Boolean, enabled: Boolean): Color {
-    return if (checked && enabled) MaterialTheme.colorScheme.onPrimaryContainer.copy(alpha = 0.8f)
-    else if (!checked && enabled) MaterialTheme.colorScheme.onSurfaceVariant
-    else MaterialTheme.colorScheme.onSurface.toDisabledColor(disabledAlpha = 0.38f)
-}
-
-@Composable
-private fun toggle_button_icon_color(enabled: Boolean): Color {
-    return if (enabled) MaterialTheme.colorScheme.primary
-    else MaterialTheme.colorScheme.onSurface.toDisabledColor(disabledAlpha = 0.38f)
-}
-
-@Composable
-private fun split_toggle_button_container_color(checked: Boolean): Color {
-    return if (checked) MaterialTheme.colorScheme.primaryContainer
-    else MaterialTheme.colorScheme.surfaceContainer
-}
-
-@Composable
-private fun split_toggle_button_content_color(checked: Boolean): Color {
-    return if (checked) MaterialTheme.colorScheme.onPrimaryContainer
-    else MaterialTheme.colorScheme.onSurface
-}
-
-@Composable
-private fun split_toggle_button_secondary_label_color(checked: Boolean): Color {
-    return if (checked) MaterialTheme.colorScheme.onPrimaryContainer.copy(alpha = 0.8f)
-    else MaterialTheme.colorScheme.onSurfaceVariant
-}
-
-@Composable
-private fun Color.withDisabledAlphaApplied(enabled: Boolean): Color {
-    return if (!enabled) toDisabledColor(disabledAlpha = 0.38f) else this
-}
-
-private val CHECKED_COLOR = Color(0xFFA020F0)
-private val UNCHECKED_COLOR = Color(0xFFFFA500)
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleControlsScreenshotTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleControlsScreenshotTest.kt
deleted file mode 100644
index e8e7428..0000000
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleControlsScreenshotTest.kt
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.wear.compose.material3
-
-import android.os.Build
-import androidx.compose.foundation.background
-import androidx.compose.foundation.layout.BoxScope
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.testutils.assertAgainstGolden
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.compositeOver
-import androidx.compose.ui.platform.LocalLayoutDirection
-import androidx.compose.ui.platform.testTag
-import androidx.compose.ui.test.captureToImage
-import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.compose.ui.test.onNodeWithTag
-import androidx.compose.ui.unit.LayoutDirection
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.MediumTest
-import androidx.test.filters.SdkSuppress
-import androidx.test.screenshot.AndroidXScreenshotTestRule
-import androidx.test.screenshot.matchers.MSSIMMatcher
-import org.junit.Rule
-import org.junit.Test
-import org.junit.rules.TestName
-import org.junit.runner.RunWith
-
-@MediumTest
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
-class ToggleControlsScreenshotTest {
-    @get:Rule val rule = createComposeRule()
-
-    @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
-
-    @get:Rule val testName = TestName()
-
-    @Test
-    fun switch_checked_enabled() = verifyScreenshot {
-        with(ToggleControlScope(isChecked = true, isEnabled = true)) {
-            Switch(modifier = testBackgroundModifier())
-        }
-    }
-
-    @Test
-    fun switch_unchecked_enabled() = verifyScreenshot {
-        with(ToggleControlScope(isChecked = false, isEnabled = true)) {
-            Switch(modifier = testBackgroundModifier())
-        }
-    }
-
-    @Test
-    fun switch_checked_disabled() = verifyScreenshot {
-        with(ToggleControlScope(isChecked = true, isEnabled = false)) {
-            Switch(modifier = testBackgroundModifier())
-        }
-    }
-
-    @Test
-    fun switch_unchecked_disabled() = verifyScreenshot {
-        with(ToggleControlScope(isChecked = false, isEnabled = false)) {
-            Switch(modifier = testBackgroundModifier())
-        }
-    }
-
-    @Test
-    fun switch_rtl_checked_enabled() = verifyScreenshot {
-        CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
-            with(ToggleControlScope(isChecked = true, isEnabled = true)) {
-                Switch(modifier = testBackgroundModifier())
-            }
-        }
-    }
-
-    @Test
-    fun switch_rtl_unchecked_enabled() = verifyScreenshot {
-        CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
-            with(ToggleControlScope(isChecked = false, isEnabled = true)) {
-                Switch(modifier = testBackgroundModifier())
-            }
-        }
-    }
-
-    @Test
-    fun switch_rtl_checked_disabled() = verifyScreenshot {
-        CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
-            with(ToggleControlScope(isChecked = true, isEnabled = false)) {
-                Switch(modifier = testBackgroundModifier())
-            }
-        }
-    }
-
-    @Test
-    fun switch_rtl_unchecked_disabled() = verifyScreenshot {
-        CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
-            with(ToggleControlScope(isChecked = false, isEnabled = false)) {
-                Switch(modifier = testBackgroundModifier())
-            }
-        }
-    }
-
-    private fun verifyScreenshot(
-        threshold: Double = 0.98,
-        content: @Composable BoxScope.() -> Unit
-    ) {
-        rule.setContentWithTheme(composable = content)
-        rule
-            .onNodeWithTag(TEST_TAG)
-            .captureToImage()
-            .assertAgainstGolden(screenshotRule, testName.methodName, MSSIMMatcher(threshold))
-    }
-
-    @Composable
-    private fun testBackgroundModifier(): Modifier =
-        Modifier.testTag(TEST_TAG)
-            .background(
-                MaterialTheme.colorScheme.primary
-                    .copy(alpha = 0.5f)
-                    .compositeOver(MaterialTheme.colorScheme.surfaceContainer)
-            )
-}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleControlsTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleControlsTest.kt
deleted file mode 100644
index f2eee2a..0000000
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleControlsTest.kt
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.wear.compose.material3
-
-import android.os.Build
-import androidx.annotation.RequiresApi
-import androidx.compose.testutils.assertContainsColor
-import androidx.compose.testutils.assertDoesNotContainColor
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.platform.testTag
-import androidx.compose.ui.semantics.Role
-import androidx.compose.ui.semantics.SemanticsProperties
-import androidx.compose.ui.test.SemanticsMatcher
-import androidx.compose.ui.test.assert
-import androidx.compose.ui.test.assertHasNoClickAction
-import androidx.compose.ui.test.assertWidthIsEqualTo
-import androidx.compose.ui.test.captureToImage
-import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.compose.ui.test.onNodeWithTag
-import androidx.compose.ui.unit.dp
-import org.junit.Rule
-import org.junit.Test
-
-class ToggleControlsTest {
-    @get:Rule val rule = createComposeRule()
-
-    @Test
-    fun switch_supports_testtag() {
-        rule.setContentWithTheme {
-            with(ToggleControlScope(isEnabled = true, isChecked = true)) {
-                Switch(modifier = Modifier.testTag(TEST_TAG))
-            }
-        }
-
-        rule.onNodeWithTag(TEST_TAG).assertExists()
-    }
-
-    @Test
-    fun switch_is_expected_size() {
-        rule
-            .setContentWithThemeForSizeAssertions {
-                with(ToggleControlScope(isEnabled = true, isChecked = true)) {
-                    Switch(modifier = Modifier.testTag(TEST_TAG))
-                }
-            }
-            .assertHeightIsEqualTo(SWITCH_CONTROL_HEIGHT)
-            .assertWidthIsEqualTo(TOGGLE_CONTROL_WIDTH)
-    }
-
-    @Test
-    fun switch_has_role_switch_when_oncheckedchange_defined() {
-        rule.setContentWithTheme {
-            with(ToggleControlScope(isEnabled = true, isChecked = true)) {
-                Switch(modifier = Modifier.testTag(TEST_TAG))
-            }
-        }
-
-        rule
-            .onNodeWithTag(TEST_TAG)
-            .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Switch))
-    }
-
-    @Test
-    fun switch_has_no_clickaction_by_default() {
-        rule.setContentWithTheme {
-            with(ToggleControlScope(isEnabled = true, isChecked = true)) {
-                Switch(modifier = Modifier.testTag(TEST_TAG))
-            }
-        }
-
-        rule.onNodeWithTag(TEST_TAG).assertHasNoClickAction()
-    }
-
-    @RequiresApi(Build.VERSION_CODES.O)
-    @Test
-    fun switch_checked_colors_are_customisable() {
-        val thumbColor = Color.Green
-        val thumbIconColor = Color.Yellow
-        val trackColor = Color.Blue
-        val trackStrokeColor = Color.Red
-        rule.setContentWithTheme {
-            with(ToggleControlScope(isEnabled = true, isChecked = true)) {
-                Switch(
-                    colors =
-                        SwitchDefaults.colors(
-                            checkedThumbColor = thumbColor,
-                            checkedThumbIconColor = thumbIconColor,
-                            checkedTrackColor = trackColor,
-                            checkedTrackBorderColor = trackStrokeColor
-                        ),
-                    modifier = Modifier.testTag(TEST_TAG)
-                )
-            }
-        }
-
-        val image = rule.onNodeWithTag(TEST_TAG).captureToImage()
-        image.assertContainsColor(thumbColor)
-        image.assertContainsColor(thumbIconColor)
-        image.assertContainsColor(trackColor)
-        image.assertContainsColor(trackStrokeColor)
-    }
-
-    @RequiresApi(Build.VERSION_CODES.O)
-    @Test
-    fun switch_unchecked_colors_are_customisable() {
-        val thumbColor = Color.Green
-        val thumbIconColor = Color.Yellow
-        val trackColor = Color.Blue
-        val trackStrokeColor = Color.Red
-        rule.setContentWithTheme {
-            with(ToggleControlScope(isEnabled = true, isChecked = false)) {
-                Switch(
-                    colors =
-                        SwitchDefaults.colors(
-                            uncheckedThumbColor = thumbColor,
-                            uncheckedThumbIconColor = thumbIconColor,
-                            uncheckedTrackColor = trackColor,
-                            uncheckedTrackBorderColor = trackStrokeColor
-                        ),
-                    modifier = Modifier.testTag(TEST_TAG)
-                )
-            }
-        }
-
-        rule.waitForIdle()
-        val image = rule.onNodeWithTag(TEST_TAG).captureToImage()
-        image.assertContainsColor(thumbColor)
-        // NB opacity of icon is decreased to 0 in unchecked state,
-        // hence we are asserting that the thumbIconColor should not exist.
-        image.assertDoesNotContainColor(thumbIconColor)
-        image.assertContainsColor(trackColor)
-    }
-}
-
-private val TOGGLE_CONTROL_WIDTH = 32.dp
-private val SWITCH_CONTROL_HEIGHT = 22.dp
-private val TOGGLE_CONTROL_HEIGHT = 24.dp
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/AnimatedText.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/AnimatedText.kt
new file mode 100644
index 0000000..02a59f1
--- /dev/null
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/AnimatedText.kt
@@ -0,0 +1,573 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.material3
+
+import android.graphics.Canvas
+import android.graphics.Paint.FontMetrics
+import android.graphics.fonts.Font
+import android.graphics.fonts.FontVariationAxis
+import android.graphics.fonts.FontVariationAxis.toFontVariationSettings
+import android.graphics.text.PositionedGlyphs
+import android.graphics.text.TextRunShaper
+import android.text.TextPaint
+import android.util.LruCache
+import androidx.annotation.RequiresApi
+import androidx.compose.foundation.Canvas
+import androidx.compose.foundation.layout.size
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.nativeCanvas
+import androidx.compose.ui.graphics.takeOrElse
+import androidx.compose.ui.graphics.toArgb
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.platform.LocalFontFamilyResolver
+import androidx.compose.ui.platform.LocalLayoutDirection
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.font.FontFamily
+import androidx.compose.ui.text.font.FontStyle
+import androidx.compose.ui.text.font.FontSynthesis
+import androidx.compose.ui.text.font.FontVariation
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.font.resolveAsTypeface
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.DpSize
+import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.unit.LayoutDirection
+import androidx.compose.ui.unit.TextUnit
+import androidx.compose.ui.util.lerp
+import kotlin.math.floor
+import kotlin.math.max
+import kotlin.math.roundToInt
+
+/**
+ * A composable that displays an animated text.
+ *
+ * AnimatedText can be used to animate a text along font variation axes and size. It requires an
+ * [AnimatedTextFontRegistry] to improve performance.
+ *
+ * [AnimatedTextFontRegistry] can be generated using [rememberAnimatedTextFontRegistry] method,
+ * which requires start and end font variation axes, and start and end font sizes for the animation.
+ *
+ * Start of the animation is when the animatable is at 0f and end of the animation is when the
+ * animatable is at 1f. Current animation progress is provided by the [progressFraction] function.
+ * This should be between 0f and 1f, but might go beyond in some cases such as overshooting spring
+ * animations.
+ *
+ * Example of a one-shot animation with AnimatedText
+ *
+ * @sample androidx.wear.compose.material3.samples.AnimatedTextSample
+ *
+ * Example of an animation in response to a button press with AnimatedText
+ *
+ * @sample androidx.wear.compose.material3.samples.AnimatedTextSampleButtonResponse
+ *
+ * Example showing how [AnimatedTextFontRegistry] can be reused and shared between two
+ * [AnimatedText] composables
+ *
+ * @sample androidx.wear.compose.material3.samples.AnimatedTextSampleSharedFontRegistry
+ * @param text The text to be displayed.
+ * @param fontRegistry The font registry to be used to animate the text.
+ * @param progressFraction A provider for the current state of the animation. Provided value should
+ *   be between 0f and 1f, but might go beyond in some cases such as overshooting spring animations.
+ * @param modifier Modifier to be applied to the composable.
+ * @param contentAlignment Alignment within the bounds of the Canvas.
+ */
+@Composable
+@RequiresApi(31)
+fun AnimatedText(
+    text: String,
+    fontRegistry: AnimatedTextFontRegistry,
+    progressFraction: () -> Float,
+    modifier: Modifier = Modifier,
+    contentAlignment: Alignment = Alignment.Center,
+) {
+    val density = LocalDensity.current
+    val layoutDirection = LocalLayoutDirection.current
+    val animatedTextState =
+        remember(fontRegistry, layoutDirection, density) {
+            AnimatedTextState(fontRegistry, layoutDirection, density)
+        }
+    // Update before composing Canvas to make sure size gets updated
+    animatedTextState.updateText(text)
+    Canvas(modifier.size(animatedTextState.size)) {
+        animatedTextState.draw(
+            drawContext.canvas.nativeCanvas,
+            contentAlignment,
+            progressFraction()
+        )
+    }
+}
+
+/**
+ * Generates an [AnimatedTextFontRegistry] to use within composition.
+ *
+ * Start and end of the animation is when the animatable is at 0f and 1f, respectively.
+ *
+ * @param startFontVariationSettings Font variation settings at the start of the animation
+ * @param endFontVariationSettings Font variation settings at the end of the animation
+ * @param textStyle Text style to be used for the animation
+ * @param startFontSize Font size at the start of the animation
+ * @param endFontSize Font size at the end of the animation
+ */
+@Composable
+@RequiresApi(31)
+fun rememberAnimatedTextFontRegistry(
+    startFontVariationSettings: FontVariation.Settings,
+    endFontVariationSettings: FontVariation.Settings,
+    textStyle: TextStyle = LocalTextStyle.current,
+    startFontSize: TextUnit = textStyle.fontSize,
+    endFontSize: TextUnit = textStyle.fontSize,
+): AnimatedTextFontRegistry {
+    // Convert current compose values to types we can use on Canvas
+    val density = LocalDensity.current
+    val fontFamilyResolver = LocalFontFamilyResolver.current
+    val contentColor = textStyle.color.takeOrElse { LocalContentColor.current }
+    return remember(
+        textStyle,
+        startFontVariationSettings.toString(),
+        endFontVariationSettings.toString(),
+        startFontSize,
+        endFontSize,
+        contentColor,
+        fontFamilyResolver,
+    ) {
+        AnimatedTextFontRegistry(
+            textStyle,
+            startFontVariationSettings,
+            endFontVariationSettings,
+            startFontSize,
+            endFontSize,
+            density,
+            fontFamilyResolver,
+            contentColor,
+        )
+    }
+}
+
+/**
+ * Generates fonts to be used by [AnimatedText] throughout the animation.
+ *
+ * Start and end of the animation is when the animatable is at 0f and 1f, respectively.
+ *
+ * @param startFontVariationSettings Font variation settings at the start of the animation
+ * @param endFontVariationSettings Font variation settings at the end of the animation
+ * @param textStyle Text style to be used for the animation
+ * @param startFontSize Font size at the start of the animation
+ * @param endFontSize Font size at the end of the animation
+ * @param density Current density, used to to convert font sizes
+ * @param contentColor Content color of the animated text
+ * @param fontFamilyResolver Current Resolver to use to resolve font families
+ * @param cacheSize Size of the cache used to store animated variable fonts, this can be increased
+ *   to improve animation performance if needed, but it also increases the memory usage.
+ */
+@RequiresApi(31)
+class AnimatedTextFontRegistry(
+    private val textStyle: TextStyle,
+    private val startFontVariationSettings: FontVariation.Settings,
+    private val endFontVariationSettings: FontVariation.Settings,
+    private val startFontSize: TextUnit,
+    private val endFontSize: TextUnit,
+    private val density: Density,
+    fontFamilyResolver: FontFamily.Resolver,
+    private val contentColor: Color = textStyle.color,
+    cacheSize: Int = AnimatedTextDefaults.CacheSize,
+) {
+    private val startFontSizePx = with(density) { startFontSize.toPx() }
+    private val endFontSizePx = with(density) { endFontSize.toPx() }
+
+    /**
+     * Returns the font at a certain [fraction] of the animation. [text] parameter is required to
+     * extract the initial font to draw the text animation.
+     */
+    internal fun getFont(text: String, fraction: Float): Font {
+        val snappedFraction =
+            floor(fraction / AnimatedTextDefaults.FractionStep) * AnimatedTextDefaults.FractionStep
+        return when (fraction) {
+            0f -> getStartFont(text)
+            1f -> getEndFont(text)
+            else -> {
+                val font =
+                    fontCache[fraction]
+                        ?: Font.Builder(getStartFont(text))
+                            .setFontVariationSettings(
+                                lerpFontVariationSettings(
+                                    startFontVariationSettings,
+                                    endFontVariationSettings,
+                                    snappedFraction
+                                )
+                            )
+                            .build()
+                fontCache.put(fraction, font)
+                font
+            }
+        }
+    }
+
+    /** Returns the font size at a certain point in the animation. */
+    internal fun getFontSize(fraction: Float): Float =
+        lerp(startFontSizePx, endFontSizePx, fraction)
+
+    /** Font cache for animation steps, between start font at 0f and end font at 1f */
+    private var fontCache = LruCache<Float, Font>(cacheSize)
+
+    /**
+     * Array to store current font variation axes, empty at the start.
+     *
+     * This helps reduce allocations during the draw phase.
+     */
+    private var currentAxes =
+        Array(startFontVariationSettings.settings.size) { FontVariationAxis("null", 0f) }
+
+    /** Font at the start of the animation. */
+    private var startFont: Font? = null
+
+    /** Font at the end of the animation. */
+    private var endFont: Font? = null
+
+    /** TextPaint to be used when drawing onto canvas, this is initially set to the start font. */
+    internal var startWorkingPaint: TextPaint
+
+    /** TextPaint that reflects how the end font should look. */
+    internal var endWorkingPaint: TextPaint
+
+    init {
+        startWorkingPaint = generateStartWorkingPaint(fontFamilyResolver)
+        endWorkingPaint = generateEndWorkingPaint(startWorkingPaint)
+    }
+
+    private fun generateStartWorkingPaint(fontFamilyResolver: FontFamily.Resolver): TextPaint {
+        val textPaint =
+            TextPaint().apply {
+                typeface =
+                    fontFamilyResolver
+                        .resolveAsTypeface(
+                            fontFamily = textStyle.fontFamily,
+                            textStyle.fontWeight ?: FontWeight.Normal,
+                            textStyle.fontStyle ?: FontStyle.Normal,
+                            textStyle.fontSynthesis ?: FontSynthesis.All,
+                        )
+                        .value
+                color = contentColor.toArgb()
+            }
+        textPaint.textSize = startFontSizePx
+        textPaint.setFontVariationSettings(
+            toFontVariationSettings(
+                lerpFontVariationSettings(startFontVariationSettings, endFontVariationSettings, 0f)
+            )
+        )
+        return textPaint
+    }
+
+    private fun generateEndWorkingPaint(startWorkingPaint: TextPaint): TextPaint {
+        val textPaint = TextPaint(startWorkingPaint)
+        textPaint.textSize = endFontSizePx
+        textPaint.setFontVariationSettings(
+            toFontVariationSettings(
+                lerpFontVariationSettings(startFontVariationSettings, endFontVariationSettings, 1f)
+            )
+        )
+        return textPaint
+    }
+
+    private fun lerpFontVariationSettings(
+        startFontVariationSettings: FontVariation.Settings,
+        endFontVariationSettings: FontVariation.Settings,
+        fraction: Float
+    ): Array<FontVariationAxis> {
+        startFontVariationSettings.settings.indices.forEach { startIndex ->
+            // Find the corresponding FontVariation.Setting in endFontVariationSettings
+            var endSetting = startFontVariationSettings.settings[startIndex]
+            for (endIndex in endFontVariationSettings.settings.indices) {
+                if (
+                    endFontVariationSettings.settings[endIndex].axisName ==
+                        startFontVariationSettings.settings[startIndex].axisName
+                ) {
+                    endSetting = endFontVariationSettings.settings[endIndex]
+                    break
+                }
+            }
+            currentAxes[startIndex] =
+                FontVariationAxis(
+                    startFontVariationSettings.settings[startIndex].axisName,
+                    lerp(
+                        startFontVariationSettings.settings[startIndex].toVariationValue(density),
+                        endSetting.toVariationValue(density),
+                        fraction
+                    )
+                )
+        }
+        return currentAxes
+    }
+
+    private fun getEndFont(text: String): Font {
+        if (endFont != null) {
+            return endFont as Font
+        }
+        endFont =
+            Font.Builder(getStartFont(text))
+                .setFontVariationSettings(
+                    lerpFontVariationSettings(
+                        startFontVariationSettings,
+                        endFontVariationSettings,
+                        1f
+                    )
+                )
+                .build()
+        return endFont as Font
+    }
+
+    private fun getStartFont(text: String): Font {
+        if (startFont != null) {
+            return startFont as Font
+        }
+        // This is required to generate font from the Typeface using Native APIs
+        // Maybe we can find another way without running shapeTextRun?
+        val glyphs =
+            TextRunShaper.shapeTextRun(
+                text,
+                0,
+                text.length,
+                0,
+                text.length,
+                0f,
+                0f,
+                false, // Correct layout direction isn't needed for generating the font
+                startWorkingPaint
+            )
+        startFont =
+            Font.Builder(glyphs.getFont(0))
+                .setFontVariationSettings(
+                    lerpFontVariationSettings(
+                        startFontVariationSettings,
+                        endFontVariationSettings,
+                        0f
+                    )
+                )
+                .build()
+        return startFont as Font
+    }
+}
+
+/** Defaults for AnimatedText. */
+object AnimatedTextDefaults {
+    /** Default font cache size to be used in AnimatedTextFontRegistry. */
+    const val CacheSize = 5
+
+    /**
+     * Default step size used to snap progress fractions. Progress fractions will be rounded down to
+     * a multiple of this to increase cache efficiency.
+     *
+     * 0.016f is chosen to divide a 1 second animation into 60 animation steps.
+     */
+    internal const val FractionStep = 0.016f
+}
+
+/**
+ * Animated text state.
+ *
+ * Generates and stores the fonts required to draw the animation.
+ *
+ * This should be generated using the [rememberAnimatedTextFontRegistry] method.
+ */
+@RequiresApi(31)
+internal class AnimatedTextState
+internal constructor(
+    private val animatedFontRegistry: AnimatedTextFontRegistry,
+    private val layoutDirection: LayoutDirection,
+    private val density: Density,
+) {
+    /**
+     * Required size for the canvas.
+     *
+     * It's a mutable state to make sure it triggers recomposition when the text changes.
+     */
+    internal var size: DpSize by mutableStateOf(DpSize.Zero)
+
+    /** Updates the text to draw. */
+    internal fun updateText(text: String) {
+        if (currentText == text) {
+            return
+        }
+        currentText = text
+        recalculateSizeAndPositions()
+    }
+
+    /** Draws the text onto a canvas. */
+    internal fun draw(canvas: Canvas, contentAlignment: Alignment, fraction: Float) {
+        // Nothing to draw, return early
+        if (size == DpSize.Zero) {
+            return
+        }
+        val widthPx = lerp(startWidthPx, endWidthPx, fraction)
+        val heightPx = lerp(startHeightPx, endHeightPx, fraction)
+        val offset =
+            contentAlignment.align(
+                IntSize(widthPx.roundToInt(), heightPx.roundToInt()),
+                intSize,
+                layoutDirection
+            )
+        canvas.translate(
+            offset.x.toFloat(),
+            offset.y.toFloat() +
+                heightPx / 2 +
+                lerp(startBaselineOffset, endBaselineOffset, fraction) / 2 +
+                lerp(startAscentPx, endAscentPx, fraction) / 4
+        )
+        val currentFont = animatedFontRegistry.getFont(currentText, fraction)
+        animatedFontRegistry.startWorkingPaint.textSize = animatedFontRegistry.getFontSize(fraction)
+        val startGlyphs = startPositionedGlyphs!!
+        val endGlyphs = endPositionedGlyphs!!
+        for (i in 0 until startGlyphs.glyphCount()) {
+            val glyphFont = startGlyphs.getFont(i)
+            canvas.drawGlyphs(
+                intArrayOf(startGlyphs.getGlyphId(i)),
+                0,
+                floatArrayOf(
+                    lerp(startGlyphs.getGlyphX(i), endGlyphs.getGlyphX(i), fraction),
+                    lerp(startGlyphs.getGlyphY(i), endGlyphs.getGlyphY(i), fraction)
+                ),
+                0,
+                1,
+                if (currentFont.file?.name != glyphFont.file?.name) {
+                    glyphFont
+                } else {
+                    currentFont
+                },
+                animatedFontRegistry.startWorkingPaint,
+            )
+        }
+    }
+
+    /**
+     * Same as [size], but in pixels, used to calculate content offset according to content
+     * alignment.
+     */
+    private var intSize = IntSize(0, 0)
+
+    /** Content height at the start of the animation, in px */
+    private var startHeightPx = 0f
+
+    /** Content height at the end of the animation, in px */
+    private var endHeightPx = 0f
+
+    /** Baseline offset at the start, used for content alignment. */
+    private var startBaselineOffset: Int = 0
+
+    /** Baseline offset at the end, used for content alignment. */
+    private var endBaselineOffset: Int = 0
+
+    /** Font ascent at the start of the animation, used for content alignment. */
+    private var startAscentPx = 0
+
+    /** Font ascent at the end of the animation, used for content alignment. */
+    private var endAscentPx = 0
+
+    /** Current text. */
+    private var currentText: String = ""
+
+    /** Content width at the start of the animation, in px */
+    private var startWidthPx = 0f
+
+    /** Content width at the end of the animation, in px */
+    private var endWidthPx = 0f
+
+    /** Positions of the glyphs at the start, used to calculate lerped glyph positions */
+    private var startPositionedGlyphs: PositionedGlyphs? = null
+
+    /** Positions of the glyphs at the end, used to calculate lerped glyph positions */
+    private var endPositionedGlyphs: PositionedGlyphs? = null
+
+    /**
+     * Calculates required canvas size to draw the text, font ascent and baseline offset for the
+     * font, positions for the glyphs at the start and the end of the animation.
+     */
+    private fun recalculateSizeAndPositions() {
+        with(density) {
+            intSize = IntSize(calculateMaxWidth().roundToInt(), calculateMaxHeight().roundToInt())
+            size = DpSize(intSize.width.toDp(), intSize.height.toDp())
+        }
+    }
+
+    private fun calculateMaxWidth(): Float {
+        if (currentText.isEmpty()) {
+            startWidthPx = 0f
+            startPositionedGlyphs = null
+            endWidthPx = 0f
+            endPositionedGlyphs = null
+            return 0f
+        }
+        startWidthPx = 0f
+        endWidthPx = 0f
+        startPositionedGlyphs =
+            TextRunShaper.shapeTextRun(
+                currentText,
+                0,
+                currentText.length,
+                0,
+                currentText.length,
+                0f,
+                0f,
+                layoutDirection == LayoutDirection.Rtl,
+                animatedFontRegistry.startWorkingPaint
+            )
+        startWidthPx = startPositionedGlyphs!!.advance
+        endPositionedGlyphs =
+            TextRunShaper.shapeTextRun(
+                currentText,
+                0,
+                currentText.length,
+                0,
+                currentText.length,
+                0f,
+                0f,
+                layoutDirection == LayoutDirection.Rtl,
+                animatedFontRegistry.endWorkingPaint
+            )
+        endWidthPx = endPositionedGlyphs!!.advance
+        return max(startWidthPx, endWidthPx)
+    }
+
+    private fun calculateMaxHeight(): Float {
+        if (currentText.isEmpty()) {
+            startHeightPx = 0f
+            startAscentPx = 0
+            startBaselineOffset = 0
+            endHeightPx = 0f
+            endAscentPx = 0
+            endBaselineOffset = 0
+            return 0f
+        }
+        val fontMetrics = FontMetrics()
+        val startFont = animatedFontRegistry.getFont(currentText, 0f)
+        val endFont = animatedFontRegistry.getFont(currentText, 1f)
+        startFont.getMetrics(animatedFontRegistry.startWorkingPaint, fontMetrics)
+        startHeightPx = fontMetrics.descent - fontMetrics.ascent
+        startAscentPx = fontMetrics.ascent.roundToInt()
+        startBaselineOffset = -fontMetrics.top.roundToInt()
+        endFont.getMetrics(animatedFontRegistry.endWorkingPaint, fontMetrics)
+        endHeightPx = fontMetrics.descent - fontMetrics.ascent
+        endAscentPx = fontMetrics.ascent.roundToInt()
+        endBaselineOffset = -fontMetrics.top.roundToInt()
+        return max(startHeightPx, endHeightPx)
+    }
+}
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/AppScaffold.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/AppScaffold.kt
new file mode 100644
index 0000000..5459b8b
--- /dev/null
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/AppScaffold.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.material3
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.ui.Modifier
+
+/**
+ * [AppScaffold] is one of the Wear Material3 scaffold components.
+ *
+ * The scaffold components [AppScaffold] and [ScreenScaffold] lay out the structure of a screen and
+ * coordinate transitions of the [ScrollIndicator] and [TimeText] components.
+ *
+ * [AppScaffold] allows static screen elements such as [TimeText] to remain visible during in-app
+ * transitions such as swipe-to-dismiss. It provides a slot for the main application content, which
+ * will usually be supplied by a navigation component such as SwipeDismissableNavHost.
+ *
+ * Example of using AppScaffold and ScreenScaffold:
+ *
+ * @sample androidx.wear.compose.material3.samples.ScaffoldSample
+ * @param modifier The modifier for the top level of the scaffold.
+ * @param timeText The default time (and potentially status message) to display at the top middle of
+ *   the screen in this app. When [AppScaffold] is used in combination with [ScreenScaffold], the
+ *   time text will be scrolled away and shown/hidden according to the scroll state of the screen.
+ * @param content The main content for this application.
+ */
+@Composable
+fun AppScaffold(
+    modifier: Modifier = Modifier,
+    timeText: @Composable () -> Unit = { TimeText { time() } },
+    content: @Composable BoxScope.() -> Unit,
+) =
+    CompositionLocalProvider(LocalScaffoldState provides ScaffoldState(timeText)) {
+        val scaffoldState = LocalScaffoldState.current
+        Box(modifier = modifier.fillMaxSize()) {
+            content()
+            scaffoldState.timeText()
+        }
+    }
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Button.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Button.kt
index dd09263..6b646f3 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Button.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Button.kt
@@ -1261,6 +1261,18 @@
      */
     val CompactButtonHeight = CompactButtonTokens.ContainerHeight
 
+    /** The height to be applied for an extra small [EdgeButton]. */
+    val EdgeButtonHeightExtraSmall = 46.dp
+
+    /** The height to be applied for a small [EdgeButton]. */
+    val EdgeButtonHeightSmall = 56.dp
+
+    /** The height to be applied for a medium [EdgeButton]. */
+    val EdgeButtonHeightMedium = 70.dp
+
+    /** The height to be applied for a large [EdgeButton]. */
+    val EdgeButtonHeightLarge = 96.dp
+
     /** The size of the icon when used inside a "[CompactButton]. */
     val SmallIconSize: Dp = CompactButtonTokens.IconSize
 
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/CheckboxButton.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/CheckboxButton.kt
index 38adf08..d48612d 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/CheckboxButton.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/CheckboxButton.kt
@@ -184,7 +184,7 @@
  * secondary label should be start aligned.
  *
  * A [SplitCheckboxButton] has two tappable areas, one tap area for the labels and another for the
- * toggle control. The [onContainerClick] listener will be associated with the main body of the
+ * checkbox. The [onContainerClick] listener will be associated with the main body of the
  * [SplitCheckboxButton] and the [onCheckedChange] listener associated with the checkbox area only.
  *
  * Samples: Example of a SplitCheckboxButton:
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ColorScheme.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ColorScheme.kt
index a2b0b43..1d4937b 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ColorScheme.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ColorScheme.kt
@@ -235,8 +235,8 @@
     internal var defaultOutlinedCardColorsCached: CardColors? = null
 
     // Toggle Button
-    internal var defaultToggleButtonColorsCached: ToggleButtonColors? = null
-    internal var defaultSplitToggleButtonColorsCached: SplitToggleButtonColors? = null
+    internal var defaultSwitchButtonColorsCached: SwitchButtonColors? = null
+    internal var defaultSplitSwitchButtonColorsCached: SplitSwitchButtonColors? = null
 
     // Checkbox Button
     internal var defaultCheckboxButtonColorsCached: CheckboxButtonColors? = null
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/CurvedText.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/CurvedText.kt
index f8c386b..841c464 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/CurvedText.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/CurvedText.kt
@@ -111,7 +111,7 @@
         angularDirection = angularDirection,
         overflow = overflow
     ) {
-        val baseStyle = style ?: CurvedTextStyle(LocalTextStyle.current)
+        val baseStyle = style ?: CurvedTextStyle(MaterialTheme.typography.arcMedium)
         val textColor =
             color.takeOrElse { baseStyle.color.takeOrElse { LocalContentColor.current } }
         baseStyle.merge(
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/EdgeButton.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/EdgeButton.kt
new file mode 100644
index 0000000..c95871c
--- /dev/null
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/EdgeButton.kt
@@ -0,0 +1,443 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.material3
+
+import androidx.compose.animation.core.CubicBezierEasing
+import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.border
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.interaction.Interaction
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.RowScope
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.requiredSizeIn
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.MutableState
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.draw.drawWithContent
+import androidx.compose.ui.draw.paint
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.geometry.Rect
+import androidx.compose.ui.geometry.Size
+import androidx.compose.ui.graphics.BlendMode
+import androidx.compose.ui.graphics.Brush
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.CompositingStrategy
+import androidx.compose.ui.graphics.Outline
+import androidx.compose.ui.graphics.Path
+import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.graphics.TransformOrigin
+import androidx.compose.ui.graphics.graphicsLayer
+import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.layout.Measurable
+import androidx.compose.ui.layout.MeasureResult
+import androidx.compose.ui.layout.MeasureScope
+import androidx.compose.ui.layout.layout
+import androidx.compose.ui.node.LayoutModifierNode
+import androidx.compose.ui.node.ModifierNodeElement
+import androidx.compose.ui.platform.InspectorInfo
+import androidx.compose.ui.platform.LocalConfiguration
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.semantics.Role
+import androidx.compose.ui.unit.Constraints
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.DpSize
+import androidx.compose.ui.unit.IntOffset
+import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.unit.LayoutDirection
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.toSize
+import androidx.compose.ui.util.lerp
+import kotlin.math.roundToInt
+import kotlin.math.sqrt
+
+/**
+ * Wear Material3 [EdgeButton] that offers a single slot to take any content.
+ *
+ * The [EdgeButton] has a special shape designed for the bottom of the screen, as it almost follows
+ * the screen's curvature, so it should be allowed to take the full width and touch the bottom of
+ * the screen. It has 4 standard sizes, taking 1 line of text for the extra small, 2 for small and
+ * medium, and 3 for the large. See the standard values on [ButtonDefaults], and specify it using
+ * the buttonSize parameter. Optionally, a single icon can be used instead of the text.
+ *
+ * This button represents the most important action on the screen, and must take the whole width of
+ * the screen as well as being anchored to the screen bottom.
+ *
+ * [EdgeButton] takes the [ButtonDefaults.buttonColors] color scheme by default, with colored
+ * background, contrasting content color and no border. This is a high-emphasis button for the
+ * primary, most important or most common action on a screen. Other possible colors for different
+ * levels of emphasis are: [FilledTonalButton] which defaults to
+ * [ButtonDefaults.filledTonalButtonColors] and [OutlinedButton] which defaults to
+ * [ButtonDefaults.outlinedButtonColors]
+ *
+ * [EdgeButton] is not intended to be used with an image background.
+ *
+ * Edge button can be enabled or disabled. A disabled button will not respond to click events.
+ *
+ * Example of an [EdgeButton]:
+ *
+ * @sample androidx.wear.compose.material3.samples.EdgeButtonSample
+ * @param onClick Will be called when the user clicks the button
+ * @param modifier Modifier to be applied to the button. When animating the button to appear/
+ *   disappear from the screen, a Modifier.height can be used to change the height of the component,
+ *   but that won't change the space available for the content (though it may be scaled)
+ * @param buttonHeight Defines the base size of the button, see the 4 standard sizes specified in
+ *   [ButtonDefaults]. This is used to determine the size constraints passed on to the content, and
+ *   the size of the edge button if no height Modifier is specified. Note that if a height Modifier
+ *   is specified for the EdgeButton, that will determine the size of the container, and the content
+ *   may be scaled and or have alpha applied to fit. The default is
+ *   [ButtonDefaults.EdgeButtonHeightSmall]
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not be
+ *   clickable
+ * @param colors [ButtonColors] that will be used to resolve the background and content color for
+ *   this button in different states. See [ButtonDefaults.buttonColors].
+ * @param border Optional [BorderStroke] that will be used to resolve the border for this button in
+ *   different states.
+ * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
+ *   emitting [Interaction]s for this button. You can use this to change the button's appearance or
+ *   preview the button in different states. Note that if `null` is provided, interactions will
+ *   still happen internally.
+ * @param content Slot for composable body content displayed on the Button. Either an Icon or Text.
+ */
+// TODO(b/261838497) Add Material3 UX guidance links
+@Composable
+fun EdgeButton(
+    onClick: () -> Unit,
+    modifier: Modifier = Modifier,
+    buttonHeight: Dp = ButtonDefaults.EdgeButtonHeightSmall,
+    enabled: Boolean = true,
+    colors: ButtonColors = ButtonDefaults.buttonColors(),
+    border: BorderStroke? = null,
+    interactionSource: MutableInteractionSource? = null,
+    content: @Composable RowScope.() -> Unit,
+) {
+    val easing = CubicBezierEasing(0.25f, 0f, 0.75f, 1.0f)
+
+    val density = LocalDensity.current
+    val screenWidthDp = LocalConfiguration.current.screenWidthDp.dp
+
+    val contentShapeHelper =
+        remember(buttonHeight) {
+            ShapeHelper(density).apply {
+                // Compute the inner size using only the screen size and the buttonSize parameter
+                val size = with(density) { DpSize(screenWidthDp, buttonHeight).toSize() }
+                update(size)
+            }
+        }
+
+    val containerShapeHelper = ShapeHelper(LocalDensity.current)
+    val shape = EdgeButtonShape(containerShapeHelper)
+
+    val containerFadeStartPx = with(LocalDensity.current) { CONTAINER_FADE_START_DP.toPx() }
+    val borderModifier =
+        if (border != null) Modifier.border(border = border, shape = shape) else Modifier
+    Row(
+        horizontalArrangement = Arrangement.Center,
+        modifier =
+            modifier
+                .padding(bottom = BOTTOM_PADDING)
+                .layout { measurable, constraints ->
+                    // Compute the actual size of the button, and save it for later.
+                    // We take the max width available, and the height is determined by the
+                    // buttonSize
+                    // coerced to the constraints at this point.
+                    // We behave similar to .fillMaxWidth().height(buttonSize)
+                    val buttonWidthPx =
+                        if (constraints.hasBoundedWidth) {
+                            constraints.maxWidth
+                        } else {
+                            screenWidthDp.roundToPx()
+                        }
+                    val buttonHeightPx = with(density) { buttonHeight.roundToPx() }
+                    val size =
+                        IntSize(
+                            buttonWidthPx,
+                            buttonHeightPx.coerceIn(constraints.minHeight, constraints.maxHeight)
+                        )
+                    containerShapeHelper.update(size.toSize())
+
+                    val placeable =
+                        measurable.measure(
+                            Constraints(size.width, size.width, size.height, size.height)
+                        )
+                    layout(size.width, size.height) { placeable.place(0, 0) }
+                }
+                .graphicsLayer {
+                    // Container fades when button height goes from 18dp to 0dp
+                    val height = (containerShapeHelper.lastSize.value?.height ?: 0f)
+                    alpha = easing.transform(height / containerFadeStartPx).coerceIn(0f, 1f)
+                }
+                .then(borderModifier)
+                .clip(shape = shape)
+                .paint(
+                    painter = colors.containerPainter(enabled = enabled),
+                    contentScale = ContentScale.Crop
+                )
+                .graphicsLayer {
+                    // Compose the content in an offscreen layer, so we can apply the gradient mask
+                    // to
+                    // it.
+                    compositingStrategy = CompositingStrategy.Offscreen
+                }
+                .drawWithContent {
+                    drawContent()
+                    // Draw the gradient.
+                    // We use the max dimension (width) as a proxy for screen size.
+                    val r = size.maxDimension / 2f
+                    val center = Offset(r, size.height - r)
+                    drawRect(
+                        Brush.radialGradient(
+                            0.875f to Color.White,
+                            1.0f to Color.Transparent,
+                            center = center,
+                            radius = r
+                        ),
+                        blendMode = BlendMode.Modulate
+                    )
+                }
+                .clickable(
+                    enabled = enabled,
+                    onClick = onClick,
+                    role = Role.Button,
+                    indication = ripple(),
+                    interactionSource = interactionSource,
+                )
+                .sizeAndOffset { containerShapeHelper.contentWindow }
+                .scaleAndAlignContent()
+                // Limit the content size to the expected box for the button size.
+                .requiredSizeIn(
+                    maxWidth = contentShapeHelper.contentWidthDp(),
+                    maxHeight = contentShapeHelper.contentHeightDp()
+                ),
+        content =
+            provideScopeContent(
+                colors.contentColor(enabled = enabled),
+                MaterialTheme.typography.labelMedium,
+                content
+            )
+    )
+}
+
+private fun Modifier.sizeAndOffset(rectFn: (Constraints) -> Rect) =
+    layout { measurable, constraints ->
+        val rect = rectFn(constraints)
+        val placeable =
+            measurable.measure(
+                Constraints(
+                    rect.width.roundToInt(),
+                    rect.width.roundToInt(),
+                    rect.height.roundToInt(),
+                    rect.height.roundToInt()
+                )
+            )
+        val wrapperWidth = placeable.width.coerceIn(constraints.minWidth, constraints.maxWidth)
+        val wrapperHeight = placeable.height.coerceIn(constraints.minHeight, constraints.maxHeight)
+
+        layout(wrapperWidth, wrapperHeight) {
+            placeable.placeWithLayer(0, 0) {
+                translationX = rect.left
+                translationY = rect.top
+            }
+        }
+    }
+
+internal class ShapeHelper(private val density: Density) {
+    private val extraSmallHeightPx =
+        with(density) { ButtonDefaults.EdgeButtonHeightExtraSmall.toPx() }
+    private val bottomPaddingPx = with(density) { BOTTOM_PADDING.toPx() }
+    private val extraSmallEllipsisHeightPx = with(density) { EXTRA_SMALL_ELLIPSIS_HEIGHT.toPx() }
+    private val targetSidePadding = with(density) { TARGET_SIDE_PADDING.toPx() }
+
+    internal val lastSize: MutableState<Size?> = mutableStateOf(null)
+    internal var sidePadding: Float = 0f
+    internal var finalFadeProgress: Float = 0f
+    internal var ellipsisHeight: Float = 0f
+    internal var r: Float = 0f
+
+    internal var contentWindow: Rect = Rect(0f, 0f, 0f, 0f)
+
+    fun contentWidthDp() = with(density) { contentWindow.width.toDp() }
+
+    fun contentHeightDp() = with(density) { contentWindow.height.toDp() }
+
+    fun update(size: Size) {
+        lastSize.value = size
+
+        finalFadeProgress = (1f - size.height / extraSmallHeightPx).coerceAtLeast(0f)
+        ellipsisHeight =
+            lerp(
+                extraSmallEllipsisHeightPx +
+                    (size.height - extraSmallHeightPx) * BUTTON_TO_ELLIPSIS_RATIO,
+                size.height,
+                finalFadeProgress
+            )
+
+        val localHalfWidth =
+            sqrt(sqr(size.width / 2) - sqr(size.width / 2 - bottomPaddingPx - ellipsisHeight / 2))
+        sidePadding = size.width / 2 - localHalfWidth + targetSidePadding
+
+        r = size.height - ellipsisHeight / 2
+
+        contentWindow = Rect(sidePadding, 0f, size.width - sidePadding, size.height).inset(r, 0f)
+    }
+}
+
+internal fun Rect.size() = Size(width, height)
+
+internal fun Rect.inset(h: Float, v: Float): Rect {
+    // Ensure we never have negative sizes.
+    val cx = (left + right) / 2
+    val cy = (top + bottom) / 2
+    val sx2 = (width / 2 - h).coerceAtLeast(0f)
+    val sy2 = (height / 2 - v).coerceAtLeast(0f)
+    return Rect(cx - sx2, cy - sy2, cx + sx2, cy + sy2)
+}
+
+internal class EdgeButtonShape(private val helper: ShapeHelper) : Shape {
+    override fun createOutline(
+        size: Size,
+        layoutDirection: LayoutDirection,
+        density: Density
+    ): Outline {
+        val path =
+            Path().apply {
+                with(helper) {
+                    // Top Side - Rounded Rect
+                    moveTo(sidePadding, r)
+                    quarterEllipsis(Offset(sidePadding + r, r), r, r, 180f)
+                    lineTo(size.width - sidePadding - r, 0f)
+                    quarterEllipsis(Offset(size.width - sidePadding - r, r), r, r, 270f)
+
+                    // Bottom side - Ellipsis morphing to round rect when very small.
+                    val ellipsisRadiusX =
+                        lerp((size.width - 2 * sidePadding) / 2, r, finalFadeProgress)
+                    val ellipsisRadiusY = ellipsisHeight / 2
+                    quarterEllipsis(
+                        Offset(
+                            size.width - sidePadding - ellipsisRadiusX,
+                            size.height - ellipsisRadiusY
+                        ),
+                        ellipsisRadiusX,
+                        ellipsisRadiusY,
+                        0f
+                    )
+                    lineTo(sidePadding + ellipsisRadiusX, size.height)
+                    quarterEllipsis(
+                        Offset(sidePadding + ellipsisRadiusX, size.height - ellipsisRadiusY),
+                        ellipsisRadiusX,
+                        ellipsisRadiusY,
+                        90f
+                    )
+                }
+            }
+
+        return Outline.Generic(path)
+    }
+}
+
+private fun Path.quarterEllipsis(
+    center: Offset,
+    radiusX: Float,
+    radiusY: Float,
+    startAngle: Float
+) {
+    arcTo(
+        Rect(center.x - radiusX, center.y - radiusY, center.x + radiusX, center.y + radiusY),
+        startAngle,
+        sweepAngleDegrees = 90f,
+        forceMoveTo = false
+    )
+}
+
+private fun sqr(x: Float) = x * x
+
+// Scales the content if it doesn't fit horizontally, horizontally center if there is room.
+// Vertically centers the content if there is room, otherwise aligns to the top.
+private fun Modifier.scaleAndAlignContent() = this.then(ScaleAndAlignContentElement())
+
+private class ScaleAndAlignContentElement : ModifierNodeElement<ScaleAndAlignContentNode>() {
+    override fun create(): ScaleAndAlignContentNode = ScaleAndAlignContentNode()
+
+    override fun update(node: ScaleAndAlignContentNode) {}
+
+    override fun InspectorInfo.inspectableProperties() {
+        name = "ScaleAndAlignContentElement"
+    }
+
+    // All instances are equivalent
+    override fun equals(other: Any?) = other is ScaleAndAlignContentElement
+
+    override fun hashCode() = 42
+}
+
+private class ScaleAndAlignContentNode : LayoutModifierNode, Modifier.Node() {
+    override fun MeasureScope.measure(
+        measurable: Measurable,
+        constraints: Constraints
+    ): MeasureResult {
+        val placeable = measurable.measure(Constraints())
+
+        val wrapperWidth = placeable.width.coerceIn(constraints.minWidth, constraints.maxWidth)
+        val wrapperHeight = placeable.height.coerceIn(constraints.minHeight, constraints.maxHeight)
+
+        val scale = (wrapperWidth.toFloat() / placeable.width.coerceAtLeast(1)).coerceAtMost(1f)
+
+        return layout(wrapperWidth, wrapperHeight) {
+            // If there is enough vertical space, we align like 'Center', otherwise like 'TopCenter'
+            val position =
+                IntOffset(
+                    x = (wrapperWidth - placeable.width) / 2, // Always center horizontally
+                    y =
+                        if (placeable.height * scale > constraints.maxHeight) {
+                            // Top
+                            0
+                        } else {
+                            // Center vertically too.
+                            ((wrapperHeight - placeable.height * scale) / 2).roundToInt()
+                        }
+                )
+            placeable.placeWithLayer(position) {
+                scaleX = scale
+                scaleY = scale
+                transformOrigin = TransformOrigin(0.5f, 0f)
+            }
+        }
+    }
+}
+
+// At which button height the container starts fading away. Fade ends at 0.dp
+private val CONTAINER_FADE_START_DP = 18.dp
+
+// How tall the ellipsis is for the extra small button.
+// Edge buttons are drawn as half a rounded rectangle on top of half an ellipsis.
+private val EXTRA_SMALL_ELLIPSIS_HEIGHT = 58.dp
+
+// How much the ellipsis grows as the button height grows
+private const val BUTTON_TO_ELLIPSIS_RATIO = 1.42f
+
+// Distance from the leftmost/rightmost point in the button to the edge of the screen, in a
+// straight line parallel to the x axis.
+private val TARGET_SIDE_PADDING = 20.dp
+
+// Padding between the Edge Button and the bottom of the screen
+private val BOTTOM_PADDING = 3.dp
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/HorizontalPageIndicator.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/HorizontalPageIndicator.kt
index 11733c1..f755f64 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/HorizontalPageIndicator.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/HorizontalPageIndicator.kt
@@ -205,9 +205,7 @@
 internal object PageIndicatorDefaults {
 
     val MaxNumberOfIndicators = 6
-
-    // TODO: replace with scaffold constant when it is available
-    internal val edgePadding = 2.dp
+    internal val edgePadding = ScaffoldDefaults.edgePadding
 }
 
 @Composable
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ProgressIndicator.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ProgressIndicator.kt
index 2b9c252..cdfab19 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ProgressIndicator.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ProgressIndicator.kt
@@ -31,9 +31,7 @@
 import androidx.compose.ui.graphics.drawscope.DrawScope
 import androidx.compose.ui.graphics.drawscope.Stroke
 import androidx.compose.ui.graphics.isSpecified
-import androidx.compose.ui.semantics.ProgressBarRangeInfo
-import androidx.compose.ui.semantics.progressBarRangeInfo
-import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.semantics.clearAndSetSemantics
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
 import androidx.wear.compose.material3.ProgressIndicatorDefaults.StartAngle
@@ -93,9 +91,7 @@
     // Using Spacer.drawWithCache to optimize the stroke allocations.
     Spacer(
         modifier
-            .semantics(mergeDescendants = true) {
-                progressBarRangeInfo = ProgressBarRangeInfo(coercedProgress(), 0f..1f)
-            }
+            .clearAndSetSemantics {}
             .fillMaxSize()
             .focusable()
             .drawWithCache {
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Scaffold.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Scaffold.kt
new file mode 100644
index 0000000..3d0b70e
--- /dev/null
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Scaffold.kt
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.material3
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.MutableState
+import androidx.compose.runtime.compositionLocalOf
+import androidx.compose.runtime.mutableStateListOf
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.util.fastForEach
+import androidx.wear.compose.foundation.ScrollInfoProvider
+import kotlinx.coroutines.delay
+
+/** Contains the default values used for Scaffold components. */
+internal object ScaffoldDefaults {
+    internal val edgePadding = 2.dp
+}
+
+internal class ScaffoldState(private val appTimeText: (@Composable (() -> Unit))? = null) {
+    fun removeScreen(key: Any) {
+        screenContent.removeIf { it.key === key }
+    }
+
+    fun addScreen(
+        key: Any,
+        timeText: @Composable (() -> Unit)?,
+        scrollInfoProvider: ScrollInfoProvider? = null
+    ) {
+        screenContent.add(ScreenContent(key, scrollInfoProvider, timeText))
+    }
+
+    val timeText: @Composable (() -> Unit)
+        get() = {
+            val (screenContent, timeText) = currentContent()
+            Box(
+                modifier =
+                    screenContent?.scrollInfoProvider?.let {
+                        Modifier.fillMaxSize().scrollAway(it) { screenStage.value }
+                    } ?: Modifier
+            ) {
+                timeText()
+            }
+        }
+
+    internal val screenStage: MutableState<ScreenStage> = mutableStateOf(ScreenStage.New)
+
+    @Composable
+    internal fun UpdateIdlingDetectorIfNeeded() {
+        val scrollInfoProvider = currentContent().first?.scrollInfoProvider
+        LaunchedEffect(scrollInfoProvider) { screenStage.value = ScreenStage.New }
+        if (scrollInfoProvider?.isScrollInProgress == true) {
+            screenStage.value = ScreenStage.Scrolling
+        } else {
+            LaunchedEffect(Unit) {
+                // Entering the idle state will show the Time text (if it's hidden) AND hide the
+                // scroll indicator.
+                delay(IDLE_DELAY)
+                screenStage.value = ScreenStage.Idle
+            }
+        }
+    }
+
+    internal data class ScreenContent(
+        val key: Any,
+        val scrollInfoProvider: ScrollInfoProvider? = null,
+        val timeText: (@Composable () -> Unit)? = null,
+    )
+
+    private fun currentContent(): Pair<ScreenContent?, @Composable (() -> Unit)> {
+        var resultTimeText: @Composable (() -> Unit)? = null
+        var resultContent: ScreenContent? = null
+        screenContent.fastForEach {
+            if (it.timeText != null) {
+                resultTimeText = it.timeText
+            }
+            if (it.scrollInfoProvider != null) {
+                resultContent = it
+            }
+        }
+        return resultContent to (resultTimeText ?: appTimeText ?: {})
+    }
+
+    private val screenContent = mutableStateListOf<ScreenContent>()
+}
+
+internal val LocalScaffoldState = compositionLocalOf { ScaffoldState() }
+
+private const val IDLE_DELAY = 2500L
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ScreenScaffold.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ScreenScaffold.kt
new file mode 100644
index 0000000..2c0e3d9
--- /dev/null
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ScreenScaffold.kt
@@ -0,0 +1,264 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.material3
+
+import androidx.compose.animation.core.AnimationSpec
+import androidx.compose.animation.core.Spring
+import androidx.compose.animation.core.animate
+import androidx.compose.animation.core.spring
+import androidx.compose.foundation.ScrollState
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.lazy.LazyListState
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.key
+import androidx.compose.runtime.mutableFloatStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.snapshotFlow
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.graphicsLayer
+import androidx.wear.compose.foundation.ExperimentalWearFoundationApi
+import androidx.wear.compose.foundation.OnFocusChange
+import androidx.wear.compose.foundation.ScrollInfoProvider
+import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
+import androidx.wear.compose.foundation.lazy.ScalingLazyListState
+import androidx.wear.compose.foundation.toScrollAwayInfoProvider
+import kotlinx.coroutines.flow.collectLatest
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.launch
+
+/**
+ * [ScreenScaffold] is one of the Wear Material3 scaffold components.
+ *
+ * The scaffold components [AppScaffold] and [ScreenScaffold] lay out the structure of a screen and
+ * coordinate transitions of the [ScrollIndicator] and [TimeText] components.
+ *
+ * [ScreenScaffold] displays the [ScrollIndicator] at the center-end of the screen by default and
+ * coordinates showing/hiding [TimeText] and [ScrollIndicator] according to [scrollState].
+ *
+ * Example of using AppScaffold and ScreenScaffold:
+ *
+ * @sample androidx.wear.compose.material3.samples.ScaffoldSample
+ * @param scrollState The scroll state for [ScalingLazyColumn], used to drive screen transitions
+ *   such as [TimeText] scroll away and showing/hiding [ScrollIndicator].
+ * @param modifier The modifier for the screen scaffold.
+ * @param timeText Time text (both time and potentially status message) for this screen, if
+ *   different to the time text at the [AppScaffold] level. When null, the time text from the
+ *   [AppScaffold] is displayed for this screen.
+ * @param scrollIndicator The [ScrollIndicator] to display on this screen, which is expected to be
+ *   aligned to Center-End. It is recommended to use the Material3 [ScrollIndicator] which is
+ *   provided by default. No scroll indicator is displayed if null is passed.
+ * @param content The body content for this screen.
+ */
+@Composable
+fun ScreenScaffold(
+    scrollState: ScalingLazyListState,
+    modifier: Modifier = Modifier,
+    timeText: (@Composable () -> Unit)? = null,
+    scrollIndicator: (@Composable BoxScope.() -> Unit)? = {
+        ScrollIndicator(scrollState, modifier = Modifier.align(Alignment.CenterEnd))
+    },
+    content: @Composable BoxScope.() -> Unit,
+) =
+    ScreenScaffold(
+        modifier,
+        timeText,
+        scrollState.toScrollAwayInfoProvider(),
+        scrollIndicator,
+        content
+    )
+
+/**
+ * [ScreenScaffold] is one of the Wear Material3 scaffold components.
+ *
+ * The scaffold components [AppScaffold] and [ScreenScaffold] lay out the structure of a screen and
+ * coordinate transitions of the [ScrollIndicator] and [TimeText] components.
+ *
+ * [ScreenScaffold] displays the [ScrollIndicator] at the center-end of the screen by default and
+ * coordinates showing/hiding [TimeText] and [ScrollIndicator] according to [scrollState].
+ *
+ * Example of using AppScaffold and ScreenScaffold:
+ *
+ * @sample androidx.wear.compose.material3.samples.ScaffoldSample
+ * @param scrollState The scroll state for LazyColumn, used to drive screen transitions such as
+ *   [TimeText] scroll away and showing/hiding [ScrollIndicator].
+ * @param modifier The modifier for the screen scaffold.
+ * @param timeText Time text (both time and potentially status message) for this screen, if
+ *   different to the time text at the [AppScaffold] level. When null, the time text from the
+ *   [AppScaffold] is displayed for this screen.
+ * @param scrollIndicator The [ScrollIndicator] to display on this screen, which is expected to be
+ *   aligned to Center-End. It is recommended to use the Material3 [ScrollIndicator] which is
+ *   provided by default. No scroll indicator is displayed if null is passed.
+ * @param content The body content for this screen.
+ */
+@Composable
+fun ScreenScaffold(
+    scrollState: LazyListState,
+    modifier: Modifier = Modifier,
+    timeText: (@Composable () -> Unit)? = null,
+    scrollIndicator: (@Composable BoxScope.() -> Unit)? = {
+        ScrollIndicator(scrollState, modifier = Modifier.align(Alignment.CenterEnd))
+    },
+    content: @Composable BoxScope.() -> Unit,
+) =
+    ScreenScaffold(
+        modifier,
+        timeText,
+        scrollState.toScrollAwayInfoProvider(),
+        scrollIndicator,
+        content
+    )
+
+/**
+ * [ScreenScaffold] is one of the Wear Material3 scaffold components.
+ *
+ * The scaffold components [AppScaffold] and [ScreenScaffold] lay out the structure of a screen and
+ * coordinate transitions of the [ScrollIndicator] and [TimeText] components.
+ *
+ * [ScreenScaffold] displays the [ScrollIndicator] at the center-end of the screen by default and
+ * coordinates showing/hiding [TimeText] and [ScrollIndicator] according to [scrollState].
+ *
+ * Example of using AppScaffold and ScreenScaffold:
+ *
+ * @sample androidx.wear.compose.material3.samples.ScaffoldSample
+ * @param scrollState The scroll state for a Column, used to drive screen transitions such as
+ *   [TimeText] scroll away and showing/hiding [ScrollIndicator].
+ * @param modifier The modifier for the screen scaffold.
+ * @param timeText Time text (both time and potentially status message) for this screen, if
+ *   different to the time text at the [AppScaffold] level. When null, the time text from the
+ *   [AppScaffold] is displayed for this screen.
+ * @param scrollIndicator The [ScrollIndicator] to display on this screen, which is expected to be
+ *   aligned to Center-End. It is recommended to use the Material3 [ScrollIndicator] which is
+ *   provided by default. No scroll indicator is displayed if null is passed.
+ * @param content The body content for this screen.
+ */
+@Composable
+fun ScreenScaffold(
+    scrollState: ScrollState,
+    modifier: Modifier = Modifier,
+    timeText: (@Composable () -> Unit)? = null,
+    scrollIndicator: (@Composable BoxScope.() -> Unit)? = {
+        ScrollIndicator(scrollState, modifier = Modifier.align(Alignment.CenterEnd))
+    },
+    content: @Composable BoxScope.() -> Unit,
+) =
+    ScreenScaffold(
+        modifier,
+        timeText,
+        scrollState.toScrollAwayInfoProvider(),
+        scrollIndicator,
+        content
+    )
+
+/**
+ * [ScreenScaffold] is one of the Wear Material3 scaffold components.
+ *
+ * The scaffold components [AppScaffold] and [ScreenScaffold] lay out the structure of a screen and
+ * coordinate transitions of the [ScrollIndicator] and [TimeText] components.
+ *
+ * [ScreenScaffold] displays the [ScrollIndicator] at the center-end of the screen by default and
+ * coordinates showing/hiding [TimeText] and [ScrollIndicator] according to [scrollInfoProvider].
+ *
+ * Example of using AppScaffold and ScreenScaffold:
+ *
+ * @sample androidx.wear.compose.material3.samples.ScaffoldSample
+ * @param modifier The modifier for the screen scaffold.
+ * @param timeText Time text (both time and potentially status message) for this screen, if
+ *   different to the time text at the [AppScaffold] level. When null, the time text from the
+ *   [AppScaffold] is displayed for this screen.
+ * @param scrollInfoProvider Provider for scroll information used to scroll away screen elements
+ *   such as [TimeText] and coordinate showing/hiding the [ScrollIndicator].
+ * @param scrollIndicator The [ScrollIndicator] to display on this screen, which is expected to be
+ *   aligned to Center-End. It is recommended to use the Material3 [ScrollIndicator] which is
+ *   provided by default. No scroll indicator is displayed if null is passed.
+ * @param content The body content for this screen.
+ */
+@OptIn(ExperimentalWearFoundationApi::class)
+@Composable
+fun ScreenScaffold(
+    modifier: Modifier = Modifier,
+    timeText: (@Composable () -> Unit)? = null,
+    scrollInfoProvider: ScrollInfoProvider? = null,
+    scrollIndicator: (@Composable BoxScope.() -> Unit)? = null,
+    content: @Composable BoxScope.() -> Unit,
+) {
+    val scaffoldState = LocalScaffoldState.current
+    val key = remember { Any() }
+
+    key(scrollInfoProvider) {
+        DisposableEffect(key) { onDispose { scaffoldState.removeScreen(key) } }
+
+        OnFocusChange { focused ->
+            if (focused) {
+                scaffoldState.addScreen(key, timeText, scrollInfoProvider)
+            } else {
+                scaffoldState.removeScreen(key)
+            }
+        }
+    }
+
+    scaffoldState.UpdateIdlingDetectorIfNeeded()
+
+    Box(modifier = modifier.fillMaxSize()) {
+        content()
+        scrollInfoProvider?.let {
+            AnimatedScrollIndicator(
+                scrollInfoProvider = scrollInfoProvider,
+                content = scrollIndicator,
+                stage = { scaffoldState.screenStage.value }
+            )
+        } ?: scrollIndicator?.let { it() }
+    }
+}
+
+@Composable
+private fun AnimatedScrollIndicator(
+    scrollInfoProvider: ScrollInfoProvider,
+    stage: () -> ScreenStage,
+    content: @Composable (BoxScope.() -> Unit)? = null
+) {
+    // Skip if no scroll indicator provided
+    content?.let { scrollIndicator ->
+        val alphaValue = remember { mutableFloatStateOf(0f) }
+        val animationSpec: AnimationSpec<Float> = spring(stiffness = Spring.StiffnessMediumLow)
+        LaunchedEffect(scrollInfoProvider, scrollIndicator) {
+            launch {
+                snapshotFlow {
+                        if (stage() != ScreenStage.Idle && scrollInfoProvider.isScrollable) 1f
+                        else 0f
+                    }
+                    .distinctUntilChanged()
+                    .collectLatest { targetValue ->
+                        animate(
+                            alphaValue.floatValue,
+                            targetValue,
+                            animationSpec = animationSpec
+                        ) { value, _ ->
+                            alphaValue.floatValue = value
+                        }
+                    }
+            }
+        }
+        Box(modifier = Modifier.fillMaxSize().graphicsLayer { alpha = alphaValue.floatValue }) {
+            scrollIndicator()
+        }
+    }
+}
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ScrollAway.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ScrollAway.kt
new file mode 100644
index 0000000..b561f85
--- /dev/null
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ScrollAway.kt
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.material3
+
+import android.util.Log
+import androidx.compose.animation.core.Animatable
+import androidx.compose.animation.core.AnimationVector1D
+import androidx.compose.animation.core.tween
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.TransformOrigin
+import androidx.compose.ui.layout.Measurable
+import androidx.compose.ui.layout.MeasureResult
+import androidx.compose.ui.layout.MeasureScope
+import androidx.compose.ui.node.LayoutModifierNode
+import androidx.compose.ui.node.ModifierNodeElement
+import androidx.compose.ui.platform.InspectorInfo
+import androidx.compose.ui.unit.Constraints
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.util.lerp
+import androidx.wear.compose.foundation.ScrollInfoProvider
+import androidx.wear.compose.foundation.lazy.ScalingLazyListState
+import androidx.wear.compose.foundation.toScrollAwayInfoProvider
+import androidx.wear.compose.material3.tokens.MotionTokens
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
+
+/**
+ * Scroll an item vertically in/out of view based on scroll state provided by a scrolling list.
+ * Typically used to scroll a [TimeText] item out of view as the user starts to scroll a vertically
+ * scrollable list of items upwards and bring additional items into view.
+ *
+ * Example of using ScrollAway directly (in practice, it is recommended to use [AppScaffold] and
+ * [ScreenScaffold] to provide the correct scroll away behavior by default):
+ *
+ * @sample androidx.wear.compose.material3.samples.ScrollAwaySample
+ * @param scrollInfoProvider Used as the basis for the scroll-away implementation, based on the
+ *   state of the scrollable container. See [toScrollAwayInfoProvider] extension methods for
+ *   creating a ScrollAwayInfoProvider from common lists such as [ScalingLazyListState].
+ * @param screenStage Function that returns the screen stage of the active screen. Scrolled away
+ *   items are shown when the screen is new, then scrolled away or hidden when scrolling, and
+ *   finally shown again when idle.
+ */
+fun Modifier.scrollAway(
+    scrollInfoProvider: ScrollInfoProvider,
+    screenStage: () -> ScreenStage
+): Modifier = this then ScrollAwayModifierElement(scrollInfoProvider, screenStage)
+
+/**
+ * [ScreenStage] represents the different stages for a screen, which affect visibility of scaffold
+ * components such as [TimeText] and [ScrollIndicator] with [scrollAway] and other animations.
+ */
+enum class ScreenStage {
+    /**
+     * Initial stage for a screen when first displayed. It is expected that the [TimeText] and
+     * [ScrollIndicator] are displayed when initially showing a screen.
+     */
+    New,
+
+    /**
+     * Stage when both the screen is not scrolling and some time has passed after the screen was
+     * initially shown. At this stage, the [TimeText] is expected to be displayed and the
+     * [ScrollIndicator] will be hidden.
+     */
+    Idle,
+
+    /**
+     * Stage when the screen is being scrolled. At this stage, it is expected that the
+     * [ScrollIndicator] will be shown and [TimeText] will be scrolled away by the scroll operation.
+     */
+    Scrolling
+}
+
+private data class ScrollAwayModifierElement(
+    val scrollInfoProvider: ScrollInfoProvider,
+    val screenStage: () -> ScreenStage
+) : ModifierNodeElement<ScrollAwayModifierNode>() {
+    override fun create(): ScrollAwayModifierNode =
+        ScrollAwayModifierNode(scrollInfoProvider, screenStage)
+
+    override fun update(node: ScrollAwayModifierNode) {
+        node.scrollInfoProvider = scrollInfoProvider
+        node.screenStage = screenStage
+    }
+
+    override fun InspectorInfo.inspectableProperties() {
+        name = "scrollAway"
+        properties["scrollInfoProvider"] = scrollInfoProvider
+    }
+}
+
+private class ScrollAwayModifierNode(
+    var scrollInfoProvider: ScrollInfoProvider,
+    var screenStage: () -> ScreenStage,
+) : LayoutModifierNode, Modifier.Node() {
+    private val progressAnimatable: Animatable<Float, AnimationVector1D> = Animatable(0f)
+    private val alphaAnimatable = Animatable(1f)
+
+    override fun MeasureScope.measure(
+        measurable: Measurable,
+        constraints: Constraints
+    ): MeasureResult {
+        val placeable = measurable.measure(constraints)
+        return layout(placeable.width, placeable.height) {
+            placeable.placeWithLayer(0, 0) {
+                val offsetPx = scrollInfoProvider.anchorItemOffset
+
+                // Progress 0 means the item is fully visible, 1 means is scaled and alphaed 50%
+                var (targetProgress, targetAlpha) =
+                    if (!scrollInfoProvider.isScrollAwayValid) {
+                        // When the scroll info provide cannot provide a valid anchor item offset
+                        // due to its configuration (e.g. the anchor item index does not exist),
+                        // just show the content anyway.
+                        0f to 1f
+                    } else if (offsetPx.isNaN() || offsetPx > maxScrollOut.toPx()) {
+                        // Offset==NaN means the offset is invalid. If offset is invalid
+                        // or out of range, we infer that the tracked item is not in the visible
+                        // items list, so hide it.
+                        1f to 0f
+                    } else {
+                        // Scale, fade and scroll the content to scroll it away.
+                        (offsetPx / maxScrollOut.toPx()).coerceIn(0f, 1f) to 1f
+                    }
+
+                Log.d("SCROLL", "OffsetPx = $offsetPx, TargetProgress=$targetProgress")
+
+                val screenStage = screenStage()
+
+                // When idle, or on a new screen, if it's hidden, show it
+                val showAfterTimeout =
+                    screenStage != ScreenStage.Scrolling &&
+                        (targetAlpha == 0f || targetProgress > timeTextVisibilityThreshold)
+                if (showAfterTimeout) {
+                    targetProgress = 0f
+                    targetAlpha = 1f
+                }
+
+                if (targetAlpha != alphaAnimatable.targetValue) {
+                    if (targetAlpha == 0f) {
+                        // Hide is instant.
+                        coroutineScope.launch { alphaAnimatable.snapTo(0f) }
+                    } else {
+                        animateAlpha(targetAlpha, coroutineScope, alphaAnimatable)
+                    }
+                }
+
+                if (targetProgress != progressAnimatable.targetValue) {
+                    val scrollingAtTheTop =
+                        targetProgress != 0f &&
+                            progressAnimatable.targetValue != 0f &&
+                            screenStage() != ScreenStage.New
+                    if (scrollingAtTheTop || (showAfterTimeout && screenStage != ScreenStage.New)) {
+                        // If we are scrolling at the top, keep in sync.
+                        // Also, when we show after a timeout, there is no progress animation.
+                        coroutineScope.launch { progressAnimatable.snapTo(targetProgress) }
+                    } else {
+                        animateProgress(targetProgress, coroutineScope, progressAnimatable)
+                    }
+                }
+
+                val motionFraction = lerp(minMotionOut, maxMotionOut, progressAnimatable.value)
+                val offsetY = -(maxOffset.toPx() * progressAnimatable.value)
+                alpha = motionFraction * alphaAnimatable.value
+                scaleX = motionFraction
+                scaleY = motionFraction
+                translationY = offsetY
+                transformOrigin = TransformOrigin(pivotFractionX = 0.5f, pivotFractionY = 0.0f)
+            }
+        }
+    }
+
+    private fun animateProgress(
+        targetValue: Float,
+        coroutineScope: CoroutineScope,
+        animatable: Animatable<Float, AnimationVector1D>
+    ) {
+        coroutineScope.launch {
+            animatable.animateTo(
+                targetValue = targetValue,
+                animationSpec =
+                    tween(
+                        durationMillis = MotionTokens.DurationShort4,
+                        easing = MotionTokens.EasingStandard
+                    )
+            )
+        }
+    }
+
+    private fun animateAlpha(
+        targetAlpha: Float,
+        coroutineScope: CoroutineScope,
+        animatable: Animatable<Float, AnimationVector1D>,
+    ) {
+        coroutineScope.launch {
+            animatable.animateTo(
+                targetValue = targetAlpha,
+                animationSpec =
+                    tween(
+                        durationMillis = MotionTokens.DurationMedium1,
+                        easing =
+                            if (targetAlpha > 0.5f) {
+                                // Animation spec for showing the TimeText
+                                MotionTokens.EasingStandard
+                            } else {
+                                // Animation spec for hidding the TimeText
+                                MotionTokens.EasingStandardDecelerate
+                            },
+                    )
+            )
+        }
+    }
+}
+
+internal val maxScrollOut = 36.dp
+internal val maxOffset = 24.dp
+// Fade and scale motion effects are between 100% and 50%.
+internal const val minMotionOut = 1f
+internal const val maxMotionOut = 0.5f
+// Threshold to determine if the time text should be re-displayed after scrolling away.
+internal const val timeTextVisibilityThreshold = 0.55f
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ScrollIndicator.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ScrollIndicator.kt
index 1e48da4..593d882 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ScrollIndicator.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ScrollIndicator.kt
@@ -226,9 +226,7 @@
 
     internal val indicatorHeight = 50.dp
     internal val indicatorWidth = 4.dp
-
-    // TODO: replace with scaffold constant when it is available
-    internal val edgePadding = 2.dp
+    internal val edgePadding = ScaffoldDefaults.edgePadding
 }
 
 /**
@@ -750,13 +748,11 @@
             startMidArc - startAngleOffset
         )
     val topArcIndicatorWidth = lerp(0f, indicatorWidthPx, topRadiusFraction)
-
     // Calculate start angle for top segment.
     val startTopArc = startAngleOffset - sweepDegrees / 2
     // Represents an offset for top arc which moves when topRadiusFraction changes.
     val startTopArcOffset =
         pixelsHeightToDegrees(indicatorWidthPx * (1 - topRadiusFraction) / 2, usableRadius)
-
     // Calculate scale fraction for bottom arc
     val bottomRadiusFraction =
         inverseLerp(
@@ -771,7 +767,6 @@
     // Represents an offset for bottom arc which moves when bottomRadiusFraction changes.
     val startBottomArcOffset =
         pixelsHeightToDegrees(indicatorWidthPx * (1 - bottomRadiusFraction) / 2, usableRadius)
-
     // Draw top arc (unselected/background)
     drawArc(
         color = background,
@@ -782,7 +777,6 @@
         size = arcSize,
         style = Stroke(width = topArcIndicatorWidth, cap = StrokeCap.Round)
     )
-
     // Draw mid arc (selected/thumb)
     drawArc(
         color = color,
@@ -793,7 +787,6 @@
         size = arcSize,
         style = Stroke(width = indicatorWidthPx, cap = StrokeCap.Round)
     )
-
     // Draw bottom arc (unselected/background)
     drawArc(
         color = background,
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/SwitchButton.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/SwitchButton.kt
new file mode 100644
index 0000000..8b13403
--- /dev/null
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/SwitchButton.kt
@@ -0,0 +1,1746 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.material3
+
+import androidx.compose.animation.core.AnimationSpec
+import androidx.compose.animation.core.TweenSpec
+import androidx.compose.animation.core.animateFloat
+import androidx.compose.animation.core.tween
+import androidx.compose.animation.core.updateTransition
+import androidx.compose.foundation.background
+import androidx.compose.foundation.border
+import androidx.compose.foundation.interaction.Interaction
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.foundation.layout.IntrinsicSize
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.RowScope
+import androidx.compose.foundation.layout.defaultMinSize
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.layout.wrapContentSize
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Immutable
+import androidx.compose.runtime.State
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.drawBehind
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.graphics.drawscope.DrawScope
+import androidx.compose.ui.graphics.takeOrElse
+import androidx.compose.ui.semantics.Role
+import androidx.compose.ui.semantics.contentDescription
+import androidx.compose.ui.semantics.role
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.util.lerp
+import androidx.wear.compose.material3.tokens.MotionTokens
+import androidx.wear.compose.material3.tokens.SplitSwitchButtonTokens
+import androidx.wear.compose.material3.tokens.SwitchButtonTokens
+import androidx.wear.compose.materialcore.SelectionStage
+import androidx.wear.compose.materialcore.animateSelectionColor
+import androidx.wear.compose.materialcore.animateTick
+import androidx.wear.compose.materialcore.isLayoutDirectionRtl
+
+/**
+ * The Wear Material [SwitchButton] offers three slots and a specific layout for an icon, a label,
+ * and a secondaryLabel. The icon and secondaryLabel are optional. The items are laid out in a row
+ * with the optional icon at the start and a column containing the two label slots in the middle.
+ *
+ * The [SwitchButton] is Stadium shaped. The label should take no more than 3 lines of text. The
+ * secondary label should take no more than 2 lines of text. With localisation and/or large font
+ * sizes, the [SwitchButton] height adjusts to accommodate the contents. The label and secondary
+ * label should be start aligned.
+ *
+ * Example of a SwitchButton:
+ *
+ * @sample androidx.wear.compose.material3.samples.SwitchButtonSample
+ *
+ * [SwitchButton] can be enabled or disabled. A disabled button will not respond to click events.
+ *
+ * The recommended set of [SwitchButton] colors can be obtained from [SwitchButtonDefaults], e.g.
+ * [SwitchButtonDefaults.switchButtonColors].
+ *
+ * @param checked Boolean flag indicating whether this button is currently checked.
+ * @param onCheckedChange Callback to be invoked when this buttons checked status is changed.
+ * @param modifier Modifier to be applied to the [SwitchButton].
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not be
+ *   clickable.
+ * @param shape Defines the button's shape. It is strongly recommended to use the default as this
+ *   shape is a key characteristic of the Wear Material Theme.
+ * @param colors [SwitchButtonColors] that will be used to resolve the background and content color
+ *   for this button in different states.
+ * @param contentPadding The spacing values to apply internally between the container and the
+ *   content.
+ * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
+ *   emitting [Interaction]s for this button's "toggleable" tap area. You can use this to change the
+ *   button's appearance or preview the button in different states. Note that if `null` is provided,
+ *   interactions will still happen internally.
+ * @param icon An optional slot for providing an icon to indicate the purpose of the button. The
+ *   contents are expected to be a horizontally and vertically center aligned icon of size 24.dp.
+ * @param secondaryLabel A slot for providing the button's secondary label. The contents are
+ *   expected to be text which is "start" aligned.
+ * @param label A slot for providing the button's main label. The contents are expected to be text
+ *   which is "start" aligned and no more than 3 lines of text.
+ */
+@Composable
+fun SwitchButton(
+    checked: Boolean,
+    onCheckedChange: (Boolean) -> Unit,
+    modifier: Modifier = Modifier,
+    enabled: Boolean = true,
+    shape: Shape = SwitchButtonDefaults.switchButtonShape,
+    colors: SwitchButtonColors = SwitchButtonDefaults.switchButtonColors(),
+    contentPadding: PaddingValues = SwitchButtonDefaults.ContentPadding,
+    interactionSource: MutableInteractionSource? = null,
+    icon: @Composable (BoxScope.() -> Unit)? = null,
+    secondaryLabel: @Composable (RowScope.() -> Unit)? = null,
+    label: @Composable RowScope.() -> Unit
+) =
+    androidx.wear.compose.materialcore.ToggleButton(
+        checked = checked,
+        onCheckedChange = onCheckedChange,
+        label =
+            provideScopeContent(
+                contentColor = colors.contentColor(enabled = enabled, checked),
+                textStyle = SwitchButtonTokens.LabelFont.value,
+                content = label
+            ),
+        toggleControl = {
+            Switch(
+                checked = checked,
+                enabled = enabled,
+                thumbColor = { enabled, checked ->
+                    colors.thumbColor(enabled = enabled, checked = checked)
+                },
+                thumbIconColor = { enabled, checked ->
+                    colors.thumbIconColor(enabled = enabled, checked = checked)
+                },
+                trackColor = { enabled, checked ->
+                    colors.trackColor(enabled = enabled, checked = checked)
+                },
+                trackBorderColor = { enabled, checked ->
+                    colors.trackBorderColor(enabled = enabled, checked = checked)
+                }
+            )
+        },
+        selectionControl = null,
+        modifier = modifier.defaultMinSize(minHeight = MIN_HEIGHT).height(IntrinsicSize.Min),
+        icon =
+            provideNullableScopeContent(
+                contentColor = colors.iconColor(enabled = enabled, checked),
+                content = icon
+            ),
+        secondaryLabel =
+            provideNullableScopeContent(
+                contentColor = colors.secondaryContentColor(enabled = enabled, checked),
+                textStyle = SwitchButtonTokens.SecondaryLabelFont.value,
+                content = secondaryLabel
+            ),
+        background = { isEnabled, isChecked ->
+            val backgroundColor =
+                colors.containerColor(enabled = isEnabled, checked = isChecked).value
+
+            Modifier.background(backgroundColor)
+        },
+        enabled = enabled,
+        interactionSource = interactionSource,
+        contentPadding = contentPadding,
+        shape = shape,
+        toggleControlWidth = SWITCH_WIDTH,
+        toggleControlHeight = SWITCH_OUTER_HEIGHT,
+        labelSpacerSize = SwitchButtonDefaults.LabelSpacerSize,
+        toggleControlSpacing = TOGGLE_CONTROL_SPACING,
+        iconSpacing = ICON_SPACING,
+        ripple = ripple()
+    )
+
+/**
+ * The Wear Material [SplitSwitchButton] offers slots and a specific layout for a label and
+ * secondary label. The secondaryLabel is optional. The items are laid out with a column containing
+ * the two label slots and a Switch at the end.
+ *
+ * The [SplitSwitchButton] is Stadium shaped. The label should take no more than 3 lines of text.
+ * The secondary label should take no more than 2 lines of text. With localisation and/or large font
+ * sizes, the [SplitSwitchButton] height adjusts to accommodate the contents. The label and
+ * secondary label should be start aligned.
+ *
+ * A [SplitSwitchButton] has two tappable areas, one tap area for the labels and another for the
+ * switch. The [onContainerClick] listener will be associated with the main body of the
+ * [SplitSwitchButton] with the [onCheckedChange] listener associated with the switch area only.
+ *
+ * Example of a SplitSwitchButton:
+ *
+ * @sample androidx.wear.compose.material3.samples.SplitSwitchButtonSample
+ *
+ * For a SplitSwitchButton the background of the tappable background area behind the switch will
+ * have a visual effect applied to provide a "divider" between the two tappable areas.
+ *
+ * The recommended set of colors can be obtained from [SwitchButtonDefaults], e.g.
+ * [SwitchButtonDefaults.splitSwitchButtonColors].
+ *
+ * [SplitSwitchButton] can be enabled or disabled. A disabled button will not respond to click
+ * events.
+ *
+ * @param checked Boolean flag indicating whether this button is currently checked.
+ * @param onCheckedChange Callback to be invoked when this buttons checked status is changed.
+ * @param toggleContentDescription The content description for the switch control part of the
+ *   component.
+ * @param onContainerClick Click listener called when the user clicks the main body of the button,
+ *   the area behind the labels.
+ * @param modifier Modifier to be applied to the button.
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not be
+ *   clickable.
+ * @param shape Defines the button's shape. It is strongly recommended to use the default as this
+ *   shape is a key characteristic of the Wear Material Theme.
+ * @param colors [SplitSwitchButtonColors] that will be used to resolve the background and content
+ *   color for this button in different states.
+ * @param toggleInteractionSource an optional hoisted [MutableInteractionSource] for observing and
+ *   emitting [Interaction]s for this button's "toggleable" tap area. You can use this to change the
+ *   button's appearance or preview the button in different states. Note that if `null` is provided,
+ *   interactions will still happen internally.
+ * @param containerInteractionSource an optional hoisted [MutableInteractionSource] for observing
+ *   and emitting [Interaction]s for this button's main body "clickable" tap area. You can use this
+ *   to change the button's appearance or preview the button in different states. Note that if
+ *   `null` is provided, interactions will still happen internally.
+ * @param containerClickLabel Optional click label on the main body of the button for accessibility.
+ * @param contentPadding The spacing values to apply internally between the container and the
+ *   content.
+ * @param secondaryLabel A slot for providing the button's secondary label. The contents are
+ *   expected to be "start" aligned.
+ * @param label A slot for providing the button's main label. The contents are expected to be text
+ *   which is "start" aligned.
+ */
+@Composable
+fun SplitSwitchButton(
+    checked: Boolean,
+    onCheckedChange: (Boolean) -> Unit,
+    toggleContentDescription: String?,
+    onContainerClick: () -> Unit,
+    modifier: Modifier = Modifier,
+    enabled: Boolean = true,
+    shape: Shape = SwitchButtonDefaults.splitSwitchButtonShape,
+    colors: SplitSwitchButtonColors = SwitchButtonDefaults.splitSwitchButtonColors(),
+    toggleInteractionSource: MutableInteractionSource? = null,
+    containerInteractionSource: MutableInteractionSource? = null,
+    containerClickLabel: String? = null,
+    contentPadding: PaddingValues = SwitchButtonDefaults.ContentPadding,
+    secondaryLabel: @Composable (RowScope.() -> Unit)? = null,
+    label: @Composable RowScope.() -> Unit
+) =
+    androidx.wear.compose.materialcore.SplitToggleButton(
+        checked = checked,
+        onCheckedChange = onCheckedChange,
+        label =
+            provideScopeContent(
+                contentColor = colors.contentColor(enabled = enabled, checked = checked),
+                textStyle = SplitSwitchButtonTokens.LabelFont.value,
+                content = label
+            ),
+        onClick = onContainerClick,
+        toggleControl = {
+            Switch(
+                checked = checked,
+                enabled = enabled,
+                modifier =
+                    if (toggleContentDescription == null) {
+                        Modifier
+                    } else {
+                        Modifier.semantics { contentDescription = toggleContentDescription }
+                    },
+                thumbColor = { enabled, checked ->
+                    colors.thumbColor(enabled = enabled, checked = checked)
+                },
+                thumbIconColor = { enabled, checked ->
+                    colors.thumbIconColor(enabled = enabled, checked = checked)
+                },
+                trackColor = { enabled, checked ->
+                    colors.trackColor(enabled = enabled, checked = checked)
+                },
+                trackBorderColor = { enabled, checked ->
+                    colors.trackBorderColor(enabled = enabled, checked = checked)
+                }
+            )
+        },
+        selectionControl = null,
+        modifier = modifier.defaultMinSize(minHeight = MIN_HEIGHT).height(IntrinsicSize.Min),
+        secondaryLabel =
+            provideNullableScopeContent(
+                contentColor = colors.secondaryContentColor(enabled = enabled, checked = checked),
+                textStyle = SplitSwitchButtonTokens.SecondaryLabelFont.value,
+                content = secondaryLabel
+            ),
+        backgroundColor = { isEnabled, isChecked ->
+            colors.containerColor(enabled = isEnabled, checked = isChecked)
+        },
+        splitBackgroundColor = { isEnabled, isChecked ->
+            colors.splitContainerColor(enabled = isEnabled, checked = isChecked)
+        },
+        enabled = enabled,
+        checkedInteractionSource = toggleInteractionSource,
+        clickInteractionSource = containerInteractionSource,
+        onClickLabel = containerClickLabel,
+        contentPadding = contentPadding,
+        shape = shape,
+        labelSpacerSize = SwitchButtonDefaults.LabelSpacerSize,
+        ripple = ripple()
+    )
+
+/** Contains the default values used by [SwitchButton]s and [SplitSwitchButton]s */
+object SwitchButtonDefaults {
+    /** Recommended [Shape] for [SwitchButton]. */
+    val switchButtonShape: Shape
+        @Composable get() = SwitchButtonTokens.ContainerShape.value
+
+    /** Recommended [Shape] for [SplitSwitchButton]. */
+    val splitSwitchButtonShape: Shape
+        @Composable get() = SplitSwitchButtonTokens.ContainerShape.value
+
+    /** Creates a [SwitchButtonColors] for use in a [SwitchButton]. */
+    @Composable fun switchButtonColors() = MaterialTheme.colorScheme.defaultSwitchButtonColors
+
+    /**
+     * Creates a [SwitchButtonColors] for use in a [SwitchButton].
+     *
+     * @param checkedContainerColor The container color of the [SwitchButton] when enabled and
+     *   checked.
+     * @param checkedContentColor The content color of the [SwitchButton] when enabled and checked.
+     * @param checkedSecondaryContentColor The secondary content color of the [SwitchButton] when
+     *   enabled and checked, used for secondaryLabel content.
+     * @param checkedIconColor The icon color of the [SwitchButton] when enabled and checked.
+     * @param checkedThumbColor The thumb color of the [SwitchButton] when enabled and checked.
+     * @param checkedThumbIconColor The thumb icon color of the [SwitchButton] when enabled and
+     *   checked.
+     * @param checkedTrackColor The track color of the [SwitchButton] when enabled and checked.
+     * @param checkedTrackBorderColor The track border color of the [SwitchButton] when enabled and
+     *   checked
+     * @param uncheckedContainerColor The container color of the [SwitchButton] when enabled and
+     *   unchecked.
+     * @param uncheckedContentColor The content color of a [SwitchButton] when enabled and
+     *   unchecked.
+     * @param uncheckedSecondaryContentColor The secondary content color of this [SwitchButton] when
+     *   enabled and unchecked, used for secondaryLabel content
+     * @param uncheckedIconColor The icon color of the [SwitchButton] when enabled and unchecked.
+     * @param uncheckedThumbColor The thumb color of the [SwitchButton] when enabled and unchecked.
+     * @param uncheckedTrackColor The track color of the [SwitchButton] when enabled and unchecked.
+     * @param uncheckedTrackBorderColor The track border color of the [SwitchButton] when enabled
+     *   and unchecked
+     * @param disabledCheckedContainerColor The container color of the [SwitchButton] when disabled
+     *   and checked.
+     * @param disabledCheckedContentColor The content color of the [SwitchButton] when disabled and
+     *   checked.
+     * @param disabledCheckedSecondaryContentColor The secondary content color of the [SwitchButton]
+     *   when disabled and checked, used for secondaryLabel content.
+     * @param disabledCheckedIconColor The icon color of the [SwitchButton] when disabled and
+     *   checked.
+     * @param disabledCheckedThumbColor The thumb color of the [SwitchButton] when disabled and
+     *   checked.
+     * @param disabledCheckedThumbIconColor The thumb icon color of the [SwitchButton] when disabled
+     *   and checked.
+     * @param disabledCheckedTrackColor The track color of the [SwitchButton] when disabled and
+     *   checked.
+     * @param disabledCheckedTrackBorderColor The track border color of the [SwitchButton] when
+     *   disabled and checked
+     * @param disabledUncheckedContainerColor The container color of the [SwitchButton] when
+     *   disabled and unchecked.
+     * @param disabledUncheckedContentColor The content color of a [SwitchButton] when disabled and
+     *   unchecked.
+     * @param disabledUncheckedSecondaryContentColor The secondary content color of this
+     *   [SwitchButton] when disabled and unchecked, used for secondaryLabel content
+     * @param disabledUncheckedIconColor The icon color of the [SwitchButton] when disabled and
+     *   unchecked.
+     * @param disabledUncheckedThumbColor The thumb color of the [SwitchButton] when disabled and
+     *   unchecked.
+     * @param disabledUncheckedTrackBorderColor The track border color of the [SwitchButton] when
+     *   disabled and unchecked
+     */
+    @Composable
+    fun switchButtonColors(
+        checkedContainerColor: Color = Color.Unspecified,
+        checkedContentColor: Color = Color.Unspecified,
+        checkedSecondaryContentColor: Color = Color.Unspecified,
+        checkedIconColor: Color = Color.Unspecified,
+        checkedThumbColor: Color = Color.Unspecified,
+        checkedThumbIconColor: Color = Color.Unspecified,
+        checkedTrackColor: Color = Color.Unspecified,
+        checkedTrackBorderColor: Color = Color.Unspecified,
+        uncheckedContainerColor: Color = Color.Unspecified,
+        uncheckedContentColor: Color = Color.Unspecified,
+        uncheckedSecondaryContentColor: Color = Color.Unspecified,
+        uncheckedIconColor: Color = Color.Unspecified,
+        uncheckedThumbColor: Color = Color.Unspecified,
+        uncheckedTrackColor: Color = Color.Unspecified,
+        uncheckedTrackBorderColor: Color = Color.Unspecified,
+        disabledCheckedContainerColor: Color = Color.Unspecified,
+        disabledCheckedContentColor: Color = Color.Unspecified,
+        disabledCheckedSecondaryContentColor: Color = Color.Unspecified,
+        disabledCheckedIconColor: Color = Color.Unspecified,
+        disabledCheckedThumbColor: Color = Color.Unspecified,
+        disabledCheckedThumbIconColor: Color = Color.Unspecified,
+        disabledCheckedTrackColor: Color = Color.Unspecified,
+        disabledCheckedTrackBorderColor: Color = Color.Unspecified,
+        disabledUncheckedContainerColor: Color = Color.Unspecified,
+        disabledUncheckedContentColor: Color = Color.Unspecified,
+        disabledUncheckedSecondaryContentColor: Color = Color.Unspecified,
+        disabledUncheckedIconColor: Color = Color.Unspecified,
+        disabledUncheckedThumbColor: Color = Color.Unspecified,
+        disabledUncheckedTrackBorderColor: Color = Color.Unspecified,
+    ) =
+        MaterialTheme.colorScheme.defaultSwitchButtonColors.copy(
+            checkedContainerColor = checkedContainerColor,
+            checkedContentColor = checkedContentColor,
+            checkedSecondaryContentColor = checkedSecondaryContentColor,
+            checkedIconColor = checkedIconColor,
+            checkedThumbColor = checkedThumbColor,
+            checkedThumbIconColor = checkedThumbIconColor,
+            checkedTrackColor = checkedTrackColor,
+            checkedTrackBorderColor = checkedTrackBorderColor,
+            uncheckedContainerColor = uncheckedContainerColor,
+            uncheckedContentColor = uncheckedContentColor,
+            uncheckedSecondaryContentColor = uncheckedSecondaryContentColor,
+            uncheckedIconColor = uncheckedIconColor,
+            uncheckedThumbColor = uncheckedThumbColor,
+            uncheckedTrackColor = uncheckedTrackColor,
+            uncheckedTrackBorderColor = uncheckedTrackBorderColor,
+            disabledCheckedContainerColor = disabledCheckedContainerColor,
+            disabledCheckedContentColor = disabledCheckedContentColor,
+            disabledCheckedSecondaryContentColor = disabledCheckedSecondaryContentColor,
+            disabledCheckedIconColor = disabledCheckedIconColor,
+            disabledCheckedThumbColor = disabledCheckedThumbColor,
+            disabledCheckedThumbIconColor = disabledCheckedThumbIconColor,
+            disabledCheckedTrackColor = disabledCheckedTrackColor,
+            disabledCheckedTrackBorderColor = disabledCheckedTrackBorderColor,
+            disabledUncheckedContainerColor = disabledUncheckedContainerColor,
+            disabledUncheckedContentColor = disabledUncheckedContentColor,
+            disabledUncheckedSecondaryContentColor = disabledUncheckedSecondaryContentColor,
+            disabledUncheckedIconColor = disabledUncheckedIconColor,
+            disabledUncheckedThumbColor = disabledUncheckedThumbColor,
+            disabledUncheckedTrackBorderColor = disabledUncheckedTrackBorderColor,
+        )
+
+    /** Creates a [SplitSwitchButtonColors] for use in a [SplitSwitchButton]. */
+    @Composable
+    fun splitSwitchButtonColors() = MaterialTheme.colorScheme.defaultSplitSwitchButtonColors
+
+    /**
+     * Creates a [SplitSwitchButtonColors] for use in a [SplitSwitchButton].
+     *
+     * @param checkedContainerColor The container color of the [SplitSwitchButton] when enabled and
+     *   checked.
+     * @param checkedContentColor The content color of the [SplitSwitchButton] when enabled and
+     *   checked.
+     * @param checkedSecondaryContentColor The secondary content color of the [SplitSwitchButton]
+     *   when enabled and checked, used for secondaryLabel content.
+     * @param checkedSplitContainerColor The split container color of the [SplitSwitchButton] when
+     *   enabled and checked.
+     * @param checkedThumbColor The thumb color of the [SplitSwitchButton] when enabled and checked.
+     * @param checkedThumbIconColor The thumb icon color of the [SplitSwitchButton] when enabled and
+     *   checked.
+     * @param checkedTrackColor The track color of the [SplitSwitchButton] when enabled and checked.
+     * @param checkedTrackBorderColor The track border color of the [SplitSwitchButton] when enabled
+     *   and checked
+     * @param uncheckedContainerColor The container color of the [SplitSwitchButton] when enabled
+     *   and unchecked.
+     * @param uncheckedContentColor The content color of the [SplitSwitchButton] when enabled and
+     *   unchecked.
+     * @param uncheckedSecondaryContentColor The secondary content color of the [SplitSwitchButton]
+     *   when enabled and unchecked, used for secondaryLabel content.
+     * @param uncheckedSplitContainerColor The split container color of the [SplitSwitchButton] when
+     *   enabled and unchecked.
+     * @param uncheckedThumbColor The thumb color of the [SplitSwitchButton] when enabled and
+     *   unchecked.
+     * @param uncheckedTrackColor The track color of the [SplitSwitchButton] when enabled and
+     *   unchecked.
+     * @param uncheckedTrackBorderColor The track border color of the [SplitSwitchButton] when
+     *   enabled and unchecked
+     * @param disabledCheckedContainerColor The container color of the [SplitSwitchButton] when
+     *   disabled and checked.
+     * @param disabledCheckedContentColor The content color of the [SplitSwitchButton] when disabled
+     *   and checked.
+     * @param disabledCheckedSecondaryContentColor The secondary content color of the
+     *   [SplitSwitchButton] when disabled and checked, used for secondaryLabel content.
+     * @param disabledCheckedSplitContainerColor The split container color of the
+     *   [ SplitSwitchButton] when disabled and checked.
+     * @param disabledCheckedThumbColor The thumb color of the [SplitSwitchButton] when disabled and
+     *   checked.
+     * @param disabledCheckedThumbIconColor The thumb icon color of the [SplitSwitchButton] when
+     *   disabled and checked.
+     * @param disabledCheckedTrackColor The track color of the [SplitSwitchButton] when disabled and
+     *   checked.
+     * @param disabledCheckedTrackBorderColor The track border color of the [SplitSwitchButton] when
+     *   disabled and checked
+     * @param disabledUncheckedContainerColor The container color of the [SplitSwitchButton] when
+     *   disabled and unchecked.
+     * @param disabledUncheckedContentColor The content color of the [SplitSwitchButton] when
+     *   disabled and unchecked.
+     * @param disabledUncheckedSecondaryContentColor The secondary content color of the
+     *   [SplitSwitchButton] when disabled and unchecked, used for secondaryLabel content.
+     * @param disabledUncheckedSplitContainerColor The split container color of the
+     *   [SplitSwitchButton] when disabled and unchecked.
+     * @param disabledUncheckedThumbColor The thumb color of the [SplitSwitchButton] when disabled
+     *   and unchecked.
+     * @param disabledUncheckedTrackBorderColor The track border color of the [SplitSwitchButton]
+     *   when disabled and unchecked
+     */
+    @Composable
+    fun splitSwitchButtonColors(
+        checkedContainerColor: Color = Color.Unspecified,
+        checkedContentColor: Color = Color.Unspecified,
+        checkedSecondaryContentColor: Color = Color.Unspecified,
+        checkedSplitContainerColor: Color = Color.Unspecified,
+        checkedThumbColor: Color = Color.Unspecified,
+        checkedThumbIconColor: Color = Color.Unspecified,
+        checkedTrackColor: Color = Color.Unspecified,
+        checkedTrackBorderColor: Color = Color.Unspecified,
+        uncheckedContainerColor: Color = Color.Unspecified,
+        uncheckedContentColor: Color = Color.Unspecified,
+        uncheckedSecondaryContentColor: Color = Color.Unspecified,
+        uncheckedSplitContainerColor: Color = Color.Unspecified,
+        uncheckedThumbColor: Color = Color.Unspecified,
+        uncheckedTrackColor: Color = Color.Unspecified,
+        uncheckedTrackBorderColor: Color = Color.Unspecified,
+        disabledCheckedContainerColor: Color = Color.Unspecified,
+        disabledCheckedContentColor: Color = Color.Unspecified,
+        disabledCheckedSecondaryContentColor: Color = Color.Unspecified,
+        disabledCheckedSplitContainerColor: Color = Color.Unspecified,
+        disabledCheckedThumbColor: Color = Color.Unspecified,
+        disabledCheckedThumbIconColor: Color = Color.Unspecified,
+        disabledCheckedTrackColor: Color = Color.Unspecified,
+        disabledCheckedTrackBorderColor: Color = Color.Unspecified,
+        disabledUncheckedContainerColor: Color = Color.Unspecified,
+        disabledUncheckedContentColor: Color = Color.Unspecified,
+        disabledUncheckedSecondaryContentColor: Color = Color.Unspecified,
+        disabledUncheckedSplitContainerColor: Color = Color.Unspecified,
+        disabledUncheckedThumbColor: Color = Color.Unspecified,
+        disabledUncheckedTrackBorderColor: Color = Color.Unspecified,
+    ) =
+        MaterialTheme.colorScheme.defaultSplitSwitchButtonColors.copy(
+            checkedContainerColor = checkedContainerColor,
+            checkedContentColor = checkedContentColor,
+            checkedSecondaryContentColor = checkedSecondaryContentColor,
+            checkedSplitContainerColor = checkedSplitContainerColor,
+            checkedThumbColor = checkedThumbColor,
+            checkedThumbIconColor = checkedThumbIconColor,
+            checkedTrackColor = checkedTrackColor,
+            checkedTrackBorderColor = checkedTrackBorderColor,
+            uncheckedContainerColor = uncheckedContainerColor,
+            uncheckedContentColor = uncheckedContentColor,
+            uncheckedSecondaryContentColor = uncheckedSecondaryContentColor,
+            uncheckedSplitContainerColor = uncheckedSplitContainerColor,
+            uncheckedThumbColor = uncheckedThumbColor,
+            uncheckedTrackColor = uncheckedTrackColor,
+            uncheckedTrackBorderColor = uncheckedTrackBorderColor,
+            disabledCheckedContainerColor = disabledCheckedContainerColor,
+            disabledCheckedContentColor = disabledCheckedContentColor,
+            disabledCheckedSecondaryContentColor = disabledCheckedSecondaryContentColor,
+            disabledCheckedSplitContainerColor = disabledCheckedSplitContainerColor,
+            disabledCheckedThumbColor = disabledCheckedThumbColor,
+            disabledCheckedThumbIconColor = disabledCheckedThumbIconColor,
+            disabledCheckedTrackColor = disabledCheckedTrackColor,
+            disabledCheckedTrackBorderColor = disabledCheckedTrackBorderColor,
+            disabledUncheckedContainerColor = disabledUncheckedContainerColor,
+            disabledUncheckedContentColor = disabledUncheckedContentColor,
+            disabledUncheckedSecondaryContentColor = disabledUncheckedSecondaryContentColor,
+            disabledUncheckedSplitContainerColor = disabledUncheckedSplitContainerColor,
+            disabledUncheckedThumbColor = disabledUncheckedThumbColor,
+            disabledUncheckedTrackBorderColor = disabledUncheckedTrackBorderColor,
+        )
+
+    internal val LabelSpacerSize = 2.dp
+    private val HorizontalPadding = 14.dp
+    private val VerticalPadding = 8.dp
+
+    /** The default content padding used by [SwitchButton] */
+    val ContentPadding: PaddingValues =
+        PaddingValues(
+            start = HorizontalPadding,
+            top = VerticalPadding,
+            end = HorizontalPadding,
+            bottom = VerticalPadding
+        )
+
+    private val ColorScheme.defaultSwitchButtonColors: SwitchButtonColors
+        get() {
+            return defaultSwitchButtonColorsCached
+                ?: SwitchButtonColors(
+                        checkedContainerColor = fromToken(SwitchButtonTokens.CheckedContainerColor),
+                        checkedContentColor = fromToken(SwitchButtonTokens.CheckedContentColor),
+                        checkedSecondaryContentColor =
+                            fromToken(SwitchButtonTokens.CheckedSecondaryLabelColor)
+                                .copy(alpha = SwitchButtonTokens.CheckedSecondaryLabelOpacity),
+                        checkedIconColor = fromToken(SwitchButtonTokens.CheckedIconColor),
+                        checkedThumbColor = fromToken(SwitchButtonTokens.CheckedThumbColor),
+                        checkedThumbIconColor = fromToken(SwitchButtonTokens.CheckedThumbIconColor),
+                        checkedTrackColor = fromToken(SwitchButtonTokens.CheckedTrackColor),
+                        checkedTrackBorderColor =
+                            fromToken(SwitchButtonTokens.CheckedTrackBorderColor),
+                        uncheckedContainerColor =
+                            fromToken(SwitchButtonTokens.UncheckedContainerColor),
+                        uncheckedContentColor = fromToken(SwitchButtonTokens.UncheckedContentColor),
+                        uncheckedSecondaryContentColor =
+                            fromToken(SwitchButtonTokens.UncheckedSecondaryLabelColor),
+                        uncheckedThumbColor = fromToken(SwitchButtonTokens.UncheckedThumbColor),
+                        uncheckedTrackColor = fromToken(SwitchButtonTokens.UncheckedTrackColor),
+                        uncheckedTrackBorderColor =
+                            fromToken(SwitchButtonTokens.UncheckedTrackBorderColor),
+                        uncheckedIconColor = fromToken(SwitchButtonTokens.UncheckedIconColor),
+                        disabledCheckedContainerColor =
+                            fromToken(SwitchButtonTokens.DisabledCheckedContainerColor)
+                                .toDisabledColor(
+                                    disabledAlpha =
+                                        SwitchButtonTokens.DisabledCheckedContainerOpacity
+                                ),
+                        disabledCheckedContentColor =
+                            fromToken(SwitchButtonTokens.DisabledCheckedContentColor)
+                                .toDisabledColor(
+                                    disabledAlpha = SwitchButtonTokens.DisabledOpacity
+                                ),
+                        disabledCheckedSecondaryContentColor =
+                            fromToken(SwitchButtonTokens.DisabledCheckedSecondaryLabelColor)
+                                .toDisabledColor(
+                                    disabledAlpha = SwitchButtonTokens.DisabledOpacity
+                                ),
+                        disabledCheckedIconColor =
+                            fromToken(SwitchButtonTokens.DisabledCheckedIconColor)
+                                .toDisabledColor(
+                                    disabledAlpha = SwitchButtonTokens.DisabledOpacity
+                                ),
+                        disabledCheckedThumbColor =
+                            fromToken(SwitchButtonTokens.DisabledCheckedThumbColor)
+                                .toDisabledColor(
+                                    disabledAlpha = SwitchButtonTokens.DisabledCheckedThumbOpacity
+                                ),
+                        disabledCheckedThumbIconColor =
+                            fromToken(SwitchButtonTokens.DisabledCheckedThumbIconColor)
+                                .toDisabledColor(
+                                    disabledAlpha =
+                                        SwitchButtonTokens.DisabledCheckedThumbIconOpacity
+                                ),
+                        disabledCheckedTrackColor =
+                            fromToken(SwitchButtonTokens.DisabledCheckedTrackColor)
+                                .toDisabledColor(
+                                    disabledAlpha = SwitchButtonTokens.DisabledCheckedTrackOpacity
+                                ),
+                        disabledCheckedTrackBorderColor =
+                            fromToken(SwitchButtonTokens.DisabledCheckedTrackBorderColor)
+                                .toDisabledColor(
+                                    disabledAlpha =
+                                        SwitchButtonTokens.DisabledCheckedTrackBorderOpacity
+                                ),
+                        disabledUncheckedContainerColor =
+                            fromToken(SwitchButtonTokens.DisabledUncheckedContainerColor)
+                                .toDisabledColor(
+                                    disabledAlpha =
+                                        SwitchButtonTokens.DisabledUncheckedContainerOpacity
+                                ),
+                        disabledUncheckedContentColor =
+                            fromToken(SwitchButtonTokens.DisabledUncheckedContentColor)
+                                .toDisabledColor(
+                                    disabledAlpha = SwitchButtonTokens.DisabledOpacity
+                                ),
+                        disabledUncheckedSecondaryContentColor =
+                            fromToken(SwitchButtonTokens.DisabledUncheckedSecondaryLabelColor)
+                                .toDisabledColor(
+                                    disabledAlpha = SwitchButtonTokens.DisabledOpacity
+                                ),
+                        disabledUncheckedIconColor =
+                            fromToken(SwitchButtonTokens.DisabledUncheckedIconColor)
+                                .toDisabledColor(
+                                    disabledAlpha = SwitchButtonTokens.DisabledOpacity
+                                ),
+                        disabledUncheckedThumbColor =
+                            fromToken(SwitchButtonTokens.DisabledUncheckedThumbColor)
+                                .toDisabledColor(
+                                    disabledAlpha = SwitchButtonTokens.DisabledUncheckedThumbOpacity
+                                ),
+                        disabledUncheckedTrackBorderColor =
+                            fromToken(SwitchButtonTokens.DisabledUncheckedTrackBorderColor)
+                                .toDisabledColor(
+                                    disabledAlpha =
+                                        SwitchButtonTokens.DisabledUncheckedTrackBorderOpacity
+                                )
+                    )
+                    .also { defaultSwitchButtonColorsCached = it }
+        }
+
+    private val ColorScheme.defaultSplitSwitchButtonColors: SplitSwitchButtonColors
+        get() {
+            return defaultSplitSwitchButtonColorsCached
+                ?: SplitSwitchButtonColors(
+                        checkedContainerColor =
+                            fromToken(SplitSwitchButtonTokens.CheckedContainerColor),
+                        checkedContentColor =
+                            fromToken(SplitSwitchButtonTokens.CheckedContentColor),
+                        checkedSecondaryContentColor =
+                            fromToken(SplitSwitchButtonTokens.CheckedSecondaryLabelColor)
+                                .copy(alpha = SplitSwitchButtonTokens.CheckedSecondaryLabelOpacity),
+                        checkedSplitContainerColor =
+                            fromToken(SplitSwitchButtonTokens.CheckedSplitContainerColor)
+                                .copy(alpha = SplitSwitchButtonTokens.CheckedSplitContainerOpacity),
+                        checkedThumbColor = fromToken(SplitSwitchButtonTokens.CheckedThumbColor),
+                        checkedThumbIconColor =
+                            fromToken(SplitSwitchButtonTokens.CheckedThumbIconColor),
+                        checkedTrackColor = fromToken(SplitSwitchButtonTokens.CheckedTrackColor),
+                        checkedTrackBorderColor =
+                            fromToken(SplitSwitchButtonTokens.CheckedTrackBorderColor),
+                        uncheckedContainerColor =
+                            fromToken(SplitSwitchButtonTokens.UncheckedContainerColor),
+                        uncheckedContentColor =
+                            fromToken(SplitSwitchButtonTokens.UncheckedContentColor),
+                        uncheckedSecondaryContentColor =
+                            fromToken(SplitSwitchButtonTokens.UncheckedSecondaryLabelColor),
+                        uncheckedSplitContainerColor =
+                            fromToken(SplitSwitchButtonTokens.UncheckedSplitContainerColor),
+                        uncheckedThumbColor =
+                            fromToken(SplitSwitchButtonTokens.UncheckedThumbColor),
+                        uncheckedTrackColor =
+                            fromToken(SplitSwitchButtonTokens.UncheckedTrackColor),
+                        uncheckedTrackBorderColor =
+                            fromToken(SplitSwitchButtonTokens.UncheckedTrackBorderColor),
+                        disabledCheckedContainerColor =
+                            fromToken(SplitSwitchButtonTokens.DisabledCheckedContainerColor)
+                                .toDisabledColor(
+                                    disabledAlpha = SplitSwitchButtonTokens.DisabledOpacity
+                                ),
+                        disabledCheckedContentColor =
+                            fromToken(SplitSwitchButtonTokens.DisabledCheckedContentColor)
+                                .toDisabledColor(
+                                    disabledAlpha = SplitSwitchButtonTokens.DisabledOpacity
+                                ),
+                        disabledCheckedSecondaryContentColor =
+                            fromToken(SplitSwitchButtonTokens.DisabledCheckedSecondaryLabelColor)
+                                .copy(
+                                    alpha =
+                                        SplitSwitchButtonTokens.DisabledCheckedSecondaryLabelOpacity
+                                )
+                                .toDisabledColor(
+                                    disabledAlpha = SplitSwitchButtonTokens.DisabledOpacity
+                                ),
+                        disabledCheckedSplitContainerColor =
+                            fromToken(SplitSwitchButtonTokens.DisabledCheckedSplitContainerColor)
+                                .copy(
+                                    alpha =
+                                        SplitSwitchButtonTokens.DisabledCheckedSplitContainerOpacity
+                                )
+                                .toDisabledColor(
+                                    disabledAlpha = SplitSwitchButtonTokens.DisabledOpacity
+                                ),
+                        disabledCheckedThumbColor =
+                            fromToken(SplitSwitchButtonTokens.DisabledCheckedThumbColor)
+                                .toDisabledColor(
+                                    disabledAlpha =
+                                        SplitSwitchButtonTokens.DisabledCheckedThumbOpacity
+                                ),
+                        disabledCheckedThumbIconColor =
+                            fromToken(SplitSwitchButtonTokens.DisabledCheckedThumbIconColor)
+                                .toDisabledColor(
+                                    disabledAlpha =
+                                        SplitSwitchButtonTokens.DisabledCheckedThumbIconOpacity
+                                ),
+                        disabledCheckedTrackColor =
+                            fromToken(SplitSwitchButtonTokens.DisabledCheckedTrackColor)
+                                .toDisabledColor(
+                                    disabledAlpha =
+                                        SplitSwitchButtonTokens.DisabledCheckedTrackOpacity
+                                ),
+                        disabledCheckedTrackBorderColor =
+                            fromToken(SplitSwitchButtonTokens.DisabledCheckedTrackBorderColor)
+                                .toDisabledColor(
+                                    disabledAlpha =
+                                        SplitSwitchButtonTokens.DisabledCheckedTrackBorderOpacity
+                                ),
+                        disabledUncheckedContainerColor =
+                            fromToken(SplitSwitchButtonTokens.DisabledUncheckedContainerColor)
+                                .toDisabledColor(
+                                    disabledAlpha = SplitSwitchButtonTokens.DisabledOpacity
+                                ),
+                        disabledUncheckedContentColor =
+                            fromToken(SplitSwitchButtonTokens.DisabledUncheckedContentColor)
+                                .toDisabledColor(
+                                    disabledAlpha = SplitSwitchButtonTokens.DisabledOpacity
+                                ),
+                        disabledUncheckedSecondaryContentColor =
+                            fromToken(SplitSwitchButtonTokens.DisabledUncheckedSecondaryLabelColor)
+                                .toDisabledColor(
+                                    disabledAlpha = SplitSwitchButtonTokens.DisabledOpacity
+                                ),
+                        disabledUncheckedSplitContainerColor =
+                            fromToken(SplitSwitchButtonTokens.DisabledUncheckedSplitContainerColor)
+                                .toDisabledColor(
+                                    disabledAlpha = SplitSwitchButtonTokens.DisabledOpacity
+                                ),
+                        disabledUncheckedThumbColor =
+                            fromToken(SplitSwitchButtonTokens.DisabledUncheckedThumbColor)
+                                .toDisabledColor(
+                                    disabledAlpha =
+                                        SplitSwitchButtonTokens.DisabledUncheckedThumbOpacity
+                                ),
+                        disabledUncheckedTrackBorderColor =
+                            fromToken(SplitSwitchButtonTokens.DisabledUncheckedTrackBorderColor)
+                                .toDisabledColor(
+                                    disabledAlpha =
+                                        SplitSwitchButtonTokens.DisabledUncheckedTrackBorderOpacity
+                                ),
+                    )
+                    .also { defaultSplitSwitchButtonColorsCached = it }
+        }
+}
+
+/**
+ * Represents the different container and content colors used for [SwitchButton], in various states,
+ * that are checked, unchecked, enabled and disabled.
+ *
+ * @param checkedContainerColor Container or background color when the [SwitchButton] is checked
+ * @param checkedContentColor Color of the content like label when the [SwitchButton] is checked
+ * @param checkedSecondaryContentColor Color of the secondary content like secondary label when the
+ *   [SwitchButton] is checked
+ * @param checkedIconColor Color of the icon when the [SwitchButton] is checked
+ * @param checkedThumbColor Color of the thumb when the [SwitchButton] is checked
+ * @param checkedThumbIconColor Color of the thumb icon when the [SwitchButton] is checked
+ * @param checkedTrackColor Color of the track when the [SwitchButton] is checked
+ * @param checkedTrackBorderColor Color of the track boarder when the [SwitchButton] is checked
+ * @param uncheckedContainerColor Container or background color when the [SwitchButton] is unchecked
+ * @param uncheckedContentColor Color of the content like label when the [SwitchButton] is unchecked
+ * @param uncheckedSecondaryContentColor Color of the secondary content like secondary label when
+ *   the [SwitchButton] is unchecked
+ * @param uncheckedIconColor Color of the icon when the [SwitchButton] is unchecked
+ * @param uncheckedThumbColor Color of the thumb when the [SwitchButton] is unchecked
+ * @param uncheckedTrackColor Color of the track when the [SwitchButton] is unchecked
+ * @param uncheckedTrackBorderColor Color of the track border when the [SwitchButton] is unchecked
+ * @param disabledCheckedContainerColor Container or background color when the [SwitchButton] is
+ *   disabled and checked
+ * @param disabledCheckedContentColor Color of content like label when the [SwitchButton] is
+ *   disabled and checked
+ * @param disabledCheckedSecondaryContentColor Color of the secondary content like secondary label
+ *   when the [SwitchButton] is disabled and checked
+ * @param disabledCheckedIconColor Icon color when the [SwitchButton] is disabled and checked
+ * @param disabledCheckedThumbColor Thumb color when the [SwitchButton] is disabled and checked
+ * @param disabledCheckedThumbIconColor Thumb icon color when the [SwitchButton] is disabled and
+ *   checked
+ * @param disabledCheckedTrackColor Track color when the [SwitchButton] is disabled and checked
+ * @param disabledCheckedTrackBorderColor Track border color when the [SwitchButton] is disabled and
+ *   checked
+ * @param disabledUncheckedContainerColor Container or background color when the [SwitchButton] is
+ *   disabled and unchecked
+ * @param disabledUncheckedContentColor Color of the content like label when the [SwitchButton] is
+ *   disabled and unchecked
+ * @param disabledUncheckedSecondaryContentColor Color of the secondary content like secondary label
+ *   when the [SwitchButton] is disabled and unchecked
+ * @param disabledUncheckedIconColor Icon color when the [SwitchButton] is disabled and unchecked
+ * @param disabledUncheckedThumbColor Thumb color when the [SwitchButton] is disabled and unchecked
+ * @param disabledUncheckedTrackBorderColor Track border color when the [SwitchButton] is disabled
+ *   and unchecked
+ */
+@Immutable
+class SwitchButtonColors(
+    val checkedContainerColor: Color,
+    val checkedContentColor: Color,
+    val checkedSecondaryContentColor: Color,
+    val checkedIconColor: Color,
+    val checkedThumbColor: Color,
+    val checkedThumbIconColor: Color,
+    val checkedTrackBorderColor: Color,
+    val checkedTrackColor: Color,
+    val uncheckedContainerColor: Color,
+    val uncheckedContentColor: Color,
+    val uncheckedSecondaryContentColor: Color,
+    val uncheckedIconColor: Color,
+    val uncheckedThumbColor: Color,
+    val uncheckedTrackColor: Color,
+    val uncheckedTrackBorderColor: Color,
+    val disabledCheckedContainerColor: Color,
+    val disabledCheckedContentColor: Color,
+    val disabledCheckedSecondaryContentColor: Color,
+    val disabledCheckedIconColor: Color,
+    val disabledCheckedThumbColor: Color,
+    val disabledCheckedThumbIconColor: Color,
+    val disabledCheckedTrackColor: Color,
+    val disabledCheckedTrackBorderColor: Color,
+    val disabledUncheckedContainerColor: Color,
+    val disabledUncheckedContentColor: Color,
+    val disabledUncheckedSecondaryContentColor: Color,
+    val disabledUncheckedIconColor: Color,
+    val disabledUncheckedThumbColor: Color,
+    val disabledUncheckedTrackBorderColor: Color
+) {
+    internal fun copy(
+        checkedContainerColor: Color,
+        checkedContentColor: Color,
+        checkedSecondaryContentColor: Color,
+        checkedIconColor: Color,
+        checkedThumbColor: Color,
+        checkedThumbIconColor: Color,
+        checkedTrackColor: Color,
+        checkedTrackBorderColor: Color,
+        uncheckedContainerColor: Color,
+        uncheckedContentColor: Color,
+        uncheckedSecondaryContentColor: Color,
+        uncheckedIconColor: Color,
+        uncheckedThumbColor: Color,
+        uncheckedTrackColor: Color,
+        uncheckedTrackBorderColor: Color,
+        disabledCheckedContainerColor: Color,
+        disabledCheckedContentColor: Color,
+        disabledCheckedSecondaryContentColor: Color,
+        disabledCheckedIconColor: Color,
+        disabledCheckedThumbColor: Color,
+        disabledCheckedThumbIconColor: Color,
+        disabledCheckedTrackColor: Color,
+        disabledCheckedTrackBorderColor: Color,
+        disabledUncheckedContainerColor: Color,
+        disabledUncheckedContentColor: Color,
+        disabledUncheckedSecondaryContentColor: Color,
+        disabledUncheckedIconColor: Color,
+        disabledUncheckedThumbColor: Color,
+        disabledUncheckedTrackBorderColor: Color,
+    ): SwitchButtonColors =
+        SwitchButtonColors(
+            checkedContainerColor = checkedContainerColor.takeOrElse { this.checkedContainerColor },
+            checkedContentColor = checkedContentColor.takeOrElse { this.checkedContentColor },
+            checkedSecondaryContentColor =
+                checkedSecondaryContentColor.takeOrElse { this.checkedSecondaryContentColor },
+            checkedIconColor = checkedIconColor.takeOrElse { this.checkedIconColor },
+            checkedThumbColor = checkedThumbColor.takeOrElse { this.checkedThumbColor },
+            checkedThumbIconColor = checkedThumbIconColor.takeOrElse { this.checkedThumbIconColor },
+            checkedTrackColor = checkedTrackColor.takeOrElse { this.checkedTrackColor },
+            checkedTrackBorderColor =
+                checkedTrackBorderColor.takeOrElse { this.checkedTrackBorderColor },
+            uncheckedContainerColor =
+                uncheckedContainerColor.takeOrElse { this.uncheckedContainerColor },
+            uncheckedContentColor = uncheckedContentColor.takeOrElse { this.uncheckedContentColor },
+            uncheckedSecondaryContentColor =
+                uncheckedSecondaryContentColor.takeOrElse { this.uncheckedSecondaryContentColor },
+            uncheckedIconColor = uncheckedIconColor.takeOrElse { this.uncheckedIconColor },
+            uncheckedThumbColor = uncheckedThumbColor.takeOrElse { this.uncheckedThumbColor },
+            uncheckedTrackColor = uncheckedTrackColor.takeOrElse { this.uncheckedTrackColor },
+            uncheckedTrackBorderColor =
+                uncheckedTrackBorderColor.takeOrElse { this.uncheckedTrackBorderColor },
+            disabledCheckedContainerColor =
+                disabledCheckedContainerColor.takeOrElse { this.disabledCheckedContainerColor },
+            disabledCheckedContentColor =
+                disabledCheckedContentColor.takeOrElse { this.disabledCheckedContentColor },
+            disabledCheckedSecondaryContentColor =
+                disabledCheckedSecondaryContentColor.takeOrElse {
+                    this.disabledCheckedSecondaryContentColor
+                },
+            disabledCheckedIconColor =
+                disabledCheckedIconColor.takeOrElse { this.disabledCheckedIconColor },
+            disabledCheckedThumbColor =
+                disabledCheckedThumbColor.takeOrElse { this.disabledCheckedThumbColor },
+            disabledCheckedThumbIconColor =
+                disabledCheckedThumbIconColor.takeOrElse { this.disabledCheckedThumbIconColor },
+            disabledCheckedTrackColor =
+                disabledCheckedTrackColor.takeOrElse { this.disabledCheckedTrackColor },
+            disabledCheckedTrackBorderColor =
+                disabledCheckedTrackBorderColor.takeOrElse { this.disabledCheckedTrackBorderColor },
+            disabledUncheckedContainerColor =
+                disabledUncheckedContainerColor.takeOrElse { this.disabledUncheckedContainerColor },
+            disabledUncheckedContentColor =
+                disabledUncheckedContentColor.takeOrElse { this.disabledUncheckedContentColor },
+            disabledUncheckedSecondaryContentColor =
+                disabledUncheckedSecondaryContentColor.takeOrElse {
+                    this.disabledUncheckedSecondaryContentColor
+                },
+            disabledUncheckedIconColor =
+                disabledUncheckedIconColor.takeOrElse { this.disabledUncheckedIconColor },
+            disabledUncheckedThumbColor =
+                disabledUncheckedThumbColor.takeOrElse { this.disabledUncheckedThumbColor },
+            disabledUncheckedTrackBorderColor =
+                disabledUncheckedTrackBorderColor.takeOrElse {
+                    this.disabledUncheckedTrackBorderColor
+                },
+        )
+
+    /**
+     * Determines the container color based on whether the [SwitchButton] is [enabled] and
+     * [checked].
+     *
+     * @param enabled Whether the [SwitchButton] is enabled
+     * @param checked Whether the [SwitchButton] is checked
+     */
+    @Composable
+    internal fun containerColor(enabled: Boolean, checked: Boolean): State<Color> =
+        animateSelectionColor(
+            enabled = enabled,
+            checked = checked,
+            checkedColor = checkedContainerColor,
+            uncheckedColor = uncheckedContainerColor,
+            disabledCheckedColor = disabledCheckedContainerColor,
+            disabledUncheckedColor = disabledUncheckedContainerColor,
+            animationSpec = COLOR_ANIMATION_SPEC
+        )
+
+    /**
+     * Determines the content color based on whether the [SwitchButton] is [enabled] and [checked].
+     *
+     * @param enabled Whether the [SwitchButton] is enabled
+     * @param checked Whether the [SwitchButton] is checked
+     */
+    @Composable
+    internal fun contentColor(enabled: Boolean, checked: Boolean): State<Color> =
+        animateSelectionColor(
+            enabled = enabled,
+            checked = checked,
+            checkedColor = checkedContentColor,
+            uncheckedColor = uncheckedContentColor,
+            disabledCheckedColor = disabledCheckedContentColor,
+            disabledUncheckedColor = disabledUncheckedContentColor,
+            animationSpec = COLOR_ANIMATION_SPEC
+        )
+
+    /**
+     * Represents the secondary content color depending on the [enabled] and [checked] properties.
+     *
+     * @param enabled Whether the [SwitchButton] is enabled.
+     * @param checked Whether the [SwitchButton] is currently checked or unchecked.
+     */
+    @Composable
+    internal fun secondaryContentColor(enabled: Boolean, checked: Boolean): State<Color> =
+        animateSelectionColor(
+            enabled = enabled,
+            checked = checked,
+            checkedColor = checkedSecondaryContentColor,
+            uncheckedColor = uncheckedSecondaryContentColor,
+            disabledCheckedColor = disabledCheckedSecondaryContentColor,
+            disabledUncheckedColor = disabledUncheckedSecondaryContentColor,
+            animationSpec = COLOR_ANIMATION_SPEC
+        )
+
+    /**
+     * Represents the icon color for the [SwitchButton] depending on the [enabled] and [checked]
+     * properties.
+     *
+     * @param enabled Whether the [SwitchButton] is enabled.
+     * @param checked Whether the [SwitchButton] is currently checked or unchecked.
+     */
+    @Composable
+    internal fun iconColor(enabled: Boolean, checked: Boolean): State<Color> =
+        animateSelectionColor(
+            enabled = enabled,
+            checked = checked,
+            checkedColor = checkedIconColor,
+            uncheckedColor = uncheckedIconColor,
+            disabledCheckedColor = disabledCheckedIconColor,
+            disabledUncheckedColor = disabledUncheckedIconColor,
+            animationSpec = COLOR_ANIMATION_SPEC
+        )
+
+    /**
+     * Represents the thumb color for the [SwitchButton] depending on the [enabled] and [checked]
+     * properties.
+     *
+     * @param enabled Whether the [SwitchButton] is enabled.
+     * @param checked Whether the [SwitchButton] is currently checked or unchecked.
+     */
+    @Composable
+    internal fun thumbColor(enabled: Boolean, checked: Boolean): State<Color> =
+        animateSelectionColor(
+            enabled = enabled,
+            checked = checked,
+            checkedColor = checkedThumbColor,
+            uncheckedColor = uncheckedThumbColor,
+            disabledCheckedColor = disabledCheckedThumbColor,
+            disabledUncheckedColor = disabledUncheckedThumbColor,
+            animationSpec = COLOR_ANIMATION_SPEC
+        )
+
+    /**
+     * Represents the thumb icon color for the [SwitchButton] depending on the [enabled] and
+     * [checked] properties.
+     *
+     * @param enabled Whether the [SwitchButton] is enabled.
+     * @param checked Whether the [SwitchButton] is currently checked or unchecked.
+     */
+    @Composable
+    internal fun thumbIconColor(enabled: Boolean, checked: Boolean): State<Color> =
+        animateSelectionColor(
+            enabled = enabled,
+            checked = checked,
+            checkedColor = checkedThumbIconColor,
+            uncheckedColor = Color.Transparent,
+            disabledCheckedColor = disabledCheckedThumbIconColor,
+            disabledUncheckedColor = Color.Transparent,
+            animationSpec = COLOR_ANIMATION_SPEC
+        )
+
+    /**
+     * Represents the track color for the [SwitchButton] depending on the [enabled] and [checked]
+     * properties.
+     *
+     * @param enabled Whether the [SwitchButton] is enabled.
+     * @param checked Whether the [SwitchButton] is currently checked or unchecked.
+     */
+    @Composable
+    internal fun trackColor(enabled: Boolean, checked: Boolean): State<Color> =
+        animateSelectionColor(
+            enabled = enabled,
+            checked = checked,
+            checkedColor = checkedTrackColor,
+            uncheckedColor = uncheckedTrackColor,
+            disabledCheckedColor = disabledCheckedTrackColor,
+            disabledUncheckedColor = Color.Transparent,
+            animationSpec = COLOR_ANIMATION_SPEC
+        )
+
+    /**
+     * Represents the track border color for the [SwitchButton] depending on the [enabled] and
+     * [checked] properties.
+     *
+     * @param enabled Whether the [SwitchButton] is enabled.
+     * @param checked Whether the [SwitchButton] is currently checked or unchecked.
+     */
+    @Composable
+    internal fun trackBorderColor(enabled: Boolean, checked: Boolean): State<Color> =
+        animateSelectionColor(
+            enabled = enabled,
+            checked = checked,
+            checkedColor = checkedTrackBorderColor,
+            uncheckedColor = uncheckedTrackBorderColor,
+            disabledCheckedColor = disabledCheckedTrackBorderColor,
+            disabledUncheckedColor = disabledUncheckedTrackBorderColor,
+            animationSpec = COLOR_ANIMATION_SPEC
+        )
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other == null) return false
+        if (this::class != other::class) return false
+
+        other as SwitchButtonColors
+
+        if (checkedContainerColor != other.checkedContainerColor) return false
+        if (checkedContentColor != other.checkedContentColor) return false
+        if (checkedSecondaryContentColor != other.checkedSecondaryContentColor) return false
+        if (checkedIconColor != other.checkedIconColor) return false
+        if (checkedThumbColor != other.checkedThumbColor) return false
+        if (checkedThumbIconColor != other.checkedThumbIconColor) return false
+        if (checkedTrackColor != other.checkedTrackColor) return false
+        if (checkedTrackBorderColor != other.checkedTrackBorderColor) return false
+        if (uncheckedContainerColor != other.uncheckedContainerColor) return false
+        if (uncheckedContentColor != other.uncheckedContentColor) return false
+        if (uncheckedSecondaryContentColor != other.uncheckedSecondaryContentColor) return false
+        if (uncheckedIconColor != other.uncheckedIconColor) return false
+        if (uncheckedThumbColor != other.uncheckedThumbColor) return false
+        if (uncheckedTrackColor != other.uncheckedTrackColor) return false
+        if (uncheckedTrackBorderColor != other.uncheckedTrackBorderColor) return false
+        if (disabledCheckedContainerColor != other.disabledCheckedContainerColor) return false
+        if (disabledCheckedContentColor != other.disabledCheckedContentColor) return false
+        if (disabledCheckedSecondaryContentColor != other.disabledCheckedSecondaryContentColor)
+            return false
+        if (disabledCheckedIconColor != other.disabledCheckedIconColor) return false
+        if (disabledCheckedThumbColor != other.disabledCheckedThumbColor) return false
+        if (disabledCheckedThumbIconColor != other.disabledCheckedThumbIconColor) return false
+        if (disabledCheckedTrackColor != other.disabledCheckedTrackColor) return false
+        if (disabledCheckedTrackBorderColor != other.disabledCheckedTrackBorderColor) return false
+        if (disabledUncheckedContainerColor != other.disabledUncheckedContainerColor) return false
+        if (disabledUncheckedContentColor != other.disabledUncheckedContentColor) return false
+        if (disabledUncheckedSecondaryContentColor != other.disabledUncheckedSecondaryContentColor)
+            return false
+        if (disabledUncheckedIconColor != other.disabledUncheckedIconColor) return false
+        if (disabledUncheckedThumbColor != other.disabledUncheckedThumbColor) return false
+        if (disabledUncheckedTrackBorderColor != other.disabledUncheckedTrackBorderColor)
+            return false
+
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = checkedContainerColor.hashCode()
+        result = 31 * result + checkedContentColor.hashCode()
+        result = 31 * result + checkedSecondaryContentColor.hashCode()
+        result = 31 * result + checkedIconColor.hashCode()
+        result = 31 * result + checkedThumbColor.hashCode()
+        result = 31 * result + checkedThumbIconColor.hashCode()
+        result = 31 * result + checkedTrackColor.hashCode()
+        result = 31 * result + checkedTrackBorderColor.hashCode()
+        result = 31 * result + uncheckedContainerColor.hashCode()
+        result = 31 * result + uncheckedContentColor.hashCode()
+        result = 31 * result + uncheckedSecondaryContentColor.hashCode()
+        result = 31 * result + uncheckedIconColor.hashCode()
+        result = 31 * result + uncheckedThumbColor.hashCode()
+        result = 31 * result + uncheckedTrackColor.hashCode()
+        result = 31 * result + uncheckedTrackBorderColor.hashCode()
+        result = 31 * result + disabledCheckedContainerColor.hashCode()
+        result = 31 * result + disabledCheckedContentColor.hashCode()
+        result = 31 * result + disabledCheckedSecondaryContentColor.hashCode()
+        result = 31 * result + disabledCheckedIconColor.hashCode()
+        result = 31 * result + disabledCheckedThumbColor.hashCode()
+        result = 31 * result + disabledCheckedThumbIconColor.hashCode()
+        result = 31 * result + disabledCheckedTrackColor.hashCode()
+        result = 31 * result + disabledCheckedTrackBorderColor.hashCode()
+        result = 31 * result + disabledUncheckedContainerColor.hashCode()
+        result = 31 * result + disabledUncheckedContentColor.hashCode()
+        result = 31 * result + disabledUncheckedSecondaryContentColor.hashCode()
+        result = 31 * result + disabledUncheckedIconColor.hashCode()
+        result = 31 * result + disabledUncheckedThumbColor.hashCode()
+        result = 31 * result + disabledUncheckedTrackBorderColor.hashCode()
+        return result
+    }
+}
+
+/**
+ * Represents the different colors used in [SplitSwitchButton] in different states.
+ *
+ * @param checkedContainerColor Container or background color when the [SplitSwitchButton] is
+ *   checked
+ * @param checkedContentColor Color of the content like label when the [SplitSwitchButton] is
+ *   checked
+ * @param checkedSecondaryContentColor Color of the secondary content like secondary label when the
+ *   [SplitSwitchButton] is checked
+ * @param checkedSplitContainerColor Split container color when the split toggle button is checked
+ * @param checkedThumbColor Color of the thumb when the [SplitSwitchButton] is checked
+ * @param checkedThumbIconColor Color of the thumb icon when the [SplitSwitchButton] is checked
+ * @param checkedTrackColor Color of the track when the [SplitSwitchButton] is checked
+ * @param checkedTrackBorderColor Color of the track border when the [SplitSwitchButton] is checked
+ * @param uncheckedContainerColor Container or background color when the [SplitSwitchButton] is
+ *   unchecked
+ * @param uncheckedContentColor Color of the content like label when the [SplitSwitchButton] is
+ *   unchecked
+ * @param uncheckedSecondaryContentColor Color of the secondary content like secondary label when
+ *   the split toggle button is unchecked
+ * @param uncheckedSplitContainerColor Split container color when the split toggle button is
+ *   unchecked
+ * @param uncheckedThumbColor Color of the thumb when the [SplitSwitchButton] is unchecked
+ * @param uncheckedTrackColor Color of the track when the [SplitSwitchButton] is unchecked
+ * @param uncheckedTrackBorderColor Color of the track border when the [SplitSwitchButton] is
+ *   unchecked
+ * @param disabledCheckedContainerColor Container color when the split toggle button is disabled and
+ *   checked
+ * @param disabledCheckedContentColor Color of the content like label when the split toggle button
+ *   is disabled and checked
+ * @param disabledCheckedSecondaryContentColor Color of the secondary content like secondary label
+ *   when the split toggle button is disabled and checked
+ * @param disabledCheckedSplitContainerColor Split container color when the split toggle button is
+ *   disabled and checked
+ * @param disabledCheckedThumbColor Color of the thumb when the [SplitSwitchButton] is disabled and
+ *   checked
+ * @param disabledCheckedThumbIconColor Color of the thumb icon when the [SplitSwitchButton] is
+ *   disabled and checked
+ * @param disabledCheckedTrackColor Color of the track when the [SplitSwitchButton] is disabled and
+ *   checked
+ * @param disabledCheckedTrackBorderColor Color of the track border when the [SplitSwitchButton] is
+ *   disabled and checked
+ * @param disabledUncheckedContainerColor Container color when the split toggle button is unchecked
+ *   and disabled
+ * @param disabledUncheckedContentColor Color of the content like label when the split toggle button
+ *   is unchecked and disabled
+ * @param disabledUncheckedSecondaryContentColor Color of the secondary content like secondary label
+ *   when the split toggle button is unchecked and disabled
+ * @param disabledUncheckedSplitContainerColor Split container color when the split toggle button is
+ *   unchecked and disabled
+ * @param disabledUncheckedThumbColor Color of the thumb when the [SplitSwitchButton] is disabled
+ *   and unchecked
+ * @param disabledUncheckedTrackBorderColor Color of the track border when the [SplitSwitchButton]
+ *   is disabled and unchecked
+ */
+class SplitSwitchButtonColors(
+    val checkedContainerColor: Color,
+    val checkedContentColor: Color,
+    val checkedSecondaryContentColor: Color,
+    val checkedSplitContainerColor: Color,
+    val checkedThumbColor: Color,
+    val checkedThumbIconColor: Color,
+    val checkedTrackColor: Color,
+    val checkedTrackBorderColor: Color,
+    val uncheckedContainerColor: Color,
+    val uncheckedContentColor: Color,
+    val uncheckedSecondaryContentColor: Color,
+    val uncheckedSplitContainerColor: Color,
+    val uncheckedThumbColor: Color,
+    val uncheckedTrackColor: Color,
+    val uncheckedTrackBorderColor: Color,
+    val disabledCheckedContainerColor: Color,
+    val disabledCheckedContentColor: Color,
+    val disabledCheckedSecondaryContentColor: Color,
+    val disabledCheckedSplitContainerColor: Color,
+    val disabledCheckedThumbColor: Color,
+    val disabledCheckedThumbIconColor: Color,
+    val disabledCheckedTrackColor: Color,
+    val disabledCheckedTrackBorderColor: Color,
+    val disabledUncheckedContainerColor: Color,
+    val disabledUncheckedContentColor: Color,
+    val disabledUncheckedSecondaryContentColor: Color,
+    val disabledUncheckedSplitContainerColor: Color,
+    val disabledUncheckedThumbColor: Color,
+    val disabledUncheckedTrackBorderColor: Color,
+) {
+    internal fun copy(
+        checkedContainerColor: Color,
+        checkedContentColor: Color,
+        checkedSecondaryContentColor: Color,
+        checkedSplitContainerColor: Color,
+        checkedThumbColor: Color,
+        checkedThumbIconColor: Color,
+        checkedTrackColor: Color,
+        checkedTrackBorderColor: Color,
+        uncheckedContainerColor: Color,
+        uncheckedContentColor: Color,
+        uncheckedSecondaryContentColor: Color,
+        uncheckedSplitContainerColor: Color,
+        uncheckedThumbColor: Color,
+        uncheckedTrackColor: Color,
+        uncheckedTrackBorderColor: Color,
+        disabledCheckedContainerColor: Color,
+        disabledCheckedContentColor: Color,
+        disabledCheckedSecondaryContentColor: Color,
+        disabledCheckedSplitContainerColor: Color,
+        disabledCheckedThumbColor: Color,
+        disabledCheckedThumbIconColor: Color,
+        disabledCheckedTrackColor: Color,
+        disabledCheckedTrackBorderColor: Color,
+        disabledUncheckedContainerColor: Color,
+        disabledUncheckedContentColor: Color,
+        disabledUncheckedSecondaryContentColor: Color,
+        disabledUncheckedSplitContainerColor: Color,
+        disabledUncheckedThumbColor: Color,
+        disabledUncheckedTrackBorderColor: Color,
+    ): SplitSwitchButtonColors =
+        SplitSwitchButtonColors(
+            checkedContainerColor = checkedContainerColor.takeOrElse { this.checkedContainerColor },
+            checkedContentColor = checkedContentColor.takeOrElse { this.checkedContentColor },
+            checkedSecondaryContentColor =
+                checkedSecondaryContentColor.takeOrElse { this.checkedSecondaryContentColor },
+            checkedSplitContainerColor =
+                checkedSplitContainerColor.takeOrElse { this.checkedSplitContainerColor },
+            checkedThumbColor = checkedThumbColor.takeOrElse { this.checkedThumbColor },
+            checkedThumbIconColor = checkedThumbIconColor.takeOrElse { this.checkedThumbIconColor },
+            checkedTrackColor = checkedTrackColor.takeOrElse { this.checkedTrackColor },
+            checkedTrackBorderColor =
+                checkedTrackBorderColor.takeOrElse { this.checkedTrackBorderColor },
+            uncheckedContainerColor =
+                uncheckedContainerColor.takeOrElse { this.uncheckedContainerColor },
+            uncheckedContentColor = uncheckedContentColor.takeOrElse { this.uncheckedContentColor },
+            uncheckedSecondaryContentColor =
+                uncheckedSecondaryContentColor.takeOrElse { this.uncheckedSecondaryContentColor },
+            uncheckedSplitContainerColor =
+                uncheckedSplitContainerColor.takeOrElse { this.uncheckedSplitContainerColor },
+            uncheckedThumbColor = uncheckedThumbColor.takeOrElse { this.uncheckedThumbColor },
+            uncheckedTrackColor = uncheckedTrackColor.takeOrElse { this.uncheckedTrackColor },
+            uncheckedTrackBorderColor =
+                uncheckedTrackBorderColor.takeOrElse { this.uncheckedTrackBorderColor },
+            disabledCheckedContainerColor =
+                disabledCheckedContainerColor.takeOrElse { this.disabledCheckedContainerColor },
+            disabledCheckedContentColor =
+                disabledCheckedContentColor.takeOrElse { this.disabledCheckedContentColor },
+            disabledCheckedSecondaryContentColor =
+                disabledCheckedSecondaryContentColor.takeOrElse {
+                    this.disabledCheckedSecondaryContentColor
+                },
+            disabledCheckedSplitContainerColor =
+                disabledCheckedSplitContainerColor.takeOrElse {
+                    this.disabledCheckedSplitContainerColor
+                },
+            disabledCheckedThumbColor =
+                disabledCheckedThumbColor.takeOrElse { this.disabledCheckedThumbColor },
+            disabledCheckedThumbIconColor =
+                disabledCheckedThumbIconColor.takeOrElse { this.disabledCheckedThumbIconColor },
+            disabledCheckedTrackColor =
+                disabledCheckedTrackColor.takeOrElse { this.disabledCheckedTrackColor },
+            disabledCheckedTrackBorderColor =
+                disabledCheckedTrackBorderColor.takeOrElse { this.disabledCheckedTrackBorderColor },
+            disabledUncheckedContainerColor =
+                disabledUncheckedContainerColor.takeOrElse { this.disabledUncheckedContainerColor },
+            disabledUncheckedContentColor =
+                disabledUncheckedContentColor.takeOrElse { this.disabledUncheckedContentColor },
+            disabledUncheckedSecondaryContentColor =
+                disabledUncheckedSecondaryContentColor.takeOrElse {
+                    this.disabledUncheckedSecondaryContentColor
+                },
+            disabledUncheckedSplitContainerColor =
+                disabledUncheckedSplitContainerColor.takeOrElse {
+                    this.disabledUncheckedSplitContainerColor
+                },
+            disabledUncheckedThumbColor =
+                disabledUncheckedThumbColor.takeOrElse { this.disabledUncheckedThumbColor },
+            disabledUncheckedTrackBorderColor =
+                disabledUncheckedTrackBorderColor.takeOrElse {
+                    this.disabledUncheckedTrackBorderColor
+                },
+        )
+
+    /**
+     * Determines the container color based on whether the [SplitSwitchButton] is [enabled] and
+     * [checked].
+     *
+     * @param enabled Whether the [SplitSwitchButton] is enabled
+     * @param checked Whether the [SplitSwitchButton] is currently checked
+     */
+    @Composable
+    internal fun containerColor(enabled: Boolean, checked: Boolean): State<Color> =
+        animateSelectionColor(
+            enabled = enabled,
+            checked = checked,
+            checkedColor = checkedContainerColor,
+            uncheckedColor = uncheckedContainerColor,
+            disabledCheckedColor = disabledCheckedContainerColor,
+            disabledUncheckedColor = disabledUncheckedContainerColor,
+            animationSpec = COLOR_ANIMATION_SPEC
+        )
+
+    /**
+     * Determines the content color based on whether the [SplitSwitchButton] is [enabled] and
+     * [checked].
+     *
+     * @param enabled Whether the [SplitSwitchButton] is enabled
+     * @param checked Whether the [SplitSwitchButton] is currently checked
+     */
+    @Composable
+    internal fun contentColor(enabled: Boolean, checked: Boolean): State<Color> =
+        animateSelectionColor(
+            enabled = enabled,
+            checked = checked,
+            checkedColor = checkedContentColor,
+            uncheckedColor = uncheckedContentColor,
+            disabledCheckedColor = disabledCheckedContentColor,
+            disabledUncheckedColor = disabledUncheckedContentColor,
+            animationSpec = COLOR_ANIMATION_SPEC
+        )
+
+    /**
+     * Represents the secondary content color for the [SplitSwitchButton] depending on the [enabled]
+     * and [checked] properties.
+     *
+     * @param enabled Whether the [SplitSwitchButton] is enabled.
+     * @param checked Whether the [SplitSwitchButton] is currently checked or unchecked.
+     */
+    @Composable
+    internal fun secondaryContentColor(enabled: Boolean, checked: Boolean): State<Color> =
+        animateSelectionColor(
+            enabled = enabled,
+            checked = checked,
+            checkedColor = checkedSecondaryContentColor,
+            uncheckedColor = uncheckedSecondaryContentColor,
+            disabledCheckedColor = disabledCheckedSecondaryContentColor,
+            disabledUncheckedColor = disabledUncheckedSecondaryContentColor,
+            animationSpec = COLOR_ANIMATION_SPEC
+        )
+
+    /**
+     * Represents the split container for the [SplitSwitchButton] color depending on the [enabled]
+     * and [checked] properties.
+     *
+     * @param enabled Whether the [SplitSwitchButton] is enabled.
+     * @param checked Whether the [SplitSwitchButton] is currently checked or unchecked.
+     */
+    @Composable
+    internal fun splitContainerColor(enabled: Boolean, checked: Boolean): State<Color> =
+        animateSelectionColor(
+            enabled = enabled,
+            checked = checked,
+            checkedColor = checkedSplitContainerColor,
+            uncheckedColor = uncheckedSplitContainerColor,
+            disabledCheckedColor = disabledCheckedSplitContainerColor,
+            disabledUncheckedColor = disabledUncheckedSplitContainerColor,
+            animationSpec = COLOR_ANIMATION_SPEC
+        )
+
+    /**
+     * Represents the thumb color for the [SwitchButton] depending on the [enabled] and [checked]
+     * properties.
+     *
+     * @param enabled Whether the [SwitchButton] is enabled.
+     * @param checked Whether the [SwitchButton] is currently checked or unchecked.
+     */
+    @Composable
+    internal fun thumbColor(enabled: Boolean, checked: Boolean): State<Color> =
+        animateSelectionColor(
+            enabled = enabled,
+            checked = checked,
+            checkedColor = checkedThumbColor,
+            uncheckedColor = uncheckedThumbColor,
+            disabledCheckedColor = disabledCheckedThumbColor,
+            disabledUncheckedColor = disabledUncheckedThumbColor,
+            animationSpec = COLOR_ANIMATION_SPEC
+        )
+
+    /**
+     * Represents the thumb icon color for the [SwitchButton] depending on the [enabled] and
+     * [checked] properties.
+     *
+     * @param enabled Whether the [SwitchButton] is enabled.
+     * @param checked Whether the [SwitchButton] is currently checked or unchecked.
+     */
+    @Composable
+    internal fun thumbIconColor(enabled: Boolean, checked: Boolean): State<Color> =
+        animateSelectionColor(
+            enabled = enabled,
+            checked = checked,
+            checkedColor = checkedThumbIconColor,
+            uncheckedColor = Color.Transparent,
+            disabledCheckedColor = disabledCheckedThumbIconColor,
+            disabledUncheckedColor = Color.Transparent,
+            animationSpec = COLOR_ANIMATION_SPEC
+        )
+
+    /**
+     * Represents the track color for the [SwitchButton] depending on the [enabled] and [checked]
+     * properties.
+     *
+     * @param enabled Whether the [SwitchButton] is enabled.
+     * @param checked Whether the [SwitchButton] is currently checked or unchecked.
+     */
+    @Composable
+    internal fun trackColor(enabled: Boolean, checked: Boolean): State<Color> =
+        animateSelectionColor(
+            enabled = enabled,
+            checked = checked,
+            checkedColor = checkedTrackColor,
+            uncheckedColor = uncheckedTrackColor,
+            disabledCheckedColor = disabledCheckedTrackColor,
+            disabledUncheckedColor = Color.Transparent,
+            animationSpec = COLOR_ANIMATION_SPEC
+        )
+
+    /**
+     * Represents the track border color for the [SwitchButton] depending on the [enabled] and
+     * [checked] properties.
+     *
+     * @param enabled Whether the [SwitchButton] is enabled.
+     * @param checked Whether the [SwitchButton] is currently checked or unchecked.
+     */
+    @Composable
+    internal fun trackBorderColor(enabled: Boolean, checked: Boolean): State<Color> =
+        animateSelectionColor(
+            enabled = enabled,
+            checked = checked,
+            checkedColor = checkedTrackBorderColor,
+            uncheckedColor = uncheckedTrackBorderColor,
+            disabledCheckedColor = disabledCheckedTrackBorderColor,
+            disabledUncheckedColor = disabledUncheckedTrackBorderColor,
+            animationSpec = COLOR_ANIMATION_SPEC
+        )
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other == null) return false
+        if (this::class != other::class) return false
+
+        other as SplitSwitchButtonColors
+
+        if (checkedContainerColor != other.checkedContainerColor) return false
+        if (checkedContentColor != other.checkedContentColor) return false
+        if (checkedSecondaryContentColor != other.checkedSecondaryContentColor) return false
+        if (checkedSplitContainerColor != other.checkedSplitContainerColor) return false
+        if (checkedThumbColor != other.checkedThumbColor) return false
+        if (checkedThumbIconColor != other.checkedThumbIconColor) return false
+        if (checkedTrackColor != other.checkedTrackColor) return false
+        if (checkedTrackBorderColor != other.checkedTrackBorderColor) return false
+        if (uncheckedContainerColor != other.uncheckedContainerColor) return false
+        if (uncheckedContentColor != other.uncheckedContentColor) return false
+        if (uncheckedSecondaryContentColor != other.uncheckedSecondaryContentColor) return false
+        if (uncheckedSplitContainerColor != other.uncheckedSplitContainerColor) return false
+        if (uncheckedThumbColor != other.uncheckedThumbColor) return false
+        if (uncheckedTrackColor != other.uncheckedTrackColor) return false
+        if (uncheckedTrackBorderColor != other.uncheckedTrackBorderColor) return false
+        if (disabledCheckedContainerColor != other.disabledCheckedContainerColor) return false
+        if (disabledCheckedContentColor != other.disabledCheckedContentColor) return false
+        if (disabledCheckedSecondaryContentColor != other.disabledCheckedSecondaryContentColor)
+            return false
+        if (disabledCheckedSplitContainerColor != other.disabledCheckedSplitContainerColor)
+            return false
+        if (disabledCheckedThumbColor != other.disabledCheckedThumbColor) return false
+        if (disabledCheckedThumbIconColor != other.disabledCheckedThumbIconColor) return false
+        if (disabledCheckedTrackColor != other.disabledCheckedTrackColor) return false
+        if (disabledCheckedTrackBorderColor != other.disabledCheckedTrackBorderColor) return false
+        if (disabledUncheckedContainerColor != other.disabledUncheckedContainerColor) return false
+        if (disabledUncheckedContentColor != other.disabledUncheckedContentColor) return false
+        if (disabledUncheckedSecondaryContentColor != other.disabledUncheckedSecondaryContentColor)
+            return false
+        if (disabledUncheckedSplitContainerColor != other.disabledUncheckedSplitContainerColor)
+            return false
+        if (disabledUncheckedThumbColor != other.disabledUncheckedThumbColor) return false
+        if (disabledUncheckedTrackBorderColor != other.disabledUncheckedTrackBorderColor)
+            return false
+
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = checkedContainerColor.hashCode()
+        result = 31 * result + checkedContentColor.hashCode()
+        result = 31 * result + checkedSecondaryContentColor.hashCode()
+        result = 31 * result + checkedSplitContainerColor.hashCode()
+        result = 31 * result + checkedThumbColor.hashCode()
+        result = 31 * result + checkedThumbIconColor.hashCode()
+        result = 31 * result + checkedTrackColor.hashCode()
+        result = 31 * result + checkedTrackBorderColor.hashCode()
+        result = 31 * result + uncheckedContainerColor.hashCode()
+        result = 31 * result + uncheckedContentColor.hashCode()
+        result = 31 * result + uncheckedSecondaryContentColor.hashCode()
+        result = 31 * result + uncheckedSplitContainerColor.hashCode()
+        result = 31 * result + uncheckedThumbColor.hashCode()
+        result = 31 * result + uncheckedTrackColor.hashCode()
+        result = 31 * result + uncheckedTrackBorderColor.hashCode()
+        result = 31 * result + disabledCheckedContainerColor.hashCode()
+        result = 31 * result + disabledCheckedContentColor.hashCode()
+        result = 31 * result + disabledCheckedSecondaryContentColor.hashCode()
+        result = 31 * result + disabledCheckedSplitContainerColor.hashCode()
+        result = 31 * result + disabledCheckedThumbColor.hashCode()
+        result = 31 * result + disabledCheckedThumbIconColor.hashCode()
+        result = 31 * result + disabledCheckedTrackColor.hashCode()
+        result = 31 * result + disabledCheckedTrackBorderColor.hashCode()
+        result = 31 * result + disabledUncheckedContainerColor.hashCode()
+        result = 31 * result + disabledUncheckedContentColor.hashCode()
+        result = 31 * result + disabledUncheckedSecondaryContentColor.hashCode()
+        result = 31 * result + disabledUncheckedSplitContainerColor.hashCode()
+        result = 31 * result + disabledUncheckedThumbColor.hashCode()
+        result = 31 * result + disabledUncheckedTrackBorderColor.hashCode()
+        return result
+    }
+}
+
+// [Switch] provides an animated switch for use as a toggle control in
+// [SwitchButton] or [SplitSwitchButton].
+@Composable
+private fun Switch(
+    checked: Boolean,
+    enabled: Boolean,
+    thumbColor: @Composable (enabled: Boolean, checked: Boolean) -> State<Color>,
+    thumbIconColor: @Composable (enabled: Boolean, checked: Boolean) -> State<Color>,
+    trackColor: @Composable (enabled: Boolean, checked: Boolean) -> State<Color>,
+    trackBorderColor: @Composable (enabled: Boolean, checked: Boolean) -> State<Color>,
+    modifier: Modifier = Modifier,
+) {
+    val isRtl = isLayoutDirectionRtl()
+    val targetState = if (checked) SelectionStage.Checked else SelectionStage.Unchecked
+    val transition = updateTransition(targetState, label = "switchTransition")
+    val thumbProgress =
+        transition.animateFloat(
+            transitionSpec = { SWITCH_PROGRESS_ANIMATION_SPEC },
+            label = "switchTransition"
+        ) {
+            when (it) {
+                SelectionStage.Unchecked -> 0f
+                SelectionStage.Checked -> 1f
+            }
+        }
+    val actualThumbColor = thumbColor(enabled, checked).value
+    val actualThumbIconColor = thumbIconColor(enabled, checked).value
+    val actualTrackColor = trackColor(enabled, checked).value
+    val actualTrackBorderColor = trackBorderColor(enabled, checked).value
+    Box(
+        modifier =
+            modifier
+                .semantics { this.role = Role.Switch }
+                .height(SWITCH_INNER_HEIGHT)
+                .width(SWITCH_WIDTH)
+                .border(
+                    width = SWITCH_TRACK_WIDTH,
+                    shape = CircleShape,
+                    color =
+                        if (actualTrackColor == actualTrackBorderColor) {
+                            Color.Transparent
+                        } else {
+                            actualTrackBorderColor
+                        }
+                )
+                .background(color = actualTrackColor, shape = CircleShape)
+                .drawBehind {
+                    drawThumbAndTick(
+                        enabled,
+                        checked,
+                        actualThumbColor,
+                        thumbProgress.value,
+                        actualThumbIconColor,
+                        isRtl
+                    )
+                }
+                .wrapContentSize(Alignment.CenterEnd)
+    )
+}
+
+private fun DrawScope.drawThumbAndTick(
+    enabled: Boolean,
+    checked: Boolean,
+    thumbColor: Color,
+    progress: Float,
+    thumbIconColor: Color,
+    isRtl: Boolean
+) {
+
+    val thumbPaddingUnchecked = SWITCH_INNER_HEIGHT / 2 - THUMB_RADIUS_UNCHECKED
+    val thumbPaddingChecked = SWITCH_INNER_HEIGHT / 2 - THUMB_RADIUS_CHECKED
+
+    val switchThumbRadiusPx =
+        lerp(
+            start = THUMB_RADIUS_UNCHECKED.toPx(),
+            stop = THUMB_RADIUS_CHECKED.toPx(),
+            fraction = progress
+        )
+
+    val switchTrackLengthPx = SWITCH_WIDTH.toPx()
+
+    // For Rtl mode the thumb progress will start from the end of the switch.
+    val thumbProgressPx =
+        if (isRtl)
+            lerp(
+                start = switchTrackLengthPx - switchThumbRadiusPx - thumbPaddingUnchecked.toPx(),
+                stop = switchThumbRadiusPx + thumbPaddingChecked.toPx(),
+                fraction = progress
+            )
+        else
+            lerp(
+                start = switchThumbRadiusPx + thumbPaddingUnchecked.toPx(),
+                stop = switchTrackLengthPx - switchThumbRadiusPx - thumbPaddingChecked.toPx(),
+                fraction = progress
+            )
+
+    drawCircle(
+        color = thumbColor,
+        radius = switchThumbRadiusPx,
+        center = Offset(thumbProgressPx, center.y)
+    )
+
+    val ltrAdditionalOffset = 5.dp.toPx()
+    val rtlAdditionalOffset = 6.dp.toPx()
+
+    val totalDist = switchTrackLengthPx - 2 * switchThumbRadiusPx - ltrAdditionalOffset
+
+    // Offset value to be added if RTL mode is enabled.
+    // We need to move the tick to the checked position in ltr mode when unchecked.
+    val rtlOffset = switchTrackLengthPx - 2 * THUMB_RADIUS_CHECKED.toPx() - rtlAdditionalOffset
+
+    val distMoved = if (isRtl) rtlOffset - progress * totalDist else progress * totalDist
+
+    // Draw tick icon
+    animateTick(
+        enabled = enabled,
+        checked = checked,
+        tickColor = thumbIconColor,
+        tickProgress = progress,
+        startXOffset = distMoved.toDp()
+    )
+}
+
+private val SWITCH_WIDTH = 32.dp
+private val SWITCH_OUTER_HEIGHT = 24.dp
+private val SWITCH_INNER_HEIGHT = 22.dp
+private val SWITCH_TRACK_WIDTH = 2.dp
+private val THUMB_RADIUS_UNCHECKED = 6.dp
+private val THUMB_RADIUS_CHECKED = 9.dp
+private val TOGGLE_CONTROL_SPACING = 6.dp
+private val ICON_SPACING = 6.dp
+private val MIN_HEIGHT = 52.dp
+
+private val COLOR_ANIMATION_SPEC: AnimationSpec<Color> =
+    tween(MotionTokens.DurationMedium1, 0, MotionTokens.EasingStandardDecelerate)
+private val SWITCH_PROGRESS_ANIMATION_SPEC: TweenSpec<Float> =
+    tween(MotionTokens.DurationMedium2, 0, MotionTokens.EasingStandardDecelerate)
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/TimeText.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/TimeText.kt
index ecd66ef..4ccd05a 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/TimeText.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/TimeText.kt
@@ -58,6 +58,7 @@
 import androidx.wear.compose.foundation.curvedRow
 import androidx.wear.compose.foundation.padding
 import androidx.wear.compose.foundation.sizeIn
+import androidx.wear.compose.foundation.weight
 import androidx.wear.compose.material3.TimeTextDefaults.CurvedTextSeparator
 import androidx.wear.compose.material3.TimeTextDefaults.TextSeparator
 import androidx.wear.compose.material3.TimeTextDefaults.timeFormat
@@ -176,10 +177,8 @@
 
 /** Contains the default values used by [TimeText]. */
 object TimeTextDefaults {
-
-    /** By default, TimeText has 2.dp screen padding from the top. */
-    private val Padding = 2.dp
-
+    /** The default padding from the edge of the screen. */
+    private val Padding = ScaffoldDefaults.edgePadding
     /** Default format for 24h clock. */
     const val TimeFormat24Hours = "HH:mm"
 
@@ -211,7 +210,7 @@
 
     /**
      * Creates a [TextStyle] with default parameters used for showing time on square screens. By
-     * default a copy of MaterialTheme.typography.labelSmall style is created.
+     * default a copy of MaterialTheme.typography.arcMedium style is created.
      *
      * @param background The background color.
      * @param color The main color.
@@ -223,7 +222,7 @@
         color: Color = MaterialTheme.colorScheme.onBackground,
         fontSize: TextUnit = TextUnit.Unspecified,
     ) =
-        MaterialTheme.typography.labelSmall +
+        MaterialTheme.typography.arcMedium +
             TextStyle(color = color, background = background, fontSize = fontSize)
 
     /**
@@ -303,7 +302,8 @@
         scope.curvedText(
             text = text,
             overflow = TextOverflow.Ellipsis,
-            style = CurvedTextStyle(style = contentTextStyle.merge(style))
+            style = CurvedTextStyle(style = contentTextStyle.merge(style)),
+            modifier = CurvedModifier.weight(1f)
         )
     }
 
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ToggleButton.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ToggleButton.kt
index 4e360e8..cc9cc49 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ToggleButton.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ToggleButton.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 The Android Open Source Project
+ * Copyright 2024 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,702 +18,43 @@
 
 import androidx.compose.animation.core.AnimationSpec
 import androidx.compose.animation.core.tween
-import androidx.compose.foundation.background
-import androidx.compose.foundation.interaction.Interaction
-import androidx.compose.foundation.interaction.MutableInteractionSource
-import androidx.compose.foundation.layout.BoxScope
-import androidx.compose.foundation.layout.IntrinsicSize
-import androidx.compose.foundation.layout.PaddingValues
-import androidx.compose.foundation.layout.RowScope
-import androidx.compose.foundation.layout.defaultMinSize
-import androidx.compose.foundation.layout.height
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.Immutable
 import androidx.compose.runtime.State
-import androidx.compose.runtime.remember
-import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.Shape
 import androidx.compose.ui.graphics.takeOrElse
-import androidx.compose.ui.unit.dp
 import androidx.wear.compose.material3.tokens.MotionTokens
-import androidx.wear.compose.material3.tokens.SplitToggleButtonTokens
-import androidx.wear.compose.material3.tokens.ToggleButtonTokens
 import androidx.wear.compose.materialcore.animateSelectionColor
 
 /**
- * The Wear Material [ToggleButton] offers four slots and a specific layout for an icon, a label, a
- * secondaryLabel and toggle control (such as [Switch]). The icon and secondaryLabel are optional.
- * The items are laid out in a row with the optional icon at the start, a column containing the two
- * label slots in the middle and a slot for the toggle control at the end.
- *
- * The [ToggleButton] is Stadium shaped and has a max height designed to take no more than two lines
- * of text. With localisation and/or large font sizes, the [ToggleButton] height adjusts to
- * accommodate the contents. The label and secondary label should be start aligned.
- *
- * Example of a ToggleButton with a Switch:
- *
- * @sample androidx.wear.compose.material3.samples.ToggleButtonWithSwitch
- *
- * [ToggleButton] can be enabled or disabled. A disabled button will not respond to click events.
- *
- * The recommended set of [ToggleButton] colors can be obtained from [ToggleButtonDefaults], e.g.
- * [ToggleButtonDefaults.toggleButtonColors].
- *
- * @param checked Boolean flag indicating whether this button is currently checked.
- * @param onCheckedChange Callback to be invoked when this buttons checked status is changed.
- * @param toggleControl A slot for providing the button's toggle control. One built-in type of
- *   toggle control is supported: [Switch].
- * @param modifier Modifier to be applied to the [ToggleButton].
- * @param enabled Controls the enabled state of the button. When `false`, this button will not be
- *   clickable.
- * @param shape Defines the button's shape. It is strongly recommended to use the default as this
- *   shape is a key characteristic of the Wear Material Theme.
- * @param colors [ToggleButtonColors] that will be used to resolve the background and content color
- *   for this button in different states.
- * @param contentPadding The spacing values to apply internally between the container and the
- *   content.
- * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- *   emitting [Interaction]s for this button's "toggleable" tap area. You can use this to change the
- *   button's appearance or preview the button in different states. Note that if `null` is provided,
- *   interactions will still happen internally.
- * @param icon An optional slot for providing an icon to indicate the purpose of the button. The
- *   contents are expected to be a horizontally and vertically center aligned icon of size 24.dp.
- * @param secondaryLabel A slot for providing the button's secondary label. The contents are
- *   expected to be text which is "start" aligned.
- * @param label A slot for providing the button's main label. The contents are expected to be text
- *   which is "start" aligned.
- */
-@Composable
-fun ToggleButton(
-    checked: Boolean,
-    onCheckedChange: (Boolean) -> Unit,
-    toggleControl: @Composable ToggleControlScope.() -> Unit,
-    modifier: Modifier = Modifier,
-    enabled: Boolean = true,
-    shape: Shape = ToggleButtonDefaults.toggleButtonShape,
-    colors: ToggleButtonColors = ToggleButtonDefaults.toggleButtonColors(),
-    contentPadding: PaddingValues = ToggleButtonDefaults.ContentPadding,
-    interactionSource: MutableInteractionSource? = null,
-    icon: @Composable (BoxScope.() -> Unit)? = null,
-    secondaryLabel: @Composable (RowScope.() -> Unit)? = null,
-    label: @Composable RowScope.() -> Unit
-) =
-    androidx.wear.compose.materialcore.ToggleButton(
-        checked = checked,
-        onCheckedChange = onCheckedChange,
-        label =
-            provideScopeContent(
-                contentColor = colors.contentColor(enabled = enabled, checked),
-                textStyle = ToggleButtonTokens.LabelFont.value,
-                content = label
-            ),
-        toggleControl = {
-            val scope = remember(enabled, checked) { ToggleControlScope(enabled, checked) }
-            toggleControl(scope)
-        },
-        selectionControl = null,
-        modifier = modifier.defaultMinSize(minHeight = MIN_HEIGHT).height(IntrinsicSize.Min),
-        icon =
-            provideNullableScopeContent(
-                contentColor = colors.iconColor(enabled = enabled, checked),
-                content = icon
-            ),
-        secondaryLabel =
-            provideNullableScopeContent(
-                contentColor = colors.secondaryContentColor(enabled = enabled, checked),
-                textStyle = ToggleButtonTokens.SecondaryLabelFont.value,
-                content = secondaryLabel
-            ),
-        background = { isEnabled, isChecked ->
-            val backgroundColor =
-                colors.containerColor(enabled = isEnabled, checked = isChecked).value
-
-            Modifier.background(backgroundColor)
-        },
-        enabled = enabled,
-        interactionSource = interactionSource,
-        contentPadding = contentPadding,
-        shape = shape,
-        toggleControlWidth = TOGGLE_CONTROL_WIDTH,
-        toggleControlHeight = TOGGLE_CONTROL_HEIGHT,
-        labelSpacerSize = ToggleButtonDefaults.LabelSpacerSize,
-        toggleControlSpacing = TOGGLE_CONTROL_SPACING,
-        iconSpacing = ICON_SPACING,
-        ripple = ripple()
-    )
-
-/**
- * The Wear Material [SplitToggleButton] offers three slots and a specific layout for a label,
- * secondaryLabel and toggle control. The secondaryLabel is optional. The items are laid out with a
- * column containing the two label slots and a slot for the toggle control at the end.
- *
- * The [SplitToggleButton] is Stadium shaped and has a max height designed to take no more than two
- * lines of text. With localisation and/or large font sizes, the [SplitToggleButton] height adjusts
- * to accommodate the contents. The label and secondary label should be start aligned.
- *
- * A [SplitToggleButton] has two tappable areas, one tap area for the labels and another for the
- * toggle control. The [onClick] listener will be associated with the main body of the split toggle
- * button with the [onCheckedChange] listener associated with the toggle control area only.
- *
- * Example of a SplitToggleButton with a Switch:
- *
- * @sample androidx.wear.compose.material3.samples.SplitToggleButtonWithSwitch
- *
- * For a SplitToggleButton the background of the tappable background area behind the toggle control
- * will have a visual effect applied to provide a "divider" between the two tappable areas.
- *
- * The recommended set of colors can be obtained from [ToggleButtonDefaults], e.g.
- * [ToggleButtonDefaults.splitToggleButtonColors].
- *
- * [SplitToggleButton] can be enabled or disabled. A disabled button will not respond to click
- * events.
- *
- * @param checked Boolean flag indicating whether this button is currently checked.
- * @param onCheckedChange Callback to be invoked when this buttons checked status is changed.
- * @param onClick Click listener called when the user clicks the main body of the button, the area
- *   behind the labels.
- * @param toggleControl A slot for providing the button's toggle control. One built-in type of
- *   toggle control is supported: [Switch].
- * @param modifier Modifier to be applied to the button.
- * @param enabled Controls the enabled state of the button. When `false`, this button will not be
- *   clickable.
- * @param shape Defines the button's shape. It is strongly recommended to use the default as this
- *   shape is a key characteristic of the Wear Material Theme.
- * @param colors [SplitToggleButtonColors] that will be used to resolve the background and content
- *   color for this button in different states.
- * @param contentPadding The spacing values to apply internally between the container and the
- *   content.
- * @param checkedInteractionSource an optional hoisted [MutableInteractionSource] for observing and
- *   emitting [Interaction]s for this button's "toggleable" tap area. You can use this to change the
- *   button's appearance or preview the button in different states. Note that if `null` is provided,
- *   interactions will still happen internally.
- * @param clickInteractionSource an optional hoisted [MutableInteractionSource] for observing and
- *   emitting [Interaction]s for this button's "clickable" tap area. You can use this to change the
- *   button's appearance or preview the button in different states. Note that if `null` is provided,
- *   interactions will still happen internally.
- * @param secondaryLabel A slot for providing the button's secondary label. The contents are
- *   expected to be "start" aligned.
- * @param label A slot for providing the button's main label. The contents are expected to be text
- *   which is "start" aligned.
- */
-@Composable
-fun SplitToggleButton(
-    checked: Boolean,
-    onCheckedChange: (Boolean) -> Unit,
-    onClick: () -> Unit,
-    toggleControl: @Composable ToggleControlScope.() -> Unit,
-    modifier: Modifier = Modifier,
-    enabled: Boolean = true,
-    shape: Shape = ToggleButtonDefaults.splitToggleButtonShape,
-    colors: SplitToggleButtonColors = ToggleButtonDefaults.splitToggleButtonColors(),
-    checkedInteractionSource: MutableInteractionSource? = null,
-    clickInteractionSource: MutableInteractionSource? = null,
-    contentPadding: PaddingValues = ToggleButtonDefaults.ContentPadding,
-    secondaryLabel: @Composable (RowScope.() -> Unit)? = null,
-    label: @Composable RowScope.() -> Unit
-) =
-    androidx.wear.compose.materialcore.SplitToggleButton(
-        checked = checked,
-        onCheckedChange = onCheckedChange,
-        label =
-            provideScopeContent(
-                contentColor = colors.contentColor(enabled = enabled, checked = checked),
-                textStyle = SplitToggleButtonTokens.LabelFont.value,
-                content = label
-            ),
-        onClick = onClick,
-        toggleControl = {
-            val scope = remember(enabled, checked) { ToggleControlScope(enabled, checked) }
-            toggleControl(scope)
-        },
-        selectionControl = null,
-        modifier = modifier.defaultMinSize(minHeight = MIN_HEIGHT).height(IntrinsicSize.Min),
-        secondaryLabel =
-            provideNullableScopeContent(
-                contentColor = colors.secondaryContentColor(enabled = enabled, checked = checked),
-                textStyle = SplitToggleButtonTokens.SecondaryLabelFont.value,
-                content = secondaryLabel
-            ),
-        backgroundColor = { isEnabled, isChecked ->
-            colors.containerColor(enabled = isEnabled, checked = isChecked)
-        },
-        splitBackgroundColor = { isEnabled, isChecked ->
-            colors.splitContainerColor(enabled = isEnabled, checked = isChecked)
-        },
-        enabled = enabled,
-        checkedInteractionSource = checkedInteractionSource,
-        clickInteractionSource = clickInteractionSource,
-        onClickLabel = null,
-        contentPadding = contentPadding,
-        shape = shape,
-        labelSpacerSize = ToggleButtonDefaults.LabelSpacerSize,
-        ripple = ripple()
-    )
-
-/** Contains the default values used by [ToggleButton]s and [SplitToggleButton]s */
-object ToggleButtonDefaults {
-    /** Recommended [Shape] for [ToggleButton]. */
-    val toggleButtonShape: Shape
-        @Composable get() = ToggleButtonTokens.ContainerShape.value
-
-    /** Recommended [Shape] for [SplitToggleButton]. */
-    val splitToggleButtonShape: Shape
-        @Composable get() = SplitToggleButtonTokens.ContainerShape.value
-
-    /** Creates a [ToggleButtonColors] for use in a [ToggleButton]. */
-    @Composable fun toggleButtonColors() = MaterialTheme.colorScheme.defaultToggleButtonColors
-
-    /**
-     * Creates a [ToggleButtonColors] for use in a [ToggleButton].
-     *
-     * @param checkedContainerColor The container color of the [ToggleButton] when enabled and
-     *   checked.
-     * @param checkedContentColor The content color of the [ToggleButton] when enabled and checked.
-     * @param checkedSecondaryContentColor The secondary content color of the [ToggleButton] when
-     *   enabled and checked, used for secondaryLabel content.
-     * @param checkedIconColor The icon color of the [ToggleButton] when enabled and checked.
-     * @param uncheckedContainerColor The container color of the [ToggleButton] when enabled and
-     *   unchecked.
-     * @param uncheckedContentColor The content color of a [ToggleButton] when enabled and
-     *   unchecked.
-     * @param uncheckedSecondaryContentColor The secondary content color of this [ToggleButton] when
-     *   enabled and unchecked, used for secondaryLabel content
-     * @param uncheckedIconColor The icon color of the [ToggleButton] when enabled and unchecked.
-     * @param disabledCheckedContainerColor The container color of the [ToggleButton] when disabled
-     *   and checked.
-     * @param disabledCheckedContentColor The content color of the [ToggleButton] when disabled and
-     *   checked.
-     * @param disabledCheckedSecondaryContentColor The secondary content color of the [ToggleButton]
-     *   when disabled and checked, used for secondaryLabel content.
-     * @param disabledCheckedIconColor The icon color of the [ToggleButton] when disabled and
-     *   checked.
-     * @param disabledUncheckedContainerColor The container color of the [ToggleButton] when
-     *   disabled and unchecked.
-     * @param disabledUncheckedContentColor The content color of a [ToggleButton] when disabled and
-     *   unchecked.
-     * @param disabledUncheckedSecondaryContentColor The secondary content color of this
-     *   [ToggleButton] when disabled and unchecked, used for secondaryLabel content
-     * @param disabledUncheckedIconColor The icon color of the [ToggleButton] when disabled and
-     *   unchecked.
-     */
-    @Composable
-    fun toggleButtonColors(
-        checkedContainerColor: Color = Color.Unspecified,
-        checkedContentColor: Color = Color.Unspecified,
-        checkedSecondaryContentColor: Color = Color.Unspecified,
-        checkedIconColor: Color = Color.Unspecified,
-        uncheckedContainerColor: Color = Color.Unspecified,
-        uncheckedContentColor: Color = Color.Unspecified,
-        uncheckedSecondaryContentColor: Color = Color.Unspecified,
-        uncheckedIconColor: Color = Color.Unspecified,
-        disabledCheckedContainerColor: Color = Color.Unspecified,
-        disabledCheckedContentColor: Color = Color.Unspecified,
-        disabledCheckedSecondaryContentColor: Color = Color.Unspecified,
-        disabledCheckedIconColor: Color = Color.Unspecified,
-        disabledUncheckedContainerColor: Color = Color.Unspecified,
-        disabledUncheckedContentColor: Color = Color.Unspecified,
-        disabledUncheckedSecondaryContentColor: Color = Color.Unspecified,
-        disabledUncheckedIconColor: Color = Color.Unspecified,
-    ) =
-        MaterialTheme.colorScheme.defaultToggleButtonColors.copy(
-            checkedContainerColor = checkedContainerColor,
-            checkedContentColor = checkedContentColor,
-            checkedSecondaryContentColor = checkedSecondaryContentColor,
-            checkedIconColor = checkedIconColor,
-            uncheckedContainerColor = uncheckedContainerColor,
-            uncheckedContentColor = uncheckedContentColor,
-            uncheckedSecondaryContentColor = uncheckedSecondaryContentColor,
-            uncheckedIconColor = uncheckedIconColor,
-            disabledCheckedContainerColor = disabledCheckedContainerColor,
-            disabledCheckedContentColor = disabledCheckedContentColor,
-            disabledCheckedSecondaryContentColor = disabledCheckedSecondaryContentColor,
-            disabledCheckedIconColor = disabledCheckedIconColor,
-            disabledUncheckedContainerColor = disabledUncheckedContainerColor,
-            disabledUncheckedContentColor = disabledUncheckedContentColor,
-            disabledUncheckedSecondaryContentColor = disabledUncheckedSecondaryContentColor,
-            disabledUncheckedIconColor = disabledUncheckedIconColor,
-        )
-
-    /** Creates a [SplitToggleButtonColors] for use in a [SplitToggleButton]. */
-    @Composable
-    fun splitToggleButtonColors() = MaterialTheme.colorScheme.defaultSplitToggleButtonColors
-
-    /**
-     * Creates a [SplitToggleButtonColors] for use in a [SplitToggleButton].
-     *
-     * @param checkedContainerColor The container color of the [SplitToggleButton] when enabled and
-     *   checked.
-     * @param checkedContentColor The content color of the [SplitToggleButton] when enabled and
-     *   checked.
-     * @param checkedSecondaryContentColor The secondary content color of the [SplitToggleButton]
-     *   when enabled and checked, used for secondaryLabel content.
-     * @param checkedSplitContainerColor The split container color of the [SplitToggleButton] when
-     *   enabled and checked.
-     * @param uncheckedContainerColor The container color of the [SplitToggleButton] when enabled
-     *   and unchecked.
-     * @param uncheckedContentColor The content color of the [SplitToggleButton] when enabled and
-     *   unchecked.
-     * @param uncheckedSecondaryContentColor The secondary content color of the [SplitToggleButton]
-     *   when enabled and unchecked, used for secondaryLabel content.
-     * @param uncheckedSplitContainerColor The split container color of the [SplitToggleButton] when
-     *   enabled and unchecked.
-     * @param disabledCheckedContainerColor The container color of the [SplitToggleButton] when
-     *   disabled and checked.
-     * @param disabledCheckedContentColor The content color of the [SplitToggleButton] when disabled
-     *   and checked.
-     * @param disabledCheckedSecondaryContentColor The secondary content color of the
-     *   [SplitToggleButton] when disabled and checked, used for secondaryLabel content.
-     * @param disabledCheckedSplitContainerColor The split container color of the
-     *   [ SplitToggleButton] when disabled and checked.
-     * @param disabledUncheckedContainerColor The container color of the [SplitToggleButton] when
-     *   disabled and unchecked.
-     * @param disabledUncheckedContentColor The content color of the [SplitToggleButton] when
-     *   disabled and unchecked.
-     * @param disabledUncheckedSecondaryContentColor The secondary content color of the
-     *   [SplitToggleButton] when disabled and unchecked, used for secondaryLabel content.
-     * @param disabledUncheckedSplitContainerColor The split container color of the
-     *   [SplitToggleButton] when disabled and unchecked.
-     */
-    @Composable
-    fun splitToggleButtonColors(
-        checkedContainerColor: Color = Color.Unspecified,
-        checkedContentColor: Color = Color.Unspecified,
-        checkedSecondaryContentColor: Color = Color.Unspecified,
-        checkedSplitContainerColor: Color = Color.Unspecified,
-        uncheckedContainerColor: Color = Color.Unspecified,
-        uncheckedContentColor: Color = Color.Unspecified,
-        uncheckedSecondaryContentColor: Color = Color.Unspecified,
-        uncheckedSplitContainerColor: Color = Color.Unspecified,
-        disabledCheckedContainerColor: Color = Color.Unspecified,
-        disabledCheckedContentColor: Color = Color.Unspecified,
-        disabledCheckedSecondaryContentColor: Color = Color.Unspecified,
-        disabledCheckedSplitContainerColor: Color = Color.Unspecified,
-        disabledUncheckedContainerColor: Color = Color.Unspecified,
-        disabledUncheckedContentColor: Color = Color.Unspecified,
-        disabledUncheckedSecondaryContentColor: Color = Color.Unspecified,
-        disabledUncheckedSplitContainerColor: Color = Color.Unspecified,
-    ) =
-        MaterialTheme.colorScheme.defaultSplitToggleButtonColors.copy(
-            checkedContainerColor = checkedContainerColor,
-            checkedContentColor = checkedContentColor,
-            checkedSecondaryContentColor = checkedSecondaryContentColor,
-            checkedSplitContainerColor = checkedSplitContainerColor,
-            uncheckedContainerColor = uncheckedContainerColor,
-            uncheckedContentColor = uncheckedContentColor,
-            uncheckedSecondaryContentColor = uncheckedSecondaryContentColor,
-            uncheckedSplitContainerColor = uncheckedSplitContainerColor,
-            disabledCheckedContainerColor = disabledCheckedContainerColor,
-            disabledCheckedContentColor = disabledCheckedContentColor,
-            disabledCheckedSecondaryContentColor = disabledCheckedSecondaryContentColor,
-            disabledCheckedSplitContainerColor = disabledCheckedSplitContainerColor,
-            disabledUncheckedContainerColor = disabledUncheckedContainerColor,
-            disabledUncheckedContentColor = disabledUncheckedContentColor,
-            disabledUncheckedSecondaryContentColor = disabledUncheckedSecondaryContentColor,
-            disabledUncheckedSplitContainerColor = disabledUncheckedSplitContainerColor
-        )
-
-    internal val LabelSpacerSize = 2.dp
-    private val HorizontalPadding = 14.dp
-    private val VerticalPadding = 8.dp
-
-    /** The default content padding used by [ToggleButton] */
-    val ContentPadding: PaddingValues =
-        PaddingValues(
-            start = HorizontalPadding,
-            top = VerticalPadding,
-            end = HorizontalPadding,
-            bottom = VerticalPadding
-        )
-
-    private val ColorScheme.defaultToggleButtonColors: ToggleButtonColors
-        get() {
-            return defaultToggleButtonColorsCached
-                ?: ToggleButtonColors(
-                        checkedContainerColor = fromToken(ToggleButtonTokens.CheckedContainerColor),
-                        checkedContentColor = fromToken(ToggleButtonTokens.CheckedContentColor),
-                        checkedSecondaryContentColor =
-                            fromToken(ToggleButtonTokens.CheckedSecondaryLabelColor)
-                                .copy(alpha = ToggleButtonTokens.CheckedSecondaryLabelOpacity),
-                        checkedIconColor = fromToken(ToggleButtonTokens.CheckedIconColor),
-                        uncheckedContainerColor =
-                            fromToken(ToggleButtonTokens.UncheckedContainerColor),
-                        uncheckedContentColor = fromToken(ToggleButtonTokens.UncheckedContentColor),
-                        uncheckedSecondaryContentColor =
-                            fromToken(ToggleButtonTokens.UncheckedSecondaryLabelColor),
-                        uncheckedIconColor = fromToken(ToggleButtonTokens.UncheckedIconColor),
-                        disabledCheckedContainerColor =
-                            fromToken(ToggleButtonTokens.DisabledCheckedContainerColor)
-                                .toDisabledColor(
-                                    disabledAlpha =
-                                        ToggleButtonTokens.DisabledCheckedContainerOpacity
-                                ),
-                        disabledCheckedContentColor =
-                            fromToken(ToggleButtonTokens.DisabledCheckedContentColor)
-                                .toDisabledColor(
-                                    disabledAlpha = ToggleButtonTokens.DisabledOpacity
-                                ),
-                        disabledCheckedSecondaryContentColor =
-                            fromToken(ToggleButtonTokens.DisabledCheckedSecondaryLabelColor)
-                                .toDisabledColor(
-                                    disabledAlpha = ToggleButtonTokens.DisabledOpacity
-                                ),
-                        disabledCheckedIconColor =
-                            fromToken(ToggleButtonTokens.DisabledCheckedIconColor)
-                                .toDisabledColor(
-                                    disabledAlpha = ToggleButtonTokens.DisabledOpacity
-                                ),
-                        disabledUncheckedContainerColor =
-                            fromToken(ToggleButtonTokens.DisabledUncheckedContainerColor)
-                                .toDisabledColor(
-                                    disabledAlpha =
-                                        ToggleButtonTokens.DisabledUncheckedContainerOpacity
-                                ),
-                        disabledUncheckedContentColor =
-                            fromToken(ToggleButtonTokens.DisabledUncheckedContentColor)
-                                .toDisabledColor(
-                                    disabledAlpha = ToggleButtonTokens.DisabledOpacity
-                                ),
-                        disabledUncheckedSecondaryContentColor =
-                            fromToken(ToggleButtonTokens.DisabledUncheckedSecondaryLabelColor)
-                                .toDisabledColor(
-                                    disabledAlpha = ToggleButtonTokens.DisabledOpacity
-                                ),
-                        disabledUncheckedIconColor =
-                            fromToken(ToggleButtonTokens.DisabledUncheckedIconColor)
-                                .toDisabledColor(
-                                    disabledAlpha = ToggleButtonTokens.DisabledOpacity
-                                ),
-                    )
-                    .also { defaultToggleButtonColorsCached = it }
-        }
-
-    private val ColorScheme.defaultSplitToggleButtonColors: SplitToggleButtonColors
-        get() {
-            return defaultSplitToggleButtonColorsCached
-                ?: SplitToggleButtonColors(
-                        checkedContainerColor =
-                            fromToken(SplitToggleButtonTokens.CheckedContainerColor),
-                        checkedContentColor =
-                            fromToken(SplitToggleButtonTokens.CheckedContentColor),
-                        checkedSecondaryContentColor =
-                            fromToken(SplitToggleButtonTokens.CheckedSecondaryLabelColor)
-                                .copy(alpha = SplitToggleButtonTokens.CheckedSecondaryLabelOpacity),
-                        checkedSplitContainerColor =
-                            fromToken(SplitToggleButtonTokens.CheckedSplitContainerColor)
-                                .copy(alpha = SplitToggleButtonTokens.CheckedSplitContainerOpacity),
-                        uncheckedContainerColor =
-                            fromToken(SplitToggleButtonTokens.UncheckedContainerColor),
-                        uncheckedContentColor =
-                            fromToken(SplitToggleButtonTokens.UncheckedContentColor),
-                        uncheckedSecondaryContentColor =
-                            fromToken(SplitToggleButtonTokens.UncheckedSecondaryLabelColor),
-                        uncheckedSplitContainerColor =
-                            fromToken(SplitToggleButtonTokens.UncheckedSplitContainerColor),
-                        disabledCheckedContainerColor =
-                            fromToken(SplitToggleButtonTokens.DisabledCheckedContainerColor)
-                                .toDisabledColor(
-                                    disabledAlpha = SplitToggleButtonTokens.DisabledOpacity
-                                ),
-                        disabledCheckedContentColor =
-                            fromToken(SplitToggleButtonTokens.DisabledCheckedContentColor)
-                                .toDisabledColor(
-                                    disabledAlpha = SplitToggleButtonTokens.DisabledOpacity
-                                ),
-                        disabledCheckedSecondaryContentColor =
-                            fromToken(SplitToggleButtonTokens.DisabledCheckedSecondaryLabelColor)
-                                .copy(
-                                    alpha =
-                                        SplitToggleButtonTokens.DisabledCheckedSecondaryLabelOpacity
-                                )
-                                .toDisabledColor(
-                                    disabledAlpha = SplitToggleButtonTokens.DisabledOpacity
-                                ),
-                        disabledCheckedSplitContainerColor =
-                            fromToken(SplitToggleButtonTokens.DisabledCheckedSplitContainerColor)
-                                .copy(
-                                    alpha =
-                                        SplitToggleButtonTokens.DisabledCheckedSplitContainerOpacity
-                                )
-                                .toDisabledColor(
-                                    disabledAlpha = SplitToggleButtonTokens.DisabledOpacity
-                                ),
-                        disabledUncheckedContainerColor =
-                            fromToken(SplitToggleButtonTokens.DisabledUncheckedContainerColor)
-                                .toDisabledColor(
-                                    disabledAlpha = SplitToggleButtonTokens.DisabledOpacity
-                                ),
-                        disabledUncheckedContentColor =
-                            fromToken(SplitToggleButtonTokens.DisabledUncheckedContentColor)
-                                .toDisabledColor(
-                                    disabledAlpha = SplitToggleButtonTokens.DisabledOpacity
-                                ),
-                        disabledUncheckedSecondaryContentColor =
-                            fromToken(SplitToggleButtonTokens.DisabledUncheckedSecondaryLabelColor)
-                                .toDisabledColor(
-                                    disabledAlpha = SplitToggleButtonTokens.DisabledOpacity
-                                ),
-                        disabledUncheckedSplitContainerColor =
-                            fromToken(SplitToggleButtonTokens.DisabledUncheckedSplitContainerColor)
-                                .toDisabledColor(
-                                    disabledAlpha = SplitToggleButtonTokens.DisabledOpacity
-                                )
-                    )
-                    .also { defaultSplitToggleButtonColorsCached = it }
-        }
-}
-
-/**
- * Represents the different container and content colors used for toggle buttons ([ToggleButton],
- * [IconToggleButton], and [TextToggleButton]) in various states, that are checked, unchecked,
- * enabled and disabled.
+ * Represents the different container and content colors used for [IconToggleButton] and
+ * [TextToggleButton]) in various states, that are checked, unchecked, enabled and disabled.
  *
  * @param checkedContainerColor Container or background color when the toggle button is checked
- * @param checkedContentColor Color of the content like label when the toggle button is checked
- * @param checkedSecondaryContentColor Color of the secondary content like secondary label when the
- *   toggle button is checked
- * @param checkedIconColor Color of the icon when the toggle button is checked
+ * @param checkedContentColor Color of the content (text or icon) when the toggle button is checked
  * @param uncheckedContainerColor Container or background color when the toggle button is unchecked
- * @param uncheckedContentColor Color of the content like label when the toggle button is unchecked
- * @param uncheckedSecondaryContentColor Color of the secondary content like secondary label when
- *   the toggle button is unchecked
- * @param uncheckedIconColor Color of the icon when the toggle button is unchecked
+ * @param uncheckedContentColor Color of the content (text or icon) when the toggle button is
+ *   unchecked
  * @param disabledCheckedContainerColor Container or background color when the toggle button is
  *   disabled and checked
- * @param disabledCheckedContentColor Color of content like label when the toggle button is disabled
- *   and checked
- * @param disabledCheckedSecondaryContentColor Color of the secondary content like secondary label
- *   when the toggle button is disabled and checked
- * @param disabledCheckedIconColor Icon color when the toggle button is disabled and checked
+ * @param disabledCheckedContentColor Color of content (text or icon) when the toggle button is
+ *   disabled and checked
  * @param disabledUncheckedContainerColor Container or background color when the toggle button is
  *   disabled and unchecked
- * @param disabledUncheckedContentColor Color of the content like label when the toggle button is
- *   disabled and unchecked
- * @param disabledUncheckedSecondaryContentColor Color of the secondary content like secondary label
- *   when the toggle button is disabled and unchecked
- * @param disabledUncheckedIconColor Icon color when the toggle button is disabled and unchecked
- * @constructor [ToggleButtonColors] constructor to be used with [ToggleButton]
+ * @param disabledUncheckedContentColor Color of the content (text or icon) when the toggle button
+ *   is disabled and unchecked
  */
 @Immutable
-class ToggleButtonColors
-constructor(
+class ToggleButtonColors(
     val checkedContainerColor: Color,
     val checkedContentColor: Color,
-    val checkedSecondaryContentColor: Color,
-    val checkedIconColor: Color,
     val uncheckedContainerColor: Color,
     val uncheckedContentColor: Color,
-    val uncheckedSecondaryContentColor: Color,
-    val uncheckedIconColor: Color,
     val disabledCheckedContainerColor: Color,
     val disabledCheckedContentColor: Color,
-    val disabledCheckedSecondaryContentColor: Color,
-    val disabledCheckedIconColor: Color,
     val disabledUncheckedContainerColor: Color,
     val disabledUncheckedContentColor: Color,
-    val disabledUncheckedSecondaryContentColor: Color,
-    val disabledUncheckedIconColor: Color,
 ) {
-    /**
-     * [ToggleButtonColors] constructor for [IconToggleButton] and [TextToggleButton].
-     *
-     * @param checkedContainerColor Container or background color of the toggle button when checked
-     * @param checkedContentColor Color of the content (text or icon) of the toggle button when
-     *   checked
-     * @param uncheckedContainerColor Container or background color of the toggle button when
-     *   unchecked
-     * @param uncheckedContentColor Color of the content (text or icon) of the toggle button when
-     *   unchecked
-     * @param disabledCheckedContainerColor Container or background color of the toggle button when
-     *   disabled and checked
-     * @param disabledCheckedContentColor Color of the content (icon or text) toggle button when
-     *   disabled and unchecked
-     * @param disabledUncheckedContainerColor Container or background color of the toggle button
-     *   when disabled and unchecked
-     * @param disabledUncheckedContentColor Color of the content (icon or text) toggle button when
-     *   disabled and unchecked
-     */
-    constructor(
-        checkedContainerColor: Color,
-        checkedContentColor: Color,
-        uncheckedContainerColor: Color,
-        uncheckedContentColor: Color,
-        disabledCheckedContainerColor: Color,
-        disabledCheckedContentColor: Color,
-        disabledUncheckedContainerColor: Color,
-        disabledUncheckedContentColor: Color
-    ) : this(
-        checkedContainerColor = checkedContainerColor,
-        checkedContentColor = checkedContentColor,
-        checkedSecondaryContentColor = checkedContentColor,
-        checkedIconColor = checkedContentColor,
-        uncheckedContainerColor = uncheckedContainerColor,
-        uncheckedContentColor = uncheckedContentColor,
-        uncheckedSecondaryContentColor = uncheckedContentColor,
-        uncheckedIconColor = uncheckedContentColor,
-        disabledCheckedContainerColor = disabledCheckedContainerColor,
-        disabledCheckedContentColor = disabledCheckedContentColor,
-        disabledCheckedSecondaryContentColor = disabledCheckedContentColor,
-        disabledCheckedIconColor = disabledCheckedContentColor,
-        disabledUncheckedContainerColor = disabledUncheckedContainerColor,
-        disabledUncheckedContentColor = disabledUncheckedContentColor,
-        disabledUncheckedSecondaryContentColor = disabledUncheckedContentColor,
-        disabledUncheckedIconColor = disabledUncheckedContentColor,
-    )
-
-    internal fun copy(
-        checkedContainerColor: Color,
-        checkedContentColor: Color,
-        checkedSecondaryContentColor: Color,
-        checkedIconColor: Color,
-        uncheckedContainerColor: Color,
-        uncheckedContentColor: Color,
-        uncheckedSecondaryContentColor: Color,
-        uncheckedIconColor: Color,
-        disabledCheckedContainerColor: Color,
-        disabledCheckedContentColor: Color,
-        disabledCheckedSecondaryContentColor: Color,
-        disabledCheckedIconColor: Color,
-        disabledUncheckedContainerColor: Color,
-        disabledUncheckedContentColor: Color,
-        disabledUncheckedSecondaryContentColor: Color,
-        disabledUncheckedIconColor: Color,
-    ): ToggleButtonColors =
-        ToggleButtonColors(
-            checkedContainerColor = checkedContainerColor.takeOrElse { this.checkedContainerColor },
-            checkedContentColor = checkedContentColor.takeOrElse { this.checkedContentColor },
-            checkedSecondaryContentColor =
-                checkedSecondaryContentColor.takeOrElse { this.checkedSecondaryContentColor },
-            checkedIconColor = checkedIconColor.takeOrElse { this.checkedIconColor },
-            uncheckedContainerColor =
-                uncheckedContainerColor.takeOrElse { this.uncheckedContainerColor },
-            uncheckedContentColor = uncheckedContentColor.takeOrElse { this.uncheckedContentColor },
-            uncheckedSecondaryContentColor =
-                uncheckedSecondaryContentColor.takeOrElse { this.uncheckedSecondaryContentColor },
-            uncheckedIconColor = uncheckedIconColor.takeOrElse { this.uncheckedIconColor },
-            disabledCheckedContainerColor =
-                disabledCheckedContainerColor.takeOrElse { this.disabledCheckedContainerColor },
-            disabledCheckedContentColor =
-                disabledCheckedContentColor.takeOrElse { this.disabledCheckedContentColor },
-            disabledCheckedSecondaryContentColor =
-                disabledCheckedSecondaryContentColor.takeOrElse {
-                    this.disabledCheckedSecondaryContentColor
-                },
-            disabledCheckedIconColor =
-                disabledCheckedIconColor.takeOrElse { this.disabledCheckedIconColor },
-            disabledUncheckedContainerColor =
-                disabledUncheckedContainerColor.takeOrElse { this.disabledUncheckedContainerColor },
-            disabledUncheckedContentColor =
-                disabledUncheckedContentColor.takeOrElse { this.disabledUncheckedContentColor },
-            disabledUncheckedSecondaryContentColor =
-                disabledUncheckedSecondaryContentColor.takeOrElse {
-                    this.disabledUncheckedSecondaryContentColor
-                },
-            disabledUncheckedIconColor =
-                disabledUncheckedIconColor.takeOrElse { this.disabledUncheckedIconColor },
-        )
-
-    /** Copy function for [IconToggleButton] and [TextToggleButton]. */
     internal fun copy(
         checkedContainerColor: Color,
         checkedContentColor: Color,
@@ -776,43 +117,6 @@
             animationSpec = COLOR_ANIMATION_SPEC
         )
 
-    /**
-     * Represents the secondary content color depending on the [enabled] and [checked] properties.
-     *
-     * @param enabled Whether the ToggleButton is enabled.
-     * @param checked Whether the ToggleButton is currently checked or unchecked.
-     */
-    @Composable
-    internal fun secondaryContentColor(enabled: Boolean, checked: Boolean): State<Color> =
-        animateSelectionColor(
-            enabled = enabled,
-            checked = checked,
-            checkedColor = checkedSecondaryContentColor,
-            uncheckedColor = uncheckedSecondaryContentColor,
-            disabledCheckedColor = disabledCheckedSecondaryContentColor,
-            disabledUncheckedColor = disabledUncheckedSecondaryContentColor,
-            animationSpec = COLOR_ANIMATION_SPEC
-        )
-
-    /**
-     * Represents the icon color for the [ToggleButton] depending on the [enabled] and [checked]
-     * properties.
-     *
-     * @param enabled Whether the ToggleButton is enabled.
-     * @param checked Whether the ToggleButton is currently checked or unchecked.
-     */
-    @Composable
-    internal fun iconColor(enabled: Boolean, checked: Boolean): State<Color> =
-        animateSelectionColor(
-            enabled = enabled,
-            checked = checked,
-            checkedColor = checkedIconColor,
-            uncheckedColor = uncheckedIconColor,
-            disabledCheckedColor = disabledCheckedIconColor,
-            disabledUncheckedColor = disabledUncheckedIconColor,
-            animationSpec = COLOR_ANIMATION_SPEC
-        )
-
     override fun equals(other: Any?): Boolean {
         if (this === other) return true
         if (other == null) return false
@@ -822,22 +126,12 @@
 
         if (checkedContainerColor != other.checkedContainerColor) return false
         if (checkedContentColor != other.checkedContentColor) return false
-        if (checkedSecondaryContentColor != other.checkedSecondaryContentColor) return false
-        if (checkedIconColor != other.checkedIconColor) return false
         if (uncheckedContainerColor != other.uncheckedContainerColor) return false
         if (uncheckedContentColor != other.uncheckedContentColor) return false
-        if (uncheckedSecondaryContentColor != other.uncheckedSecondaryContentColor) return false
-        if (uncheckedIconColor != other.uncheckedIconColor) return false
         if (disabledCheckedContainerColor != other.disabledCheckedContainerColor) return false
         if (disabledCheckedContentColor != other.disabledCheckedContentColor) return false
-        if (disabledCheckedSecondaryContentColor != other.disabledCheckedSecondaryContentColor)
-            return false
-        if (disabledCheckedIconColor != other.disabledCheckedIconColor) return false
         if (disabledUncheckedContainerColor != other.disabledUncheckedContainerColor) return false
         if (disabledUncheckedContentColor != other.disabledUncheckedContentColor) return false
-        if (disabledUncheckedSecondaryContentColor != other.disabledUncheckedSecondaryContentColor)
-            return false
-        if (disabledUncheckedIconColor != other.disabledUncheckedIconColor) return false
 
         return true
     }
@@ -845,281 +139,15 @@
     override fun hashCode(): Int {
         var result = checkedContainerColor.hashCode()
         result = 31 * result + checkedContentColor.hashCode()
-        result = 31 * result + checkedSecondaryContentColor.hashCode()
-        result = 31 * result + checkedIconColor.hashCode()
         result = 31 * result + uncheckedContainerColor.hashCode()
         result = 31 * result + uncheckedContentColor.hashCode()
-        result = 31 * result + uncheckedSecondaryContentColor.hashCode()
-        result = 31 * result + uncheckedIconColor.hashCode()
         result = 31 * result + disabledCheckedContainerColor.hashCode()
         result = 31 * result + disabledCheckedContentColor.hashCode()
-        result = 31 * result + disabledCheckedSecondaryContentColor.hashCode()
-        result = 31 * result + disabledCheckedIconColor.hashCode()
         result = 31 * result + disabledUncheckedContainerColor.hashCode()
         result = 31 * result + disabledUncheckedContentColor.hashCode()
-        result = 31 * result + disabledUncheckedSecondaryContentColor.hashCode()
-        result = 31 * result + disabledUncheckedIconColor.hashCode()
         return result
     }
 }
 
-/**
- * Represents the different colors used in [SplitToggleButton] in different states.
- *
- * @param checkedContainerColor Container or background color when the split toggle button is
- *   checked
- * @param checkedContentColor Color of the content like label when the split toggle button is
- *   checked
- * @param checkedSecondaryContentColor Color of the secondary content like secondary label when the
- *   split toggle button is checked
- * @param checkedSplitContainerColor Split container color when the split toggle button is checked
- * @param uncheckedContainerColor Container or background color when the split toggle button is
- *   unchecked
- * @param uncheckedContentColor Color of the content like label when the split toggle button is
- *   unchecked
- * @param uncheckedSecondaryContentColor Color of the secondary content like secondary label when
- *   the split toggle button is unchecked
- * @param uncheckedSplitContainerColor Split container color when the split toggle button is
- *   unchecked
- * @param disabledCheckedContainerColor Container color when the split toggle button is disabled and
- *   checked
- * @param disabledCheckedContentColor Color of the content like label when the split toggle button
- *   is disabled and checked
- * @param disabledCheckedSecondaryContentColor Color of the secondary content like secondary label
- *   when the split toggle button is disabled and checked
- * @param disabledCheckedSplitContainerColor Split container color when the split toggle button is
- *   disabled and checked
- * @param disabledUncheckedContainerColor Container color when the split toggle button is unchecked
- *   and disabled
- * @param disabledUncheckedContentColor Color of the content like label when the split toggle button
- *   is unchecked and disabled
- * @param disabledUncheckedSecondaryContentColor Color of the secondary content like secondary label
- *   when the split toggle button is unchecked and disabled
- * @param disabledUncheckedSplitContainerColor Split container color when the split toggle button is
- *   unchecked and disabled
- * @constructor [SplitToggleButtonColors] constructor to be used with [SplitToggleButton]
- */
-class SplitToggleButtonColors
-constructor(
-    val checkedContainerColor: Color,
-    val checkedContentColor: Color,
-    val checkedSecondaryContentColor: Color,
-    val checkedSplitContainerColor: Color,
-    val uncheckedContainerColor: Color,
-    val uncheckedContentColor: Color,
-    val uncheckedSecondaryContentColor: Color,
-    val uncheckedSplitContainerColor: Color,
-    val disabledCheckedContainerColor: Color,
-    val disabledCheckedContentColor: Color,
-    val disabledCheckedSecondaryContentColor: Color,
-    val disabledCheckedSplitContainerColor: Color,
-    val disabledUncheckedContainerColor: Color,
-    val disabledUncheckedContentColor: Color,
-    val disabledUncheckedSecondaryContentColor: Color,
-    val disabledUncheckedSplitContainerColor: Color,
-) {
-
-    internal fun copy(
-        checkedContainerColor: Color,
-        checkedContentColor: Color,
-        checkedSecondaryContentColor: Color,
-        checkedSplitContainerColor: Color,
-        uncheckedContainerColor: Color,
-        uncheckedContentColor: Color,
-        uncheckedSecondaryContentColor: Color,
-        uncheckedSplitContainerColor: Color,
-        disabledCheckedContainerColor: Color,
-        disabledCheckedContentColor: Color,
-        disabledCheckedSecondaryContentColor: Color,
-        disabledCheckedSplitContainerColor: Color,
-        disabledUncheckedContainerColor: Color,
-        disabledUncheckedContentColor: Color,
-        disabledUncheckedSecondaryContentColor: Color,
-        disabledUncheckedSplitContainerColor: Color,
-    ): SplitToggleButtonColors =
-        SplitToggleButtonColors(
-            checkedContainerColor = checkedContainerColor.takeOrElse { this.checkedContainerColor },
-            checkedContentColor = checkedContentColor.takeOrElse { this.checkedContentColor },
-            checkedSecondaryContentColor =
-                checkedSecondaryContentColor.takeOrElse { this.checkedSecondaryContentColor },
-            checkedSplitContainerColor =
-                checkedSplitContainerColor.takeOrElse { this.checkedSplitContainerColor },
-            uncheckedContainerColor =
-                uncheckedContainerColor.takeOrElse { this.uncheckedContainerColor },
-            uncheckedContentColor = uncheckedContentColor.takeOrElse { this.uncheckedContentColor },
-            uncheckedSecondaryContentColor =
-                uncheckedSecondaryContentColor.takeOrElse { this.uncheckedSecondaryContentColor },
-            uncheckedSplitContainerColor =
-                uncheckedSplitContainerColor.takeOrElse { this.uncheckedSplitContainerColor },
-            disabledCheckedContainerColor =
-                disabledCheckedContainerColor.takeOrElse { this.disabledCheckedContainerColor },
-            disabledCheckedContentColor =
-                disabledCheckedContentColor.takeOrElse { this.disabledCheckedContentColor },
-            disabledCheckedSecondaryContentColor =
-                disabledCheckedSecondaryContentColor.takeOrElse {
-                    this.disabledCheckedSecondaryContentColor
-                },
-            disabledCheckedSplitContainerColor =
-                disabledCheckedSplitContainerColor.takeOrElse {
-                    this.disabledCheckedSplitContainerColor
-                },
-            disabledUncheckedContainerColor =
-                disabledUncheckedContainerColor.takeOrElse { this.disabledUncheckedContainerColor },
-            disabledUncheckedContentColor =
-                disabledUncheckedContentColor.takeOrElse { this.disabledUncheckedContentColor },
-            disabledUncheckedSecondaryContentColor =
-                disabledUncheckedSecondaryContentColor.takeOrElse {
-                    this.disabledUncheckedSecondaryContentColor
-                },
-            disabledUncheckedSplitContainerColor =
-                disabledUncheckedSplitContainerColor.takeOrElse {
-                    this.disabledUncheckedSplitContainerColor
-                },
-        )
-
-    /**
-     * Determines the container color based on whether the [SplitToggleButton] is [enabled] and
-     * [checked].
-     *
-     * @param enabled Whether the [SplitToggleButton] is enabled
-     * @param checked Whether the [SplitToggleButton] is currently checked
-     */
-    @Composable
-    internal fun containerColor(enabled: Boolean, checked: Boolean): State<Color> =
-        animateSelectionColor(
-            enabled = enabled,
-            checked = checked,
-            checkedColor = checkedContainerColor,
-            uncheckedColor = uncheckedContainerColor,
-            disabledCheckedColor = disabledCheckedContainerColor,
-            disabledUncheckedColor = disabledUncheckedContainerColor,
-            animationSpec = COLOR_ANIMATION_SPEC
-        )
-
-    /**
-     * Determines the content color based on whether the [SplitToggleButton] is [enabled] and
-     * [checked].
-     *
-     * @param enabled Whether the [SplitToggleButton] is enabled
-     * @param checked Whether the [SplitToggleButton] is currently checked
-     */
-    @Composable
-    internal fun contentColor(enabled: Boolean, checked: Boolean): State<Color> =
-        animateSelectionColor(
-            enabled = enabled,
-            checked = checked,
-            checkedColor = checkedContentColor,
-            uncheckedColor = uncheckedContentColor,
-            disabledCheckedColor = disabledCheckedContentColor,
-            disabledUncheckedColor = disabledUncheckedContentColor,
-            animationSpec = COLOR_ANIMATION_SPEC
-        )
-
-    /**
-     * Represents the secondary content color for the [SplitToggleButton] depending on the [enabled]
-     * and [checked] properties.
-     *
-     * @param enabled Whether the [SplitToggleButton] is enabled.
-     * @param checked Whether the [SplitToggleButton] is currently checked or unchecked.
-     */
-    @Composable
-    internal fun secondaryContentColor(enabled: Boolean, checked: Boolean): State<Color> =
-        animateSelectionColor(
-            enabled = enabled,
-            checked = checked,
-            checkedColor = checkedSecondaryContentColor,
-            uncheckedColor = uncheckedSecondaryContentColor,
-            disabledCheckedColor = disabledCheckedSecondaryContentColor,
-            disabledUncheckedColor = disabledUncheckedSecondaryContentColor,
-            animationSpec = COLOR_ANIMATION_SPEC
-        )
-
-    /**
-     * Represents the split container for the [SplitToggleButton] color depending on the [enabled]
-     * and [checked] properties.
-     *
-     * @param enabled Whether the [SplitToggleButton] is enabled.
-     * @param checked Whether the [SplitToggleButton] is currently checked or unchecked.
-     */
-    @Composable
-    internal fun splitContainerColor(enabled: Boolean, checked: Boolean): State<Color> =
-        animateSelectionColor(
-            enabled = enabled,
-            checked = checked,
-            checkedColor = checkedSplitContainerColor,
-            uncheckedColor = uncheckedSplitContainerColor,
-            disabledCheckedColor = disabledCheckedSplitContainerColor,
-            disabledUncheckedColor = disabledUncheckedSplitContainerColor,
-            animationSpec = COLOR_ANIMATION_SPEC
-        )
-
-    override fun equals(other: Any?): Boolean {
-        if (this === other) return true
-        if (other == null) return false
-        if (this::class != other::class) return false
-
-        other as SplitToggleButtonColors
-
-        if (checkedContainerColor != other.checkedContainerColor) return false
-        if (checkedContentColor != other.checkedContentColor) return false
-        if (checkedSecondaryContentColor != other.checkedSecondaryContentColor) return false
-        if (checkedSplitContainerColor != other.checkedSplitContainerColor) return false
-        if (uncheckedContainerColor != other.uncheckedContainerColor) return false
-        if (uncheckedContentColor != other.uncheckedContentColor) return false
-        if (uncheckedSecondaryContentColor != other.uncheckedSecondaryContentColor) return false
-        if (uncheckedSplitContainerColor != other.uncheckedSplitContainerColor) return false
-        if (disabledCheckedContainerColor != other.disabledCheckedContainerColor) return false
-        if (disabledCheckedContentColor != other.disabledCheckedContentColor) return false
-        if (disabledCheckedSecondaryContentColor != other.disabledCheckedSecondaryContentColor)
-            return false
-        if (disabledCheckedSplitContainerColor != other.disabledCheckedSplitContainerColor)
-            return false
-        if (disabledUncheckedContainerColor != other.disabledUncheckedContainerColor) return false
-        if (disabledUncheckedContentColor != other.disabledUncheckedContentColor) return false
-        if (disabledUncheckedSecondaryContentColor != other.disabledUncheckedSecondaryContentColor)
-            return false
-        if (disabledUncheckedSplitContainerColor != other.disabledUncheckedSplitContainerColor)
-            return false
-
-        return true
-    }
-
-    override fun hashCode(): Int {
-        var result = checkedContainerColor.hashCode()
-        result = 31 * result + checkedContentColor.hashCode()
-        result = 31 * result + checkedSecondaryContentColor.hashCode()
-        result = 31 * result + checkedSplitContainerColor.hashCode()
-        result = 31 * result + uncheckedContainerColor.hashCode()
-        result = 31 * result + uncheckedContentColor.hashCode()
-        result = 31 * result + uncheckedSecondaryContentColor.hashCode()
-        result = 31 * result + uncheckedSplitContainerColor.hashCode()
-        result = 31 * result + disabledCheckedContainerColor.hashCode()
-        result = 31 * result + disabledCheckedContentColor.hashCode()
-        result = 31 * result + disabledCheckedSecondaryContentColor.hashCode()
-        result = 31 * result + disabledCheckedSplitContainerColor.hashCode()
-        result = 31 * result + disabledUncheckedContainerColor.hashCode()
-        result = 31 * result + disabledUncheckedContentColor.hashCode()
-        result = 31 * result + disabledUncheckedSecondaryContentColor.hashCode()
-        result = 31 * result + disabledUncheckedSplitContainerColor.hashCode()
-        return result
-    }
-}
-
-/**
- * [ToggleControlScope] provides enabled and checked properties. This allows toggle controls to omit
- * enabled/checked parameters as they given by the scope.
- *
- * @param isEnabled Controls the enabled state of the toggle control. When `false`, the control is
- *   displayed with disabled colors.
- * @param isChecked Indicates whether the control is currently checked.
- */
-class ToggleControlScope(val isEnabled: Boolean, val isChecked: Boolean)
-
-private val TOGGLE_CONTROL_WIDTH = 32.dp
-private val TOGGLE_CONTROL_HEIGHT = 24.dp
-private val TOGGLE_CONTROL_SPACING = 6.dp
-private val ICON_SPACING = 6.dp
-private val MIN_HEIGHT = 52.dp
-
 private val COLOR_ANIMATION_SPEC: AnimationSpec<Color> =
     tween(MotionTokens.DurationMedium1, 0, MotionTokens.EasingStandardDecelerate)
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ToggleControls.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ToggleControls.kt
deleted file mode 100644
index 35b0ba0..0000000
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ToggleControls.kt
+++ /dev/null
@@ -1,530 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.wear.compose.material3
-
-import androidx.compose.animation.core.AnimationSpec
-import androidx.compose.animation.core.TweenSpec
-import androidx.compose.animation.core.animateFloat
-import androidx.compose.animation.core.tween
-import androidx.compose.animation.core.updateTransition
-import androidx.compose.foundation.background
-import androidx.compose.foundation.border
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.width
-import androidx.compose.foundation.layout.wrapContentSize
-import androidx.compose.foundation.shape.CircleShape
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.Immutable
-import androidx.compose.runtime.State
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.drawBehind
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.drawscope.DrawScope
-import androidx.compose.ui.semantics.Role
-import androidx.compose.ui.semantics.role
-import androidx.compose.ui.semantics.semantics
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.util.lerp
-import androidx.wear.compose.material3.tokens.MotionTokens
-import androidx.wear.compose.materialcore.SelectionStage
-import androidx.wear.compose.materialcore.animateSelectionColor
-import androidx.wear.compose.materialcore.animateTick
-import androidx.wear.compose.materialcore.isLayoutDirectionRtl
-
-/**
- * [Switch] provides an animated switch for use as a toggle control in [ToggleButton] or
- * [SplitToggleButton].
- *
- * Switch samples:
- *
- * @sample androidx.wear.compose.material3.samples.ToggleButtonWithSwitch
- * @param modifier Modifier to be applied to the switch. This can be used to provide a content
- *   description for accessibility.
- * @param colors [SwitchColors] from which the colors of the thumb and track will be obtained.
- */
-@Composable
-fun ToggleControlScope.Switch(
-    modifier: Modifier = Modifier,
-    colors: SwitchColors = SwitchDefaults.colors(),
-) {
-    val isRtl = isLayoutDirectionRtl()
-    val targetState = if (isChecked) SelectionStage.Checked else SelectionStage.Unchecked
-    val transition = updateTransition(targetState, label = "switchTransition")
-    val thumbProgress =
-        transition.animateFloat(
-            transitionSpec = { SWITCH_PROGRESS_ANIMATION_SPEC },
-            label = "switchTransition"
-        ) {
-            when (it) {
-                SelectionStage.Unchecked -> 0f
-                SelectionStage.Checked -> 1f
-            }
-        }
-    val thumbColor = colors.thumbColor(enabled = isEnabled, checked = isChecked).value
-    val thumbIconColor = colors.thumbIconColor(enabled = isEnabled, checked = isChecked).value
-    val trackColor = colors.trackColor(enabled = isEnabled, checked = isChecked).value
-    val trackBorderColor = colors.trackBorderColor(enabled = isEnabled, checked = isChecked).value
-    Box(
-        modifier =
-            modifier
-                .semantics { this.role = Role.Switch }
-                .height(SWITCH_HEIGHT)
-                .width(WIDTH)
-                .border(
-                    width = SWITCH_TRACK_WIDTH,
-                    shape = CircleShape,
-                    color =
-                        if (trackColor == trackBorderColor) Color.Transparent else trackBorderColor
-                )
-                .background(color = trackColor, shape = CircleShape)
-                .drawBehind {
-                    drawThumbAndTick(
-                        isEnabled,
-                        isChecked,
-                        thumbColor,
-                        thumbProgress.value,
-                        thumbIconColor,
-                        isRtl
-                    )
-                }
-                .wrapContentSize(Alignment.CenterEnd)
-    )
-}
-
-/**
- * Represents the content colors used in [Checkbox] in different states.
- *
- * @param checkedBoxColor The box color of [Checkbox] when enabled and checked.
- * @param checkedCheckmarkColor The check mark color of [Checkbox] when enabled and checked.
- * @param uncheckedBoxColor The box color of [Checkbox] when enabled and unchecked.
- * @param uncheckedCheckmarkColor The check mark color of [Checkbox] when enabled and unchecked.
- * @param disabledCheckedBoxColor The box color of [Checkbox] when disabled and checked.
- * @param disabledCheckedCheckmarkColor The check mark color of [Checkbox] when disabled and
- *   checked.
- * @param disabledUncheckedBoxColor The box color of [Checkbox] when disabled and unchecked.
- * @param disabledUncheckedCheckmarkColor The check mark color of [Checkbox] when disabled and
- *   unchecked.
- */
-@Immutable
-class CheckboxColors(
-    val checkedBoxColor: Color,
-    val checkedCheckmarkColor: Color,
-    val uncheckedBoxColor: Color,
-    val uncheckedCheckmarkColor: Color,
-    val disabledCheckedBoxColor: Color,
-    val disabledCheckedCheckmarkColor: Color,
-    val disabledUncheckedBoxColor: Color,
-    val disabledUncheckedCheckmarkColor: Color,
-) {
-
-    /**
-     * Represents the box color for this [Checkbox], depending on the [enabled] and [checked]
-     * properties.
-     *
-     * @param enabled Whether the [Checkbox] is enabled
-     * @param checked Whether the [Checkbox] is currently checked or unchecked
-     */
-    @Composable
-    internal fun boxColor(enabled: Boolean, checked: Boolean): State<Color> =
-        animateSelectionColor(
-            enabled = enabled,
-            checked = checked,
-            checkedColor = checkedBoxColor,
-            uncheckedColor = uncheckedBoxColor,
-            disabledCheckedColor = disabledCheckedBoxColor,
-            disabledUncheckedColor = disabledUncheckedBoxColor,
-            animationSpec = COLOR_ANIMATION_SPEC
-        )
-
-    /**
-     * Represents the checkmark color for this [Checkbox], depending on the [enabled] and [checked]
-     * properties.
-     *
-     * @param enabled Whether the [Checkbox] is enabled
-     * @param checked Whether the [Checkbox] is currently checked or unchecked
-     */
-    @Composable
-    internal fun checkmarkColor(enabled: Boolean, checked: Boolean): State<Color> =
-        animateSelectionColor(
-            enabled = enabled,
-            checked = checked,
-            checkedColor = checkedCheckmarkColor,
-            uncheckedColor = uncheckedCheckmarkColor,
-            disabledCheckedColor = disabledCheckedCheckmarkColor,
-            disabledUncheckedColor = disabledUncheckedCheckmarkColor,
-            animationSpec = COLOR_ANIMATION_SPEC
-        )
-
-    override fun equals(other: Any?): Boolean {
-        if (this === other) return true
-        if (other == null || other !is CheckboxColors) return false
-
-        if (checkedBoxColor != other.checkedBoxColor) return false
-        if (checkedCheckmarkColor != other.checkedCheckmarkColor) return false
-        if (uncheckedCheckmarkColor != other.uncheckedCheckmarkColor) return false
-        if (uncheckedBoxColor != other.uncheckedBoxColor) return false
-        if (disabledCheckedBoxColor != other.disabledCheckedBoxColor) return false
-        if (disabledCheckedCheckmarkColor != other.disabledCheckedCheckmarkColor) return false
-        if (disabledUncheckedBoxColor != other.disabledUncheckedBoxColor) return false
-        if (disabledUncheckedCheckmarkColor != other.disabledUncheckedCheckmarkColor) return false
-
-        return true
-    }
-
-    override fun hashCode(): Int {
-        var result = checkedBoxColor.hashCode()
-        result = 31 * result + checkedCheckmarkColor.hashCode()
-        result = 31 * result + uncheckedCheckmarkColor.hashCode()
-        result = 31 * result + uncheckedBoxColor.hashCode()
-        result = 31 * result + disabledCheckedBoxColor.hashCode()
-        result = 31 * result + disabledCheckedCheckmarkColor.hashCode()
-        result = 31 * result + disabledUncheckedBoxColor.hashCode()
-        result = 31 * result + disabledUncheckedCheckmarkColor.hashCode()
-        return result
-    }
-}
-
-/**
- * Represents the content colors used in [Switch] in different states.
- *
- * @param checkedThumbColor The thumb color of [Switch] when enabled and checked.
- * @param checkedThumbIconColor The thumb icon color of [Switch] when enabled and checked.
- * @param checkedTrackColor The track color of [Switch] when enabled and checked.
- * @param checkedTrackBorderColor The track border color of [Switch] when enabled and checked.
- * @param uncheckedThumbColor The thumb color of [Switch] when enabled and unchecked.
- * @param uncheckedThumbIconColor The thumb icon color of [Switch] when enabled and unchecked.
- * @param uncheckedTrackColor The track color of [Switch] when enabled and unchecked.
- * @param uncheckedTrackBorderColor The track border color of [Switch] when enabled and unchecked.
- * @param disabledCheckedThumbColor The thumb color of [Switch] when disabled and checked.
- * @param disabledCheckedThumbIconColor The thumb icon color of [Switch] when disabled and checked.
- * @param disabledCheckedTrackColor The track color of [Switch] when disabled and checked.
- * @param disabledCheckedTrackBorderColor The track border color of [Switch] when disabled and
- *   checked.
- * @param disabledUncheckedThumbColor The thumb color of [Switch] when disabled and unchecked.
- * @param disabledUncheckedThumbIconColor The thumb icon color of [Switch] when disabled and
- *   unchecked.
- * @param disabledUncheckedTrackColor The track color of [Switch] when disabled and unchecked.
- * @param disabledUncheckedTrackBorderColor The track border color of [Switch] when disabled and
- *   unchecked.
- */
-@Immutable
-class SwitchColors(
-    val checkedThumbColor: Color,
-    val checkedThumbIconColor: Color,
-    val checkedTrackColor: Color,
-    val checkedTrackBorderColor: Color,
-    val uncheckedThumbColor: Color,
-    val uncheckedThumbIconColor: Color,
-    val uncheckedTrackColor: Color,
-    val uncheckedTrackBorderColor: Color,
-    val disabledCheckedThumbColor: Color,
-    val disabledCheckedThumbIconColor: Color,
-    val disabledCheckedTrackColor: Color,
-    val disabledCheckedTrackBorderColor: Color,
-    val disabledUncheckedThumbColor: Color,
-    val disabledUncheckedThumbIconColor: Color,
-    val disabledUncheckedTrackColor: Color,
-    val disabledUncheckedTrackBorderColor: Color,
-) {
-    @Composable
-    internal fun thumbColor(enabled: Boolean, checked: Boolean): State<Color> =
-        animateSelectionColor(
-            enabled = enabled,
-            checked = checked,
-            checkedColor = checkedThumbColor,
-            uncheckedColor = uncheckedThumbColor,
-            disabledCheckedColor = disabledCheckedThumbColor,
-            disabledUncheckedColor = disabledUncheckedThumbColor,
-            animationSpec = COLOR_ANIMATION_SPEC
-        )
-
-    @Composable
-    internal fun thumbIconColor(enabled: Boolean, checked: Boolean): State<Color> =
-        animateSelectionColor(
-            enabled = enabled,
-            checked = checked,
-            checkedColor = checkedThumbIconColor,
-            uncheckedColor = uncheckedThumbIconColor,
-            disabledCheckedColor = disabledCheckedThumbIconColor,
-            disabledUncheckedColor = disabledUncheckedThumbIconColor,
-            animationSpec = COLOR_ANIMATION_SPEC
-        )
-
-    @Composable
-    internal fun trackColor(enabled: Boolean, checked: Boolean): State<Color> =
-        animateSelectionColor(
-            enabled = enabled,
-            checked = checked,
-            checkedColor = checkedTrackColor,
-            uncheckedColor = uncheckedTrackColor,
-            disabledCheckedColor = disabledCheckedTrackBorderColor,
-            disabledUncheckedColor = disabledUncheckedTrackColor,
-            animationSpec = COLOR_ANIMATION_SPEC
-        )
-
-    @Composable
-    internal fun trackBorderColor(enabled: Boolean, checked: Boolean): State<Color> =
-        animateSelectionColor(
-            enabled = enabled,
-            checked = checked,
-            checkedColor = checkedTrackBorderColor,
-            uncheckedColor = uncheckedTrackBorderColor,
-            disabledCheckedColor = disabledCheckedTrackColor,
-            disabledUncheckedColor = disabledUncheckedTrackBorderColor,
-            animationSpec = COLOR_ANIMATION_SPEC
-        )
-
-    override fun equals(other: Any?): Boolean {
-        if (this === other) return true
-        if (other == null || other !is SwitchColors) return false
-
-        if (checkedThumbColor != other.checkedThumbColor) return false
-        if (checkedThumbIconColor != other.checkedThumbIconColor) return false
-        if (checkedTrackColor != other.checkedTrackColor) return false
-        if (checkedTrackBorderColor != other.checkedTrackBorderColor) return false
-        if (uncheckedThumbColor != other.uncheckedThumbColor) return false
-        if (uncheckedThumbIconColor != other.uncheckedThumbIconColor) return false
-        if (uncheckedTrackColor != other.uncheckedTrackColor) return false
-        if (uncheckedTrackBorderColor != other.uncheckedTrackBorderColor) return false
-        if (disabledCheckedThumbColor != other.disabledCheckedThumbColor) return false
-        if (disabledCheckedThumbIconColor != other.disabledCheckedThumbIconColor) return false
-        if (disabledCheckedTrackColor != other.disabledCheckedTrackColor) return false
-        if (disabledCheckedTrackBorderColor != other.disabledCheckedTrackBorderColor) return false
-        if (disabledUncheckedThumbColor != other.disabledUncheckedThumbColor) return false
-        if (disabledUncheckedThumbIconColor != other.disabledUncheckedThumbIconColor) return false
-        if (disabledUncheckedTrackColor != other.disabledUncheckedTrackColor) return false
-        if (disabledUncheckedTrackBorderColor != other.disabledCheckedTrackBorderColor) return false
-
-        return true
-    }
-
-    override fun hashCode(): Int {
-        var result = checkedThumbColor.hashCode()
-        result = 31 * result + checkedThumbIconColor.hashCode()
-        result = 31 * result + checkedTrackColor.hashCode()
-        result = 31 * result + checkedTrackBorderColor.hashCode()
-        result = 31 * result + uncheckedThumbColor.hashCode()
-        result = 31 * result + uncheckedThumbIconColor.hashCode()
-        result = 31 * result + uncheckedTrackColor.hashCode()
-        result = 31 * result + uncheckedTrackBorderColor.hashCode()
-        result = 31 * result + disabledCheckedThumbColor.hashCode()
-        result = 31 * result + disabledCheckedThumbIconColor.hashCode()
-        result = 31 * result + disabledCheckedTrackColor.hashCode()
-        result = 31 * result + disabledCheckedTrackBorderColor.hashCode()
-        result = 31 * result + disabledUncheckedThumbColor.hashCode()
-        result = 31 * result + disabledUncheckedThumbIconColor.hashCode()
-        result = 31 * result + disabledUncheckedTrackColor.hashCode()
-        result = 31 * result + disabledUncheckedTrackBorderColor.hashCode()
-        return result
-    }
-}
-
-/** Contains the default values used by [Checkbox]. */
-object CheckboxDefaults {
-    /**
-     * Creates a [CheckboxColors] for use in a [Checkbox].
-     *
-     * @param checkedBoxColor The box color of this [Checkbox] when enabled and checked.
-     * @param checkedCheckmarkColor The check mark color of this [Checkbox] when enabled and
-     *   checked.
-     * @param uncheckedBoxColor The box color of this [Checkbox] when enabled and unchecked.
-     * @param uncheckedCheckmarkColor The check mark color of this [Checkbox] when enabled and
-     *   unchecked.
-     * @param disabledCheckedBoxColor The box color of this [Checkbox] when disabled and checked
-     * @param disabledCheckedCheckmarkColor The check mark color of this [Checkbox] when disabled
-     *   and checked
-     * @param disabledUncheckedBoxColor The box color of this [Checkbox] when disabled and unchecked
-     * @param disabledUncheckedCheckmarkColor The check mark color of this [Checkbox] when disabled
-     *   and unchecked
-     */
-    @Composable
-    fun colors(
-        checkedBoxColor: Color = MaterialTheme.colorScheme.primary,
-        checkedCheckmarkColor: Color = MaterialTheme.colorScheme.onPrimary,
-        uncheckedBoxColor: Color = MaterialTheme.colorScheme.outline,
-        uncheckedCheckmarkColor: Color = Color.Transparent,
-        disabledCheckedBoxColor: Color =
-            MaterialTheme.colorScheme.onSurface.toDisabledColor(disabledAlpha = 0.12f),
-        disabledCheckedCheckmarkColor: Color =
-            MaterialTheme.colorScheme.background.toDisabledColor(),
-        disabledUncheckedBoxColor: Color =
-            MaterialTheme.colorScheme.onSurface.toDisabledColor(disabledAlpha = 0.12f),
-        disabledUncheckedCheckmarkColor: Color = Color.Transparent
-    ): CheckboxColors =
-        CheckboxColors(
-            checkedBoxColor = checkedBoxColor,
-            checkedCheckmarkColor = checkedCheckmarkColor,
-            uncheckedBoxColor = uncheckedBoxColor,
-            uncheckedCheckmarkColor = uncheckedCheckmarkColor,
-            disabledCheckedBoxColor = disabledCheckedBoxColor,
-            disabledCheckedCheckmarkColor = disabledCheckedCheckmarkColor,
-            disabledUncheckedBoxColor = disabledUncheckedBoxColor,
-            disabledUncheckedCheckmarkColor = disabledUncheckedCheckmarkColor
-        )
-}
-
-/** Contains the default values used by [Switch]. */
-object SwitchDefaults {
-    /**
-     * Creates a [SwitchColors] for use in a [Switch].
-     *
-     * @param checkedThumbColor The thumb color of this [Switch] when enabled and checked.
-     * @param checkedThumbIconColor The thumb icon color of this [Switch] when enabled and checked.
-     * @param checkedTrackColor The track color of this [Switch] when enabled and checked.
-     * @param checkedTrackBorderColor The border color of this [Switch] when enabled and checked.
-     * @param uncheckedThumbColor The thumb color of this [Switch] when enabled and unchecked.
-     * @param uncheckedThumbIconColor The thumb icon color of this [Switch] when enabled and
-     *   checked.
-     * @param uncheckedTrackColor The track color of this [Switch] when enabled and unchecked.
-     * @param uncheckedTrackBorderColor The border color of this [Switch] when enabled and
-     *   unchecked.
-     * @param disabledCheckedThumbColor The thumb color of this [Switch] when disabled and checked.
-     * @param disabledCheckedThumbIconColor The thumb icon color of this [Switch] when disabled and
-     *   checked.
-     * @param disabledCheckedTrackColor The track color of this [Switch] when disabled and checked.
-     * @param disabledCheckedTrackBorderColor The border color of this [Switch] when disabled and
-     *   unchecked.
-     * @param disabledUncheckedThumbColor The thumb color of this [Switch] when disabled and
-     *   unchecked.
-     * @param disabledUncheckedThumbIconColor The thumb icon color of this [Switch] when disabled
-     *   and unchecked.
-     * @param disabledUncheckedTrackColor The track color of this [Switch] when disabled and
-     *   unchecked.
-     * @param disabledUncheckedTrackBorderColor The border color of this [Switch] when disabled and
-     *   unchecked.
-     */
-    @Composable
-    fun colors(
-        checkedThumbColor: Color = MaterialTheme.colorScheme.onPrimary,
-        checkedThumbIconColor: Color = MaterialTheme.colorScheme.primary,
-        checkedTrackColor: Color = MaterialTheme.colorScheme.primary,
-        checkedTrackBorderColor: Color = MaterialTheme.colorScheme.primary,
-        uncheckedThumbColor: Color = MaterialTheme.colorScheme.outline,
-        uncheckedThumbIconColor: Color = Color.Transparent,
-        uncheckedTrackColor: Color = MaterialTheme.colorScheme.surfaceContainer,
-        uncheckedTrackBorderColor: Color = MaterialTheme.colorScheme.outline,
-        disabledCheckedThumbColor: Color = MaterialTheme.colorScheme.background.toDisabledColor(),
-        disabledCheckedThumbIconColor: Color =
-            MaterialTheme.colorScheme.onSurface.toDisabledColor(disabledAlpha = 0.12f),
-        disabledCheckedTrackColor: Color =
-            MaterialTheme.colorScheme.onSurface.toDisabledColor(disabledAlpha = 0.12f),
-        disabledCheckedTrackBorderColor: Color =
-            MaterialTheme.colorScheme.onSurface.toDisabledColor(disabledAlpha = 0.12f),
-        disabledUncheckedThumbColor: Color =
-            MaterialTheme.colorScheme.onSurface.toDisabledColor(disabledAlpha = 0.12f),
-        disabledUncheckedThumbIconColor: Color = Color.Transparent,
-        disabledUncheckedTrackColor: Color = Color.Transparent,
-        disabledUncheckedTrackBorderColor: Color =
-            MaterialTheme.colorScheme.onSurface.toDisabledColor(disabledAlpha = 0.12f)
-    ): SwitchColors =
-        SwitchColors(
-            checkedThumbColor = checkedThumbColor,
-            checkedThumbIconColor = checkedThumbIconColor,
-            checkedTrackColor = checkedTrackColor,
-            checkedTrackBorderColor = checkedTrackBorderColor,
-            uncheckedThumbColor = uncheckedThumbColor,
-            uncheckedThumbIconColor = uncheckedThumbIconColor,
-            uncheckedTrackColor = uncheckedTrackColor,
-            uncheckedTrackBorderColor = uncheckedTrackBorderColor,
-            disabledCheckedThumbColor = disabledCheckedThumbColor,
-            disabledCheckedThumbIconColor = disabledCheckedThumbIconColor,
-            disabledCheckedTrackColor = disabledCheckedTrackColor,
-            disabledCheckedTrackBorderColor = disabledCheckedTrackBorderColor,
-            disabledUncheckedThumbColor = disabledUncheckedThumbColor,
-            disabledUncheckedThumbIconColor = disabledUncheckedThumbIconColor,
-            disabledUncheckedTrackColor = disabledUncheckedTrackColor,
-            disabledUncheckedTrackBorderColor = disabledUncheckedTrackBorderColor
-        )
-}
-
-private fun DrawScope.drawThumbAndTick(
-    enabled: Boolean,
-    checked: Boolean,
-    thumbColor: Color,
-    progress: Float,
-    thumbIconColor: Color,
-    isRtl: Boolean
-) {
-
-    val thumbPaddingUnchecked = SWITCH_HEIGHT / 2 - THUMB_RADIUS_UNCHECKED
-    val thumbPaddingChecked = SWITCH_HEIGHT / 2 - THUMB_RADIUS_CHECKED
-
-    val switchThumbRadiusPx =
-        lerp(
-            start = THUMB_RADIUS_UNCHECKED.toPx(),
-            stop = THUMB_RADIUS_CHECKED.toPx(),
-            fraction = progress
-        )
-
-    val switchTrackLengthPx = WIDTH.toPx()
-
-    // For Rtl mode the thumb progress will start from the end of the switch.
-    val thumbProgressPx =
-        if (isRtl)
-            lerp(
-                start = switchTrackLengthPx - switchThumbRadiusPx - thumbPaddingUnchecked.toPx(),
-                stop = switchThumbRadiusPx + thumbPaddingChecked.toPx(),
-                fraction = progress
-            )
-        else
-            lerp(
-                start = switchThumbRadiusPx + thumbPaddingUnchecked.toPx(),
-                stop = switchTrackLengthPx - switchThumbRadiusPx - thumbPaddingChecked.toPx(),
-                fraction = progress
-            )
-
-    drawCircle(
-        color = thumbColor,
-        radius = switchThumbRadiusPx,
-        center = Offset(thumbProgressPx, center.y)
-    )
-
-    val ltrAdditionalOffset = 5.dp.toPx()
-    val rtlAdditionalOffset = 6.dp.toPx()
-
-    val totalDist = switchTrackLengthPx - 2 * switchThumbRadiusPx - ltrAdditionalOffset
-
-    // Offset value to be added if RTL mode is enabled.
-    // We need to move the tick to the checked position in ltr mode when unchecked.
-    val rtlOffset = switchTrackLengthPx - 2 * THUMB_RADIUS_CHECKED.toPx() - rtlAdditionalOffset
-
-    val distMoved = if (isRtl) rtlOffset - progress * totalDist else progress * totalDist
-
-    // Draw tick icon
-    animateTick(
-        enabled = enabled,
-        checked = checked,
-        tickColor = thumbIconColor,
-        tickProgress = progress,
-        startXOffset = distMoved.toDp()
-    )
-}
-
-private val THUMB_RADIUS_UNCHECKED = 6.dp
-private val THUMB_RADIUS_CHECKED = 9.dp
-private val SWITCH_HEIGHT = 22.dp
-private val CHECKBOX_HEIGHT = 24.dp
-private val WIDTH = 32.dp
-private val SWITCH_TRACK_WIDTH = 2.dp
-
-private val COLOR_ANIMATION_SPEC: AnimationSpec<Color> =
-    tween(MotionTokens.DurationMedium1, 0, MotionTokens.EasingStandardDecelerate)
-private val SWITCH_PROGRESS_ANIMATION_SPEC: TweenSpec<Float> =
-    tween(MotionTokens.DurationMedium2, 0, MotionTokens.EasingStandardDecelerate)
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Typography.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Typography.kt
index 556592d..a5bc319 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Typography.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Typography.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 The Android Open Source Project
+ * Copyright 2024 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -35,6 +35,32 @@
  * size for DisplayLarge:
  *
  * @sample androidx.wear.compose.material3.samples.FixedFontSize
+ *
+ * Display styles are utilized for large, short strings of text used to display highly glanceable
+ * hero information, significant metrics, confidence or expressive brand moments.
+ *
+ * Title styles are hierarchical text used as a mechanism for way-finding, like a page, section
+ * title, or sub-section title (in the case of Title Small).
+ *
+ * Label styles are used for component level text that describes an action that would happen if
+ * interacted with. The most common and widely used application for label is for text nested within
+ * a button.
+ *
+ * Body styles are reserved for content text like paragraphs of body copy, text used in complex data
+ * visualisation, time stamps and metadata.
+ *
+ * Numeral text styles are used for numerical digits, usually limited to a few characters. These can
+ * take on more expressive properties at the larger display sizes. They give flexibility to expand
+ * width axis with minimal localization and font scaling concerns.
+ *
+ * Arc text styles are used for curved text making up the signposting on the UI such as time text
+ * and curved labels, a tailored font axis that specifically optimizes type along a curve.
+ *
+ * @property arcMedium ArcMedium is for arc headers and titles. Arc is for text along a curved path
+ *   on the screen, reserved for short header text strings at the very top or bottom of the screen
+ *   like page titles.
+ * @property arcSmall ArcSmall is for arc headers and titles. Arc is for text along a curved path on
+ *   the screen, reserved for short header text strings at the very top or bottom of the screen.
  * @property displayLarge DisplayLarge is the largest headline. Displays are the largest text on the
  *   screen, reserved for short, important text or numerals.
  * @property displayMedium DisplayMedium is the second largest headline. Displays are the largest
@@ -65,12 +91,29 @@
  * @property bodyExtraSmall BodyExtraSmall is the smallest body. Body texts are typically used for
  *   long-form writing as it works well for small text sizes. For longer sections of text, a serif
  *   or sans serif typeface is recommended.
+ * @property numeralExtraLarge NumeralExtraLarge is the largest role for digits. Numerals use
+ *   tabular spacing by default. They highlight and express glanceable numbers that are limited to a
+ *   two or three characters only, where no localization is required like the charging screen.
+ * @property numeralLarge NumeralLarge is the second largest role for digits. Numerals use tabular
+ *   spacing by default. They are large sized number strings that are limited to big displays of
+ *   time, where no localization is required like a timer countdown.
+ * @property numeralMedium NumeralMedium is the third largest role for digits. Numerals use tabular
+ *   spacing by default. They are medium sized numbers that are limited to short strings of digits,
+ *   where no localization is required like a steps count.
+ * @property numeralSmall NumeralSmall is the fourth largest role for digits. Numerals use tabular
+ *   spacing by default. They are for numbers that need emphasis at a smaller scale, where no
+ *   localization is required like date and time pickers.
+ * @property numeralExtraSmall NumeralExtraSmall is the smallest role for digits. Numerals use
+ *   tabular spacing by default. They are for numbers that need to accommodate longer strings of
+ *   digits, where no localization is required like in-workout metrics.
  *
  * TODO(b/273526150) Review documentation for typography, add examples for each size.
  */
 @Immutable
 class Typography
 internal constructor(
+    val arcMedium: TextStyle,
+    val arcSmall: TextStyle,
     val displayLarge: TextStyle,
     val displayMedium: TextStyle,
     val displaySmall: TextStyle,
@@ -83,10 +126,17 @@
     val bodyLarge: TextStyle,
     val bodyMedium: TextStyle,
     val bodySmall: TextStyle,
-    val bodyExtraSmall: TextStyle
+    val bodyExtraSmall: TextStyle,
+    val numeralExtraLarge: TextStyle,
+    val numeralLarge: TextStyle,
+    val numeralMedium: TextStyle,
+    val numeralSmall: TextStyle,
+    val numeralExtraSmall: TextStyle,
 ) {
     constructor(
         defaultFontFamily: FontFamily = FontFamily.Default,
+        arcMedium: TextStyle = TypographyTokens.ArcMedium,
+        arcSmall: TextStyle = TypographyTokens.ArcSmall,
         displayLarge: TextStyle = TypographyTokens.DisplayLarge,
         displayMedium: TextStyle = TypographyTokens.DisplayMedium,
         displaySmall: TextStyle = TypographyTokens.DisplaySmall,
@@ -99,8 +149,15 @@
         bodyLarge: TextStyle = TypographyTokens.BodyLarge,
         bodyMedium: TextStyle = TypographyTokens.BodyMedium,
         bodySmall: TextStyle = TypographyTokens.BodySmall,
-        bodyExtraSmall: TextStyle = TypographyTokens.BodyExtraSmall
+        bodyExtraSmall: TextStyle = TypographyTokens.BodyExtraSmall,
+        numeralExtraLarge: TextStyle = TypographyTokens.NumeralExtraLarge,
+        numeralLarge: TextStyle = TypographyTokens.NumeralLarge,
+        numeralMedium: TextStyle = TypographyTokens.NumeralMedium,
+        numeralSmall: TextStyle = TypographyTokens.NumeralSmall,
+        numeralExtraSmall: TextStyle = TypographyTokens.NumeralExtraSmall,
     ) : this(
+        arcMedium = arcMedium.withDefaultFontFamily(defaultFontFamily),
+        arcSmall = arcSmall.withDefaultFontFamily(defaultFontFamily),
         displayLarge = displayLarge.withDefaultFontFamily(defaultFontFamily),
         displayMedium = displayMedium.withDefaultFontFamily(defaultFontFamily),
         displaySmall = displaySmall.withDefaultFontFamily(defaultFontFamily),
@@ -113,11 +170,18 @@
         bodyLarge = bodyLarge.withDefaultFontFamily(defaultFontFamily),
         bodyMedium = bodyMedium.withDefaultFontFamily(defaultFontFamily),
         bodySmall = bodySmall.withDefaultFontFamily(defaultFontFamily),
-        bodyExtraSmall = bodyExtraSmall.withDefaultFontFamily(defaultFontFamily)
+        bodyExtraSmall = bodyExtraSmall.withDefaultFontFamily(defaultFontFamily),
+        numeralExtraLarge = numeralExtraLarge.withDefaultFontFamily(defaultFontFamily),
+        numeralLarge = numeralLarge.withDefaultFontFamily(defaultFontFamily),
+        numeralMedium = numeralMedium.withDefaultFontFamily(defaultFontFamily),
+        numeralSmall = numeralSmall.withDefaultFontFamily(defaultFontFamily),
+        numeralExtraSmall = numeralExtraSmall.withDefaultFontFamily(defaultFontFamily),
     )
 
     /** Returns a copy of this Typography, optionally overriding some of the values. */
     fun copy(
+        arcMedium: TextStyle = this.arcMedium,
+        arcSmall: TextStyle = this.arcSmall,
         displayLarge: TextStyle = this.displayLarge,
         displayMedium: TextStyle = this.displayMedium,
         displaySmall: TextStyle = this.displaySmall,
@@ -130,9 +194,16 @@
         bodyLarge: TextStyle = this.bodyLarge,
         bodyMedium: TextStyle = this.bodyMedium,
         bodySmall: TextStyle = this.bodySmall,
-        bodyExtraSmall: TextStyle = this.bodyExtraSmall
+        bodyExtraSmall: TextStyle = this.bodyExtraSmall,
+        numeralExtraLarge: TextStyle = this.numeralExtraLarge,
+        numeralLarge: TextStyle = this.numeralLarge,
+        numeralMedium: TextStyle = this.numeralMedium,
+        numeralSmall: TextStyle = this.numeralSmall,
+        numeralExtraSmall: TextStyle = this.numeralExtraSmall,
     ): Typography =
         Typography(
+            arcMedium,
+            arcSmall,
             displayLarge,
             displayMedium,
             displaySmall,
@@ -145,13 +216,20 @@
             bodyLarge,
             bodyMedium,
             bodySmall,
-            bodyExtraSmall
+            bodyExtraSmall,
+            numeralExtraLarge,
+            numeralLarge,
+            numeralMedium,
+            numeralSmall,
+            numeralExtraSmall,
         )
 
     override fun equals(other: Any?): Boolean {
         if (this === other) return true
         if (other !is Typography) return false
 
+        if (arcMedium != other.arcMedium) return false
+        if (arcSmall != other.arcSmall) return false
         if (displayLarge != other.displayLarge) return false
         if (displayMedium != other.displayMedium) return false
         if (displaySmall != other.displaySmall) return false
@@ -165,12 +243,19 @@
         if (bodyMedium != other.bodyMedium) return false
         if (bodySmall != other.bodySmall) return false
         if (bodyExtraSmall != other.bodyExtraSmall) return false
+        if (numeralExtraLarge != other.numeralExtraLarge) return false
+        if (numeralLarge != other.numeralLarge) return false
+        if (numeralMedium != other.numeralMedium) return false
+        if (numeralSmall != other.numeralSmall) return false
+        if (numeralExtraSmall != other.numeralExtraSmall) return false
 
         return true
     }
 
     override fun hashCode(): Int {
-        var result = displayLarge.hashCode()
+        var result = arcMedium.hashCode()
+        result = 31 * result + arcSmall.hashCode()
+        result = 31 * result + displayLarge.hashCode()
         result = 31 * result + displayMedium.hashCode()
         result = 31 * result + displaySmall.hashCode()
         result = 31 * result + titleLarge.hashCode()
@@ -183,15 +268,36 @@
         result = 31 * result + bodyMedium.hashCode()
         result = 31 * result + bodySmall.hashCode()
         result = 31 * result + bodyExtraSmall.hashCode()
+        result = 31 * result + numeralExtraLarge.hashCode()
+        result = 31 * result + numeralLarge.hashCode()
+        result = 31 * result + numeralMedium.hashCode()
+        result = 31 * result + numeralSmall.hashCode()
+        result = 31 * result + numeralExtraSmall.hashCode()
         return result
     }
 
     override fun toString(): String {
-        return "Typography(displayLarge=$displayLarge, displayMedium=$displayMedium, " +
-            "displaySmall=$displaySmall, titleLarge=$titleLarge, titleMedium=$titleMedium, " +
-            "titleSmall=$titleSmall, labelLarge=$labelLarge, labelMedium=$labelMedium, " +
-            "labelSmall=$labelSmall, bodyLarge=$bodyLarge, bodyMedium=$bodyMedium, " +
-            "bodySmall=$bodySmall, bodyExtraSmall=$bodyExtraSmall)"
+        return "Typography(" +
+            "arcMedium=$arcMedium, " +
+            "arcSmall=$arcSmall, " +
+            "displayLarge=$displayLarge, " +
+            "displayMedium=$displayMedium, " +
+            "displaySmall=$displaySmall, " +
+            "titleLarge=$titleLarge, " +
+            "titleMedium=$titleMedium, " +
+            "titleSmall=$titleSmall, " +
+            "labelLarge=$labelLarge, " +
+            "labelMedium=$labelMedium, " +
+            "labelSmall=$labelSmall, " +
+            "bodyLarge=$bodyLarge, " +
+            "bodyMedium=$bodyMedium, " +
+            "bodySmall=$bodySmall, " +
+            "bodyExtraSmall=$bodyExtraSmall)" +
+            "numeralExtraLarge=$numeralExtraLarge, " +
+            "numeralLarge=$numeralLarge, " +
+            "numeralMedium=$numeralMedium, " +
+            "numeralSmall=$numeralSmall, " +
+            "numeralExtraSmall=$numeralExtraSmall)"
     }
 }
 
@@ -221,6 +327,8 @@
 /** Helper function for typography tokens. */
 internal fun Typography.fromToken(value: TypographyKeyTokens): TextStyle {
     return when (value) {
+        TypographyKeyTokens.ArcMedium -> arcMedium
+        TypographyKeyTokens.ArcSmall -> arcSmall
         TypographyKeyTokens.DisplayLarge -> displayLarge
         TypographyKeyTokens.DisplayMedium -> displayMedium
         TypographyKeyTokens.DisplaySmall -> displaySmall
@@ -234,6 +342,11 @@
         TypographyKeyTokens.BodyMedium -> bodyMedium
         TypographyKeyTokens.BodySmall -> bodySmall
         TypographyKeyTokens.BodyExtraSmall -> bodyExtraSmall
+        TypographyKeyTokens.NumeralExtraLarge -> numeralExtraLarge
+        TypographyKeyTokens.NumeralLarge -> numeralLarge
+        TypographyKeyTokens.NumeralMedium -> numeralMedium
+        TypographyKeyTokens.NumeralSmall -> numeralSmall
+        TypographyKeyTokens.NumeralExtraSmall -> numeralExtraSmall
     }
 }
 
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/CardTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/CardTokens.kt
index dfe657c..cd03fe5 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/CardTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/CardTokens.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-// VERSION: v0_32
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
@@ -23,10 +23,10 @@
 
 internal object CardTokens {
     val AppImageSize = 16.0.dp
-    val ContainerMinHeight = 64.0.dp
     val AppNameColor = ColorSchemeKeyTokens.OnSurface
     val AppNameTypography = TypographyKeyTokens.TitleSmall
     val ContainerColor = ColorSchemeKeyTokens.SurfaceContainer
+    val ContainerMinHeight = 64.0.dp
     val ContentColor = ColorSchemeKeyTokens.OnSurfaceVariant
     val ContentTypography = TypographyKeyTokens.BodyLarge
     val Shape = ShapeKeyTokens.CornerLarge
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/CheckboxButtonTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/CheckboxButtonTokens.kt
index d0ff2f6..25c6f47 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/CheckboxButtonTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/CheckboxButtonTokens.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-// VERSION: v0_63
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ChildButtonTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ChildButtonTokens.kt
index 6efc706..3b050ce 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ChildButtonTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ChildButtonTokens.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-// VERSION: v0_11
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ColorSchemeKeyTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ColorSchemeKeyTokens.kt
index 3dbbc0c..bdafd77 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ColorSchemeKeyTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ColorSchemeKeyTokens.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-// VERSION: v0_42
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ColorTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ColorTokens.kt
index 68dc43f..a2e2591 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ColorTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ColorTokens.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-// VERSION: v0_42
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/CompactButtonTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/CompactButtonTokens.kt
index 577be84..97b5c3f 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/CompactButtonTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/CompactButtonTokens.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2024 The Android Open Source Project
+ * Copyright 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-// VERSION: v0_38
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/FilledButtonTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/FilledButtonTokens.kt
index d62ceb2..2e52543 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/FilledButtonTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/FilledButtonTokens.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-// VERSION: v0_11
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/FilledIconButtonTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/FilledIconButtonTokens.kt
index efed6a6..589ff4b 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/FilledIconButtonTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/FilledIconButtonTokens.kt
@@ -14,11 +14,10 @@
  * limitations under the License.
  */
 
-// VERSION: v0_12
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
-
 internal object FilledIconButtonTokens {
     val ContainerColor = ColorSchemeKeyTokens.Primary
     val ContentColor = ColorSchemeKeyTokens.OnPrimary
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/FilledTextButtonTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/FilledTextButtonTokens.kt
index 82c5bab..04e3d11 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/FilledTextButtonTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/FilledTextButtonTokens.kt
@@ -14,11 +14,10 @@
  * limitations under the License.
  */
 
-// VERSION: v0_27
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
-
 internal object FilledTextButtonTokens {
     val ContainerColor = ColorSchemeKeyTokens.Primary
     val ContainerShape = ShapeKeyTokens.CornerFull
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/FilledTonalButtonTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/FilledTonalButtonTokens.kt
index 9275864..1ad42ba 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/FilledTonalButtonTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/FilledTonalButtonTokens.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-// VERSION: v0_11
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/FilledTonalIconButtonTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/FilledTonalIconButtonTokens.kt
index f4dc76f..fa7cca4 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/FilledTonalIconButtonTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/FilledTonalIconButtonTokens.kt
@@ -14,11 +14,10 @@
  * limitations under the License.
  */
 
-// VERSION: v0_12
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
-
 internal object FilledTonalIconButtonTokens {
     val ContainerColor = ColorSchemeKeyTokens.SurfaceContainer
     val ContentColor = ColorSchemeKeyTokens.OnSurfaceVariant
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/FilledTonalTextButtonTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/FilledTonalTextButtonTokens.kt
index 876fbb5..a7c42e8 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/FilledTonalTextButtonTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/FilledTonalTextButtonTokens.kt
@@ -14,11 +14,10 @@
  * limitations under the License.
  */
 
-// VERSION: v0_27
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
-
 internal object FilledTonalTextButtonTokens {
     val ContainerColor = ColorSchemeKeyTokens.SurfaceContainer
     val ContainerShape = ShapeKeyTokens.CornerFull
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/IconButtonTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/IconButtonTokens.kt
index 76c1b63..34cb9fc 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/IconButtonTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/IconButtonTokens.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-// VERSION: v0_13
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/IconToggleButtonTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/IconToggleButtonTokens.kt
index c48f2e7..1ca8e5d 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/IconToggleButtonTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/IconToggleButtonTokens.kt
@@ -14,11 +14,10 @@
  * limitations under the License.
  */
 
-// VERSION: v0_16
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
-
 internal object IconToggleButtonTokens {
     val CheckedContainerColor = ColorSchemeKeyTokens.Primary
     val CheckedContentColor = ColorSchemeKeyTokens.OnPrimary
@@ -30,6 +29,7 @@
     val DisabledUncheckedContainerOpacity = 0.12f
     val DisabledUncheckedContentColor = ColorSchemeKeyTokens.OnSurface
     val DisabledUncheckedContentOpacity = 0.38f
+    val IconDisabledCheckedContainerShape = ShapeKeyTokens.CornerExtraLarge
     val UncheckedContainerColor = ColorSchemeKeyTokens.SurfaceContainer
     val UncheckedContentColor = ColorSchemeKeyTokens.OnSurfaceVariant
 }
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ImageButtonTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ImageButtonTokens.kt
index 51a8342..4af2dad 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ImageButtonTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ImageButtonTokens.kt
@@ -14,16 +14,15 @@
  * limitations under the License.
  */
 
-// VERSION: v0_33
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
-
 internal object ImageButtonTokens {
     val BackgroundImageGradientColor = ColorSchemeKeyTokens.SurfaceContainer
     val ContentColor = ColorSchemeKeyTokens.OnSurface
-    val DisabledContentOpacity = 0.38f
     val DisabledContentColor = ColorSchemeKeyTokens.OnSurface
+    val DisabledContentOpacity = 0.38f
     val GradientEndOpacity = 0.0f
     val GradientStartOpacity = 1.0f
     val IconColor = ColorSchemeKeyTokens.OnSurface
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ImageCardTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ImageCardTokens.kt
index bfeba1d..a6fe8bd 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ImageCardTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ImageCardTokens.kt
@@ -14,17 +14,16 @@
  * limitations under the License.
  */
 
-// VERSION: v0_32
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
-
 internal object ImageCardTokens {
     val AppNameColor = ColorSchemeKeyTokens.OnBackground
     val ContentColor = ColorSchemeKeyTokens.OnBackground
+    val OverlayScrimColor = ColorSchemeKeyTokens.Background
+    val OverlayScrimOpacity = 0.5f
     val SubtitleColor = ColorSchemeKeyTokens.Tertiary
     val TimeColor = ColorSchemeKeyTokens.OnBackground
     val TitleColor = ColorSchemeKeyTokens.OnBackground
-    val OverlayScrimColor = ColorSchemeKeyTokens.Background
-    val OverlayScrimOpacity = 0.5f
 }
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ListHeaderTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ListHeaderTokens.kt
index b2c398f..fc38bc0 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ListHeaderTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ListHeaderTokens.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-// VERSION: v0_32
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ListSubHeaderTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ListSubHeaderTokens.kt
index 0edf39e..a31f870 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ListSubHeaderTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ListSubHeaderTokens.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-// VERSION: v0_32
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/MotionTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/MotionTokens.kt
index 062e72c..a5a96a11 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/MotionTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/MotionTokens.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-// VERSION: v0_40
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/OutlinedButtonTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/OutlinedButtonTokens.kt
index 51371a0..62eb568 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/OutlinedButtonTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/OutlinedButtonTokens.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-// VERSION: v0_33
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
@@ -26,7 +26,7 @@
     val ContainerBorderWidth = 1.0.dp
     val ContainerHeight = 52.0.dp
     val ContainerShape = ShapeKeyTokens.CornerLarge
-    val DisabledContainerBorderColor = ColorSchemeKeyTokens.Outline
+    val DisabledContainerBorderColor = ColorSchemeKeyTokens.OnSurface
     val DisabledContainerBorderOpacity = 0.2f
     val DisabledContentColor = ColorSchemeKeyTokens.OnSurface
     val DisabledContentOpacity = 0.38f
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/OutlinedCardTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/OutlinedCardTokens.kt
index 56ae4af..8c17f20 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/OutlinedCardTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/OutlinedCardTokens.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-// VERSION: v0_32
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/OutlinedIconButtonTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/OutlinedIconButtonTokens.kt
index 9ec0db9..d0e84d0 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/OutlinedIconButtonTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/OutlinedIconButtonTokens.kt
@@ -14,11 +14,10 @@
  * limitations under the License.
  */
 
-// VERSION: v0_12
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
-
 internal object OutlinedIconButtonTokens {
     val ContentColor = ColorSchemeKeyTokens.OnSurface
     val DisabledContentColor = ColorSchemeKeyTokens.OnSurface
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/OutlinedTextButtonTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/OutlinedTextButtonTokens.kt
index 1012cb3..de29596 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/OutlinedTextButtonTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/OutlinedTextButtonTokens.kt
@@ -14,11 +14,10 @@
  * limitations under the License.
  */
 
-// VERSION: v0_27
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
-
 internal object OutlinedTextButtonTokens {
     val ContainerShape = ShapeKeyTokens.CornerFull
     val ContentColor = ColorSchemeKeyTokens.OnSurface
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/PaletteTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/PaletteTokens.kt
index 6c79d71..608479b 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/PaletteTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/PaletteTokens.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-// VERSION: v0_44
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/RadioButtonTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/RadioButtonTokens.kt
index 338020d..12ed324 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/RadioButtonTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/RadioButtonTokens.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-// VERSION: v0_57
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ShapeKeyTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ShapeKeyTokens.kt
index 0b8f5ed..653efce 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ShapeKeyTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ShapeKeyTokens.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-// VERSION: v0_7
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ShapeTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ShapeTokens.kt
index f9c5b20..a220415 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ShapeTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ShapeTokens.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-// VERSION: v0_45
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/SplitCheckboxButtonTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/SplitCheckboxButtonTokens.kt
index 43365d3..0c24b09 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/SplitCheckboxButtonTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/SplitCheckboxButtonTokens.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-// VERSION: v0_63
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/SplitRadioButtonTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/SplitRadioButtonTokens.kt
index d466ce3..acee450 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/SplitRadioButtonTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/SplitRadioButtonTokens.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-// VERSION: v0_58
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/SplitSwitchButtonTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/SplitSwitchButtonTokens.kt
new file mode 100644
index 0000000..1142bf0
--- /dev/null
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/SplitSwitchButtonTokens.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// VERSION: v0_65
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+package androidx.wear.compose.material3.tokens
+internal object SplitSwitchButtonTokens {
+    val CheckedContainerColor = ColorSchemeKeyTokens.PrimaryContainer
+    val CheckedContentColor = ColorSchemeKeyTokens.OnPrimaryContainer
+    val CheckedSecondaryLabelColor = ColorSchemeKeyTokens.OnPrimaryContainer
+    val CheckedSecondaryLabelOpacity = 0.8f
+    val CheckedSplitContainerColor = ColorSchemeKeyTokens.Primary
+    val CheckedSplitContainerOpacity = 0.15f
+    val CheckedThumbColor = ColorSchemeKeyTokens.OnPrimary
+    val CheckedThumbIconColor = ColorSchemeKeyTokens.Primary
+    val CheckedTrackBorderColor = ColorSchemeKeyTokens.Primary
+    val CheckedTrackColor = ColorSchemeKeyTokens.Primary
+    val ContainerShape = ShapeKeyTokens.CornerLarge
+    val DisabledCheckedContainerColor = ColorSchemeKeyTokens.PrimaryContainer
+    val DisabledCheckedContentColor = ColorSchemeKeyTokens.OnPrimaryContainer
+    val DisabledCheckedSecondaryLabelColor = ColorSchemeKeyTokens.OnPrimaryContainer
+    val DisabledCheckedSecondaryLabelOpacity = 0.8f
+    val DisabledCheckedSplitContainerColor = ColorSchemeKeyTokens.Primary
+    val DisabledCheckedSplitContainerOpacity = 0.15f
+    val DisabledCheckedThumbColor = ColorSchemeKeyTokens.Background
+    val DisabledCheckedThumbIconColor = ColorSchemeKeyTokens.OnSurface
+    val DisabledCheckedThumbIconOpacity = 0.12f
+    val DisabledCheckedThumbOpacity = 0.38f
+    val DisabledCheckedTrackBorderColor = ColorSchemeKeyTokens.OnSurface
+    val DisabledCheckedTrackBorderOpacity = 0.12f
+    val DisabledCheckedTrackColor = ColorSchemeKeyTokens.OnSurface
+    val DisabledCheckedTrackOpacity = 0.12f
+    val DisabledOpacity = 0.38f
+    val DisabledUncheckedContainerColor = ColorSchemeKeyTokens.SurfaceContainer
+    val DisabledUncheckedContentColor = ColorSchemeKeyTokens.OnSurface
+    val DisabledUncheckedSecondaryLabelColor = ColorSchemeKeyTokens.OnSurfaceVariant
+    val DisabledUncheckedSplitContainerColor = ColorSchemeKeyTokens.SurfaceContainerHigh
+    val DisabledUncheckedThumbColor = ColorSchemeKeyTokens.OnSurface
+    val DisabledUncheckedThumbOpacity = 0.12f
+    val DisabledUncheckedTrackBorderColor = ColorSchemeKeyTokens.OnSurface
+    val DisabledUncheckedTrackBorderOpacity = 0.12f
+    val LabelFont = TypographyKeyTokens.LabelMedium
+    val SecondaryLabelFont = TypographyKeyTokens.LabelSmall
+    val UncheckedContainerColor = ColorSchemeKeyTokens.SurfaceContainer
+    val UncheckedContentColor = ColorSchemeKeyTokens.OnSurface
+    val UncheckedSecondaryLabelColor = ColorSchemeKeyTokens.OnSurfaceVariant
+    val UncheckedSplitContainerColor = ColorSchemeKeyTokens.SurfaceContainerHigh
+    val UncheckedThumbColor = ColorSchemeKeyTokens.Outline
+    val UncheckedTrackBorderColor = ColorSchemeKeyTokens.Outline
+    val UncheckedTrackColor = ColorSchemeKeyTokens.SurfaceContainer
+}
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/SplitToggleButtonTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/SplitToggleButtonTokens.kt
deleted file mode 100644
index 73a0847..0000000
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/SplitToggleButtonTokens.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// VERSION: v0_40
-// GENERATED CODE - DO NOT MODIFY BY HAND
-
-package androidx.wear.compose.material3.tokens
-
-internal object SplitToggleButtonTokens {
-    val CheckedContainerColor = ColorSchemeKeyTokens.PrimaryContainer
-    val CheckedContentColor = ColorSchemeKeyTokens.OnPrimaryContainer
-    val CheckedSecondaryLabelColor = ColorSchemeKeyTokens.OnPrimaryContainer
-    val CheckedSecondaryLabelOpacity = 0.8f
-    val CheckedSplitContainerColor = ColorSchemeKeyTokens.Primary
-    val CheckedSplitContainerOpacity = 0.15f
-    val ContainerShape = ShapeKeyTokens.CornerLarge
-    val DisabledCheckedContainerColor = ColorSchemeKeyTokens.PrimaryContainer
-    val DisabledCheckedContentColor = ColorSchemeKeyTokens.OnPrimaryContainer
-    val DisabledCheckedSecondaryLabelColor = ColorSchemeKeyTokens.OnPrimaryContainer
-    val DisabledCheckedSecondaryLabelOpacity = 0.8f
-    val DisabledCheckedSplitContainerColor = ColorSchemeKeyTokens.Primary
-    val DisabledCheckedSplitContainerOpacity = 0.15f
-    val DisabledOpacity = 0.38f
-    val DisabledUncheckedContainerColor = ColorSchemeKeyTokens.SurfaceContainer
-    val DisabledUncheckedContentColor = ColorSchemeKeyTokens.OnSurface
-    val DisabledUncheckedSecondaryLabelColor = ColorSchemeKeyTokens.OnSurfaceVariant
-    val DisabledUncheckedSplitContainerColor = ColorSchemeKeyTokens.SurfaceContainerHigh
-    val LabelFont = TypographyKeyTokens.LabelMedium
-    val SecondaryLabelFont = TypographyKeyTokens.LabelSmall
-    val UncheckedContainerColor = ColorSchemeKeyTokens.SurfaceContainer
-    val UncheckedContentColor = ColorSchemeKeyTokens.OnSurface
-    val UncheckedSecondaryLabelColor = ColorSchemeKeyTokens.OnSurfaceVariant
-    val UncheckedSplitContainerColor = ColorSchemeKeyTokens.SurfaceContainerHigh
-}
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/SwitchButtonTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/SwitchButtonTokens.kt
new file mode 100644
index 0000000..657e8cc
--- /dev/null
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/SwitchButtonTokens.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// VERSION: v0_65
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+package androidx.wear.compose.material3.tokens
+internal object SwitchButtonTokens {
+    val CheckedContainerColor = ColorSchemeKeyTokens.PrimaryContainer
+    val CheckedContentColor = ColorSchemeKeyTokens.OnPrimaryContainer
+    val CheckedIconColor = ColorSchemeKeyTokens.Primary
+    val CheckedSecondaryLabelColor = ColorSchemeKeyTokens.OnPrimaryContainer
+    val CheckedSecondaryLabelOpacity = 0.8f
+    val CheckedThumbColor = ColorSchemeKeyTokens.OnPrimary
+    val CheckedThumbIconColor = ColorSchemeKeyTokens.Primary
+    val CheckedTrackBorderColor = ColorSchemeKeyTokens.Primary
+    val CheckedTrackColor = ColorSchemeKeyTokens.Primary
+    val ContainerShape = ShapeKeyTokens.CornerLarge
+    val DisabledCheckedContainerColor = ColorSchemeKeyTokens.OnSurface
+    val DisabledCheckedContainerOpacity = 0.12f
+    val DisabledCheckedContentColor = ColorSchemeKeyTokens.OnSurface
+    val DisabledCheckedIconColor = ColorSchemeKeyTokens.OnSurface
+    val DisabledCheckedSecondaryLabelColor = ColorSchemeKeyTokens.OnSurface
+    val DisabledCheckedThumbColor = ColorSchemeKeyTokens.Background
+    val DisabledCheckedThumbIconColor = ColorSchemeKeyTokens.OnSurface
+    val DisabledCheckedThumbIconOpacity = 0.12f
+    val DisabledCheckedThumbOpacity = 0.38f
+    val DisabledCheckedTrackBorderColor = ColorSchemeKeyTokens.OnSurface
+    val DisabledCheckedTrackBorderOpacity = 0.12f
+    val DisabledCheckedTrackColor = ColorSchemeKeyTokens.OnSurface
+    val DisabledCheckedTrackOpacity = 0.12f
+    val DisabledOpacity = 0.38f
+    val DisabledUncheckedContainerColor = ColorSchemeKeyTokens.OnSurface
+    val DisabledUncheckedContainerOpacity = 0.12f
+    val DisabledUncheckedContentColor = ColorSchemeKeyTokens.OnSurface
+    val DisabledUncheckedIconColor = ColorSchemeKeyTokens.OnSurface
+    val DisabledUncheckedSecondaryLabelColor = ColorSchemeKeyTokens.OnSurface
+    val DisabledUncheckedThumbColor = ColorSchemeKeyTokens.OnSurface
+    val DisabledUncheckedThumbOpacity = 0.12f
+    val DisabledUncheckedTrackBorderColor = ColorSchemeKeyTokens.OnSurface
+    val DisabledUncheckedTrackBorderOpacity = 0.12f
+    val LabelFont = TypographyKeyTokens.LabelMedium
+    val SecondaryLabelFont = TypographyKeyTokens.LabelSmall
+    val UncheckedContainerColor = ColorSchemeKeyTokens.SurfaceContainer
+    val UncheckedContentColor = ColorSchemeKeyTokens.OnSurface
+    val UncheckedIconColor = ColorSchemeKeyTokens.Primary
+    val UncheckedSecondaryLabelColor = ColorSchemeKeyTokens.OnSurfaceVariant
+    val UncheckedThumbColor = ColorSchemeKeyTokens.Outline
+    val UncheckedTrackBorderColor = ColorSchemeKeyTokens.Outline
+    val UncheckedTrackColor = ColorSchemeKeyTokens.SurfaceContainer
+}
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TextButtonTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TextButtonTokens.kt
index adffcf5..67ae831 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TextButtonTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TextButtonTokens.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-// VERSION: v0_27
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TextToggleButtonTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TextToggleButtonTokens.kt
index 9e2ff85..2cbf8fb 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TextToggleButtonTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TextToggleButtonTokens.kt
@@ -14,11 +14,10 @@
  * limitations under the License.
  */
 
-// VERSION: v0_26
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
-
 internal object TextToggleButtonTokens {
     val CheckedContainerColor = ColorSchemeKeyTokens.Primary
     val CheckedContentColor = ColorSchemeKeyTokens.OnPrimary
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ToggleButtonTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ToggleButtonTokens.kt
deleted file mode 100644
index d5bb0445..0000000
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/ToggleButtonTokens.kt
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// VERSION: v0_46
-// GENERATED CODE - DO NOT MODIFY BY HAND
-
-package androidx.wear.compose.material3.tokens
-internal object ToggleButtonTokens {
-    val CheckedContainerColor = ColorSchemeKeyTokens.PrimaryContainer
-    val CheckedContentColor = ColorSchemeKeyTokens.OnPrimaryContainer
-    val CheckedIconColor = ColorSchemeKeyTokens.Primary
-    val CheckedSecondaryLabelColor = ColorSchemeKeyTokens.OnPrimaryContainer
-    val CheckedSecondaryLabelOpacity = 0.8f
-    val ContainerShape = ShapeKeyTokens.CornerLarge
-    val DisabledCheckedContainerColor = ColorSchemeKeyTokens.OnSurface
-    val DisabledCheckedContainerOpacity = 0.12f
-    val DisabledCheckedContentColor = ColorSchemeKeyTokens.OnSurface
-    val DisabledCheckedIconColor = ColorSchemeKeyTokens.OnSurface
-    val DisabledCheckedSecondaryLabelColor = ColorSchemeKeyTokens.OnSurface
-    val DisabledOpacity = 0.38f
-    val DisabledUncheckedContainerColor = ColorSchemeKeyTokens.OnSurface
-    val DisabledUncheckedContainerOpacity = 0.12f
-    val DisabledUncheckedContentColor = ColorSchemeKeyTokens.OnSurface
-    val DisabledUncheckedIconColor = ColorSchemeKeyTokens.OnSurface
-    val DisabledUncheckedSecondaryLabelColor = ColorSchemeKeyTokens.OnSurface
-    val LabelFont = TypographyKeyTokens.LabelMedium
-    val SecondaryLabelFont = TypographyKeyTokens.LabelSmall
-    val UncheckedContainerColor = ColorSchemeKeyTokens.SurfaceContainer
-    val UncheckedContentColor = ColorSchemeKeyTokens.OnSurface
-    val UncheckedIconColor = ColorSchemeKeyTokens.Primary
-    val UncheckedSecondaryLabelColor = ColorSchemeKeyTokens.OnSurfaceVariant
-}
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TypeScaleTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TypeScaleTokens.kt
new file mode 100644
index 0000000..0190368
--- /dev/null
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TypeScaleTokens.kt
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// VERSION: v0_65
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+package androidx.wear.compose.material3.tokens
+
+import androidx.compose.ui.unit.sp
+
+internal object TypeScaleTokens {
+    val ArcMediumFont = TypefaceTokens.Brand
+    val ArcMediumLineHeight = 18.0.sp
+    val ArcMediumSize = 15.sp
+    val ArcMediumTracking = 0.2.sp
+    val ArcMediumWeight = 600.0f
+    val ArcMediumWeightProminent = 800.0f
+    val ArcMediumWidth = 100.0f
+    val ArcSmallFont = TypefaceTokens.Brand
+    val ArcSmallLineHeight = 16.0.sp
+    val ArcSmallSize = 14.sp
+    val ArcSmallTracking = 0.2.sp
+    val ArcSmallWeight = 560.0f
+    val ArcSmallWeightProminent = 760.0f
+    val ArcSmallWidth = 100.0f
+    val BodyExtraSmallFont = TypefaceTokens.Brand
+    val BodyExtraSmallLineHeight = 12.0.sp
+    val BodyExtraSmallSize = 10.sp
+    val BodyExtraSmallTracking = 0.2.sp
+    val BodyExtraSmallWeight = 500.0f
+    val BodyExtraSmallWeightProminent = 700.0f
+    val BodyExtraSmallWidth = 104.0f
+    val BodyLargeFont = TypefaceTokens.Brand
+    val BodyLargeLineHeight = 18.0.sp
+    val BodyLargeSize = 16.sp
+    val BodyLargeTracking = 0.4.sp
+    val BodyLargeWeight = 450.0f
+    val BodyLargeWeightProminent = 650.0f
+    val BodyLargeWidth = 110.0f
+    val BodyMediumFont = TypefaceTokens.Brand
+    val BodyMediumLineHeight = 16.0.sp
+    val BodyMediumSize = 14.sp
+    val BodyMediumTracking = 0.4.sp
+    val BodyMediumWeight = 450.0f
+    val BodyMediumWeightProminent = 650.0f
+    val BodyMediumWidth = 110.0f
+    val BodySmallFont = TypefaceTokens.Brand
+    val BodySmallLineHeight = 14.0.sp
+    val BodySmallSize = 12.sp
+    val BodySmallTracking = 0.4.sp
+    val BodySmallWeight = 500.0f
+    val BodySmallWeightProminent = 700.0f
+    val BodySmallWidth = 110.0f
+    val DisplayLargeFont = TypefaceTokens.Brand
+    val DisplayLargeLineHeight = 44.0.sp
+    val DisplayLargeSize = 40.sp
+    val DisplayLargeTracking = 0.2.sp
+    val DisplayLargeWeight = 500.0f
+    val DisplayLargeWidth = 110.0f
+    val DisplayMediumFont = TypefaceTokens.Brand
+    val DisplayMediumLineHeight = 36.0.sp
+    val DisplayMediumSize = 30.sp
+    val DisplayMediumTracking = 0.2.sp
+    val DisplayMediumWeight = 520.0f
+    val DisplayMediumWidth = 110.0f
+    val DisplaySmallFont = TypefaceTokens.Brand
+    val DisplaySmallLineHeight = 26.0.sp
+    val DisplaySmallSize = 24.sp
+    val DisplaySmallTracking = 0.2.sp
+    val DisplaySmallWeight = 550.0f
+    val DisplaySmallWidth = 110.0f
+    val LabelLargeFont = TypefaceTokens.Brand
+    val LabelLargeLineHeight = 22.0.sp
+    val LabelLargeSize = 20.sp
+    val LabelLargeTracking = 0.4.sp
+    val LabelLargeWeight = 500.0f
+    val LabelLargeWidth = 110.0f
+    val LabelMediumFont = TypefaceTokens.Brand
+    val LabelMediumLineHeight = 16.0.sp
+    val LabelMediumSize = 15.sp
+    val LabelMediumTracking = 0.4.sp
+    val LabelMediumWeight = 500.0f
+    val LabelMediumWidth = 110.0f
+    val LabelSmallFont = TypefaceTokens.Brand
+    val LabelSmallLineHeight = 16.0.sp
+    val LabelSmallSize = 13.sp
+    val LabelSmallTracking = 0.4.sp
+    val LabelSmallWeight = 500.0f
+    val LabelSmallWidth = 110.0f
+    val NumeralExtraLargeFont = TypefaceTokens.Brand
+    val NumeralExtraLargeLineHeight = 60.0.sp
+    val NumeralExtraLargeSize = 60.sp
+    val NumeralExtraLargeTracking = 0.0.sp
+    val NumeralExtraLargeWeight = 560.0f
+    val NumeralExtraLargeWeightProminent = 760.0f
+    val NumeralExtraLargeWidth = 110.0f
+    val NumeralExtraSmallFont = TypefaceTokens.Brand
+    val NumeralExtraSmallLineHeight = 24.0.sp
+    val NumeralExtraSmallSize = 24.sp
+    val NumeralExtraSmallTracking = 0.0.sp
+    val NumeralExtraSmallWeight = 550.0f
+    val NumeralExtraSmallWeightProminent = 750.0f
+    val NumeralExtraSmallWidth = 100.0f
+    val NumeralLargeFont = TypefaceTokens.Brand
+    val NumeralLargeLineHeight = 50.0.sp
+    val NumeralLargeSize = 50.sp
+    val NumeralLargeTracking = 1.0.sp
+    val NumeralLargeWeight = 580.0f
+    val NumeralLargeWeightProminent = 780.0f
+    val NumeralLargeWidth = 110.0f
+    val NumeralMediumFont = TypefaceTokens.Brand
+    val NumeralMediumLineHeight = 40.0.sp
+    val NumeralMediumSize = 40.sp
+    val NumeralMediumTracking = 0.0.sp
+    val NumeralMediumWeight = 580.0f
+    val NumeralMediumWeightProminent = 780.0f
+    val NumeralMediumWidth = 100.0f
+    val NumeralSmallFont = TypefaceTokens.Brand
+    val NumeralSmallLineHeight = 30.0.sp
+    val NumeralSmallSize = 30.sp
+    val NumeralSmallTracking = 1.0.sp
+    val NumeralSmallWeight = 550.0f
+    val NumeralSmallWeightProminent = 750.0f
+    val NumeralSmallWidth = 100.0f
+    val TitleLargeFont = TypefaceTokens.Brand
+    val TitleLargeLineHeight = 22.0.sp
+    val TitleLargeSize = 20.sp
+    val TitleLargeTracking = 0.2.sp
+    val TitleLargeWeight = 500.0f
+    val TitleLargeWidth = 110.0f
+    val TitleMediumFont = TypefaceTokens.Brand
+    val TitleMediumLineHeight = 18.0.sp
+    val TitleMediumSize = 16.sp
+    val TitleMediumTracking = 0.4.sp
+    val TitleMediumWeight = 500.0f
+    val TitleMediumWidth = 110.0f
+    val TitleSmallFont = TypefaceTokens.Brand
+    val TitleSmallLineHeight = 16.0.sp
+    val TitleSmallSize = 14.sp
+    val TitleSmallTracking = 0.4.sp
+    val TitleSmallWeight = 500.0f
+    val TitleSmallWidth = 110.0f
+}
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TypefaceTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TypefaceTokens.kt
index 2eea3e2..aeb00d3 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TypefaceTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TypefaceTokens.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 The Android Open Source Project
+ * Copyright 2024 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-// VERSION: v0_8
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
@@ -24,8 +24,7 @@
 
 internal object TypefaceTokens {
     val Brand = FontFamily.SansSerif
-    val MediumWeight = FontWeight.Medium
-    val Plain = FontFamily.SansSerif
-    val RegularWeight = FontWeight.Normal
     val WeightBold = FontWeight.Bold
+    val WeightMedium = FontWeight.Medium
+    val WeightRegular = FontWeight.Normal
 }
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TypescaleTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TypescaleTokens.kt
deleted file mode 100644
index 858bbf7..0000000
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TypescaleTokens.kt
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// VERSION: v0_9
-// GENERATED CODE - DO NOT MODIFY BY HAND
-
-package androidx.wear.compose.material3.tokens
-
-import androidx.compose.ui.unit.sp
-
-internal object TypeScaleTokens {
-    val BodyExtraSmallFont = TypefaceTokens.Brand
-    val BodyExtraSmallLineHeight = 14.0.sp
-    val BodyExtraSmallSize = 11.sp
-    val BodyExtraSmallTracking = 0.4.sp
-    val BodyExtraSmallWeight = TypefaceTokens.RegularWeight
-    val BodyExtraSmallWeightProminent = TypefaceTokens.WeightBold
-    val BodyLargeFont = TypefaceTokens.Brand
-    val BodyLargeLineHeight = 18.0.sp
-    val BodyLargeSize = 16.sp
-    val BodyLargeTracking = 0.3.sp
-    val BodyLargeWeight = TypefaceTokens.RegularWeight
-    val BodyLargeWeightProminent = TypefaceTokens.WeightBold
-    val BodyMediumFont = TypefaceTokens.Brand
-    val BodyMediumLineHeight = 18.0.sp
-    val BodyMediumSize = 14.sp
-    val BodyMediumTracking = 0.2.sp
-    val BodyMediumWeight = TypefaceTokens.RegularWeight
-    val BodyMediumWeightProminent = TypefaceTokens.WeightBold
-    val BodySmallFont = TypefaceTokens.Brand
-    val BodySmallLineHeight = 16.0.sp
-    val BodySmallSize = 12.sp
-    val BodySmallTracking = 0.4.sp
-    val BodySmallWeight = TypefaceTokens.MediumWeight
-    val BodySmallWeightProminent = TypefaceTokens.WeightBold
-    val DisplayLargeFont = TypefaceTokens.Brand
-    val DisplayLargeLineHeight = 44.0.sp
-    val DisplayLargeSize = 40.sp
-    val DisplayLargeTracking = 0.0.sp
-    val DisplayLargeWeight = TypefaceTokens.RegularWeight
-    val DisplayMediumFont = TypefaceTokens.Brand
-    val DisplayMediumLineHeight = 34.0.sp
-    val DisplayMediumSize = 30.sp
-    val DisplayMediumTracking = 0.0.sp
-    val DisplayMediumWeight = TypefaceTokens.RegularWeight
-    val DisplaySmallFont = TypefaceTokens.Brand
-    val DisplaySmallLineHeight = 28.0.sp
-    val DisplaySmallSize = 24.sp
-    val DisplaySmallTracking = 0.0.sp
-    val DisplaySmallWeight = TypefaceTokens.MediumWeight
-    val LabelLargeFont = TypefaceTokens.Brand
-    val LabelLargeLineHeight = 22.0.sp
-    val LabelLargeSize = 20.sp
-    val LabelLargeTracking = 0.2.sp
-    val LabelLargeWeight = TypefaceTokens.MediumWeight
-    val LabelMediumFont = TypefaceTokens.Brand
-    val LabelMediumLineHeight = 16.0.sp
-    val LabelMediumSize = 15.sp
-    val LabelMediumTracking = 0.2.sp
-    val LabelMediumWeight = TypefaceTokens.MediumWeight
-    val LabelSmallFont = TypefaceTokens.Brand
-    val LabelSmallLineHeight = 14.0.sp
-    val LabelSmallSize = 13.sp
-    val LabelSmallTracking = 0.3.sp
-    val LabelSmallWeight = TypefaceTokens.MediumWeight
-    val TitleLargeFont = TypefaceTokens.Brand
-    val TitleLargeLineHeight = 22.0.sp
-    val TitleLargeSize = 20.sp
-    val TitleLargeTracking = 0.2.sp
-    val TitleLargeWeight = TypefaceTokens.MediumWeight
-    val TitleMediumFont = TypefaceTokens.Brand
-    val TitleMediumLineHeight = 18.0.sp
-    val TitleMediumSize = 16.sp
-    val TitleMediumTracking = 0.3.sp
-    val TitleMediumWeight = TypefaceTokens.MediumWeight
-    val TitleSmallFont = TypefaceTokens.Brand
-    val TitleSmallLineHeight = 16.0.sp
-    val TitleSmallSize = 14.sp
-    val TitleSmallTracking = 0.3.sp
-    val TitleSmallWeight = TypefaceTokens.MediumWeight
-}
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TypographyKeyTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TypographyKeyTokens.kt
index 40869af..bb04daa 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TypographyKeyTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TypographyKeyTokens.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 The Android Open Source Project
+ * Copyright 2024 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,12 +14,14 @@
  * limitations under the License.
  */
 
-// VERSION: v0_8
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
 
 internal enum class TypographyKeyTokens {
+    ArcMedium,
+    ArcSmall,
     BodyExtraSmall,
     BodyLarge,
     BodyMedium,
@@ -30,6 +32,11 @@
     LabelLarge,
     LabelMedium,
     LabelSmall,
+    NumeralExtraLarge,
+    NumeralExtraSmall,
+    NumeralLarge,
+    NumeralMedium,
+    NumeralSmall,
     TitleLarge,
     TitleMedium,
     TitleSmall,
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TypographyTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TypographyTokens.kt
index 60131a2..cfb310e 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TypographyTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TypographyTokens.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 The Android Open Source Project
+ * Copyright 2024 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,114 +14,313 @@
  * limitations under the License.
  */
 
-// VERSION: v0_8
+// VERSION: v0_65
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.wear.compose.material3.tokens
 
+import androidx.compose.ui.text.font.DeviceFontFamilyName
+import androidx.compose.ui.text.font.Font
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.font.toFontFamily
 import androidx.wear.compose.material3.DefaultTextStyle
 
 internal object TypographyTokens {
+    val ArcMedium =
+        DefaultTextStyle.copy(
+            fontFamily =
+                Font(
+                        DeviceFontFamilyName(TypeScaleTokens.ArcMediumFont.name),
+                        weight = FontWeight(TypeScaleTokens.ArcMediumWeight.toInt()),
+                        variationSettings =
+                            TypographyVariableFontsTokens.ArcMediumVariationSettings,
+                    )
+                    .toFontFamily(),
+            fontWeight = FontWeight(TypeScaleTokens.ArcMediumWeight.toInt()),
+            fontSize = TypeScaleTokens.ArcMediumSize,
+            lineHeight = TypeScaleTokens.ArcMediumLineHeight,
+            letterSpacing = TypeScaleTokens.ArcMediumTracking,
+        )
+    val ArcSmall =
+        DefaultTextStyle.copy(
+            fontFamily =
+                Font(
+                        DeviceFontFamilyName(TypeScaleTokens.ArcSmallFont.name),
+                        weight = FontWeight(TypeScaleTokens.ArcSmallWeight.toInt()),
+                        variationSettings = TypographyVariableFontsTokens.ArcSmallVariationSettings,
+                    )
+                    .toFontFamily(),
+            fontWeight = FontWeight(TypeScaleTokens.ArcSmallWeight.toInt()),
+            fontSize = TypeScaleTokens.ArcSmallSize,
+            lineHeight = TypeScaleTokens.ArcSmallLineHeight,
+            letterSpacing = TypeScaleTokens.ArcSmallTracking,
+        )
     val BodyExtraSmall =
         DefaultTextStyle.copy(
-            fontFamily = TypeScaleTokens.BodyExtraSmallFont,
-            fontWeight = TypeScaleTokens.BodyExtraSmallWeight,
+            fontFamily =
+                Font(
+                        DeviceFontFamilyName(TypeScaleTokens.BodyExtraSmallFont.name),
+                        weight = FontWeight(TypeScaleTokens.BodyExtraSmallWeight.toInt()),
+                        variationSettings =
+                            TypographyVariableFontsTokens.BodyExtraSmallVariationSettings,
+                    )
+                    .toFontFamily(),
+            fontWeight = FontWeight(TypeScaleTokens.BodyExtraSmallWeight.toInt()),
             fontSize = TypeScaleTokens.BodyExtraSmallSize,
             lineHeight = TypeScaleTokens.BodyExtraSmallLineHeight,
             letterSpacing = TypeScaleTokens.BodyExtraSmallTracking,
         )
     val BodyLarge =
         DefaultTextStyle.copy(
-            fontFamily = TypeScaleTokens.BodyLargeFont,
-            fontWeight = TypeScaleTokens.BodyLargeWeight,
+            fontFamily =
+                Font(
+                        DeviceFontFamilyName(TypeScaleTokens.BodyLargeFont.name),
+                        weight = FontWeight(TypeScaleTokens.BodyLargeWeight.toInt()),
+                        variationSettings =
+                            TypographyVariableFontsTokens.BodyLargeVariationSettings,
+                    )
+                    .toFontFamily(),
+            fontWeight = FontWeight(TypeScaleTokens.BodyLargeWeight.toInt()),
             fontSize = TypeScaleTokens.BodyLargeSize,
             lineHeight = TypeScaleTokens.BodyLargeLineHeight,
             letterSpacing = TypeScaleTokens.BodyLargeTracking,
         )
     val BodyMedium =
         DefaultTextStyle.copy(
-            fontFamily = TypeScaleTokens.BodyMediumFont,
-            fontWeight = TypeScaleTokens.BodyMediumWeight,
+            fontFamily =
+                Font(
+                        DeviceFontFamilyName(TypeScaleTokens.BodyMediumFont.name),
+                        weight = FontWeight(TypeScaleTokens.BodyMediumWeight.toInt()),
+                        variationSettings =
+                            TypographyVariableFontsTokens.BodyMediumVariationSettings,
+                    )
+                    .toFontFamily(),
+            fontWeight = FontWeight(TypeScaleTokens.BodyMediumWeight.toInt()),
             fontSize = TypeScaleTokens.BodyMediumSize,
             lineHeight = TypeScaleTokens.BodyMediumLineHeight,
             letterSpacing = TypeScaleTokens.BodyMediumTracking,
         )
     val BodySmall =
         DefaultTextStyle.copy(
-            fontFamily = TypeScaleTokens.BodySmallFont,
-            fontWeight = TypeScaleTokens.BodySmallWeight,
+            fontFamily =
+                Font(
+                        DeviceFontFamilyName(TypeScaleTokens.BodySmallFont.name),
+                        weight = FontWeight(TypeScaleTokens.BodySmallWeight.toInt()),
+                        variationSettings =
+                            TypographyVariableFontsTokens.BodySmallVariationSettings,
+                    )
+                    .toFontFamily(),
+            fontWeight = FontWeight(TypeScaleTokens.BodySmallWeight.toInt()),
             fontSize = TypeScaleTokens.BodySmallSize,
             lineHeight = TypeScaleTokens.BodySmallLineHeight,
             letterSpacing = TypeScaleTokens.BodySmallTracking,
         )
     val DisplayLarge =
         DefaultTextStyle.copy(
-            fontFamily = TypeScaleTokens.DisplayLargeFont,
-            fontWeight = TypeScaleTokens.DisplayLargeWeight,
+            fontFamily =
+                Font(
+                        DeviceFontFamilyName(TypeScaleTokens.DisplayLargeFont.name),
+                        weight = FontWeight(TypeScaleTokens.DisplayLargeWeight.toInt()),
+                        variationSettings =
+                            TypographyVariableFontsTokens.DisplayLargeVariationSettings,
+                    )
+                    .toFontFamily(),
+            fontWeight = FontWeight(TypeScaleTokens.DisplayLargeWeight.toInt()),
             fontSize = TypeScaleTokens.DisplayLargeSize,
             lineHeight = TypeScaleTokens.DisplayLargeLineHeight,
             letterSpacing = TypeScaleTokens.DisplayLargeTracking,
         )
     val DisplayMedium =
         DefaultTextStyle.copy(
-            fontFamily = TypeScaleTokens.DisplayMediumFont,
-            fontWeight = TypeScaleTokens.DisplayMediumWeight,
+            fontFamily =
+                Font(
+                        DeviceFontFamilyName(TypeScaleTokens.DisplayMediumFont.name),
+                        weight = FontWeight(TypeScaleTokens.DisplayMediumWeight.toInt()),
+                        variationSettings =
+                            TypographyVariableFontsTokens.DisplayMediumVariationSettings,
+                    )
+                    .toFontFamily(),
+            fontWeight = FontWeight(TypeScaleTokens.DisplayMediumWeight.toInt()),
             fontSize = TypeScaleTokens.DisplayMediumSize,
             lineHeight = TypeScaleTokens.DisplayMediumLineHeight,
             letterSpacing = TypeScaleTokens.DisplayMediumTracking,
         )
     val DisplaySmall =
         DefaultTextStyle.copy(
-            fontFamily = TypeScaleTokens.DisplaySmallFont,
-            fontWeight = TypeScaleTokens.DisplaySmallWeight,
+            fontFamily =
+                Font(
+                        DeviceFontFamilyName(TypeScaleTokens.DisplaySmallFont.name),
+                        weight = FontWeight(TypeScaleTokens.DisplaySmallWeight.toInt()),
+                        variationSettings =
+                            TypographyVariableFontsTokens.DisplaySmallVariationSettings,
+                    )
+                    .toFontFamily(),
+            fontWeight = FontWeight(TypeScaleTokens.DisplaySmallWeight.toInt()),
             fontSize = TypeScaleTokens.DisplaySmallSize,
             lineHeight = TypeScaleTokens.DisplaySmallLineHeight,
             letterSpacing = TypeScaleTokens.DisplaySmallTracking,
         )
     val LabelLarge =
         DefaultTextStyle.copy(
-            fontFamily = TypeScaleTokens.LabelLargeFont,
-            fontWeight = TypeScaleTokens.LabelLargeWeight,
+            fontFamily =
+                Font(
+                        DeviceFontFamilyName(TypeScaleTokens.LabelLargeFont.name),
+                        weight = FontWeight(TypeScaleTokens.LabelLargeWeight.toInt()),
+                        variationSettings =
+                            TypographyVariableFontsTokens.LabelLargeVariationSettings,
+                    )
+                    .toFontFamily(),
+            fontWeight = FontWeight(TypeScaleTokens.LabelLargeWeight.toInt()),
             fontSize = TypeScaleTokens.LabelLargeSize,
             lineHeight = TypeScaleTokens.LabelLargeLineHeight,
             letterSpacing = TypeScaleTokens.LabelLargeTracking,
         )
     val LabelMedium =
         DefaultTextStyle.copy(
-            fontFamily = TypeScaleTokens.LabelMediumFont,
-            fontWeight = TypeScaleTokens.LabelMediumWeight,
+            fontFamily =
+                Font(
+                        DeviceFontFamilyName(TypeScaleTokens.LabelMediumFont.name),
+                        weight = FontWeight(TypeScaleTokens.LabelMediumWeight.toInt()),
+                        variationSettings =
+                            TypographyVariableFontsTokens.LabelMediumVariationSettings,
+                    )
+                    .toFontFamily(),
+            fontWeight = FontWeight(TypeScaleTokens.LabelMediumWeight.toInt()),
             fontSize = TypeScaleTokens.LabelMediumSize,
             lineHeight = TypeScaleTokens.LabelMediumLineHeight,
             letterSpacing = TypeScaleTokens.LabelMediumTracking,
         )
     val LabelSmall =
         DefaultTextStyle.copy(
-            fontFamily = TypeScaleTokens.LabelSmallFont,
-            fontWeight = TypeScaleTokens.LabelSmallWeight,
+            fontFamily =
+                Font(
+                        DeviceFontFamilyName(TypeScaleTokens.LabelSmallFont.name),
+                        weight = FontWeight(TypeScaleTokens.LabelSmallWeight.toInt()),
+                        variationSettings =
+                            TypographyVariableFontsTokens.LabelSmallVariationSettings,
+                    )
+                    .toFontFamily(),
+            fontWeight = FontWeight(TypeScaleTokens.LabelSmallWeight.toInt()),
             fontSize = TypeScaleTokens.LabelSmallSize,
             lineHeight = TypeScaleTokens.LabelSmallLineHeight,
             letterSpacing = TypeScaleTokens.LabelSmallTracking,
         )
+    val NumeralExtraLarge =
+        DefaultTextStyle.copy(
+            fontFamily =
+                Font(
+                        DeviceFontFamilyName(TypeScaleTokens.NumeralExtraLargeFont.name),
+                        weight = FontWeight(TypeScaleTokens.NumeralExtraLargeWeight.toInt()),
+                        variationSettings =
+                            TypographyVariableFontsTokens.NumeralExtraLargeVariationSettings,
+                    )
+                    .toFontFamily(),
+            fontWeight = FontWeight(TypeScaleTokens.NumeralExtraLargeWeight.toInt()),
+            fontSize = TypeScaleTokens.NumeralExtraLargeSize,
+            lineHeight = TypeScaleTokens.NumeralExtraLargeLineHeight,
+            letterSpacing = TypeScaleTokens.NumeralExtraLargeTracking,
+        )
+    val NumeralExtraSmall =
+        DefaultTextStyle.copy(
+            fontFamily =
+                Font(
+                        DeviceFontFamilyName(TypeScaleTokens.NumeralExtraSmallFont.name),
+                        weight = FontWeight(TypeScaleTokens.NumeralExtraSmallWeight.toInt()),
+                        variationSettings =
+                            TypographyVariableFontsTokens.NumeralExtraSmallVariationSettings,
+                    )
+                    .toFontFamily(),
+            fontWeight = FontWeight(TypeScaleTokens.NumeralExtraSmallWeight.toInt()),
+            fontSize = TypeScaleTokens.NumeralExtraSmallSize,
+            lineHeight = TypeScaleTokens.NumeralExtraSmallLineHeight,
+            letterSpacing = TypeScaleTokens.NumeralExtraSmallTracking,
+        )
+    val NumeralLarge =
+        DefaultTextStyle.copy(
+            fontFamily =
+                Font(
+                        DeviceFontFamilyName(TypeScaleTokens.NumeralLargeFont.name),
+                        weight = FontWeight(TypeScaleTokens.NumeralLargeWeight.toInt()),
+                        variationSettings =
+                            TypographyVariableFontsTokens.NumeralLargeVariationSettings,
+                    )
+                    .toFontFamily(),
+            fontWeight = FontWeight(TypeScaleTokens.NumeralLargeWeight.toInt()),
+            fontSize = TypeScaleTokens.NumeralLargeSize,
+            lineHeight = TypeScaleTokens.NumeralLargeLineHeight,
+            letterSpacing = TypeScaleTokens.NumeralLargeTracking,
+        )
+    val NumeralMedium =
+        DefaultTextStyle.copy(
+            fontFamily =
+                Font(
+                        DeviceFontFamilyName(TypeScaleTokens.NumeralMediumFont.name),
+                        weight = FontWeight(TypeScaleTokens.NumeralMediumWeight.toInt()),
+                        variationSettings =
+                            TypographyVariableFontsTokens.NumeralMediumVariationSettings,
+                    )
+                    .toFontFamily(),
+            fontWeight = FontWeight(TypeScaleTokens.NumeralMediumWeight.toInt()),
+            fontSize = TypeScaleTokens.NumeralMediumSize,
+            lineHeight = TypeScaleTokens.NumeralMediumLineHeight,
+            letterSpacing = TypeScaleTokens.NumeralMediumTracking,
+        )
+    val NumeralSmall =
+        DefaultTextStyle.copy(
+            fontFamily =
+                Font(
+                        DeviceFontFamilyName(TypeScaleTokens.NumeralSmallFont.name),
+                        weight = FontWeight(TypeScaleTokens.NumeralSmallWeight.toInt()),
+                        variationSettings =
+                            TypographyVariableFontsTokens.NumeralSmallVariationSettings,
+                    )
+                    .toFontFamily(),
+            fontWeight = FontWeight(TypeScaleTokens.NumeralSmallWeight.toInt()),
+            fontSize = TypeScaleTokens.NumeralSmallSize,
+            lineHeight = TypeScaleTokens.NumeralSmallLineHeight,
+            letterSpacing = TypeScaleTokens.NumeralSmallTracking,
+        )
     val TitleLarge =
         DefaultTextStyle.copy(
-            fontFamily = TypeScaleTokens.TitleLargeFont,
-            fontWeight = TypeScaleTokens.TitleLargeWeight,
+            fontFamily =
+                Font(
+                        DeviceFontFamilyName(TypeScaleTokens.TitleLargeFont.name),
+                        weight = FontWeight(TypeScaleTokens.TitleLargeWeight.toInt()),
+                        variationSettings =
+                            TypographyVariableFontsTokens.TitleLargeVariationSettings,
+                    )
+                    .toFontFamily(),
+            fontWeight = FontWeight(TypeScaleTokens.TitleLargeWeight.toInt()),
             fontSize = TypeScaleTokens.TitleLargeSize,
             lineHeight = TypeScaleTokens.TitleLargeLineHeight,
             letterSpacing = TypeScaleTokens.TitleLargeTracking,
         )
     val TitleMedium =
         DefaultTextStyle.copy(
-            fontFamily = TypeScaleTokens.TitleMediumFont,
-            fontWeight = TypeScaleTokens.TitleMediumWeight,
+            fontFamily =
+                Font(
+                        DeviceFontFamilyName(TypeScaleTokens.TitleMediumFont.name),
+                        weight = FontWeight(TypeScaleTokens.TitleMediumWeight.toInt()),
+                        variationSettings =
+                            TypographyVariableFontsTokens.TitleMediumVariationSettings,
+                    )
+                    .toFontFamily(),
+            fontWeight = FontWeight(TypeScaleTokens.TitleMediumWeight.toInt()),
             fontSize = TypeScaleTokens.TitleMediumSize,
             lineHeight = TypeScaleTokens.TitleMediumLineHeight,
             letterSpacing = TypeScaleTokens.TitleMediumTracking,
         )
     val TitleSmall =
         DefaultTextStyle.copy(
-            fontFamily = TypeScaleTokens.TitleSmallFont,
-            fontWeight = TypeScaleTokens.TitleSmallWeight,
+            fontFamily =
+                Font(
+                        DeviceFontFamilyName(TypeScaleTokens.TitleSmallFont.name),
+                        weight = FontWeight(TypeScaleTokens.TitleSmallWeight.toInt()),
+                        variationSettings =
+                            TypographyVariableFontsTokens.TitleSmallVariationSettings,
+                    )
+                    .toFontFamily(),
+            fontWeight = FontWeight(TypeScaleTokens.TitleSmallWeight.toInt()),
             fontSize = TypeScaleTokens.TitleSmallSize,
             lineHeight = TypeScaleTokens.TitleSmallLineHeight,
             letterSpacing = TypeScaleTokens.TitleSmallTracking,
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TypographyVariableFontsTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TypographyVariableFontsTokens.kt
new file mode 100644
index 0000000..dd22c78
--- /dev/null
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/TypographyVariableFontsTokens.kt
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// VERSION: v0_65
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+package androidx.wear.compose.material3.tokens
+
+import androidx.compose.ui.text.font.FontVariation
+
+internal object TypographyVariableFontsTokens {
+    val ArcMediumVariationSettings =
+        FontVariation.Settings(
+            FontVariation.Setting("wdth", TypeScaleTokens.ArcMediumWidth),
+            FontVariation.Setting("wght", TypeScaleTokens.ArcMediumWeight),
+        )
+    val ArcSmallVariationSettings =
+        FontVariation.Settings(
+            FontVariation.Setting("wght", TypeScaleTokens.ArcSmallWeight),
+            FontVariation.Setting("wdth", TypeScaleTokens.ArcSmallWidth),
+        )
+    val BodyExtraSmallVariationSettings =
+        FontVariation.Settings(
+            FontVariation.Setting("wdth", TypeScaleTokens.BodyExtraSmallWidth),
+            FontVariation.Setting("wght", TypeScaleTokens.BodyExtraSmallWeight),
+        )
+    val BodyLargeVariationSettings =
+        FontVariation.Settings(
+            FontVariation.Setting("wght", TypeScaleTokens.BodyLargeWeight),
+            FontVariation.Setting("wdth", TypeScaleTokens.BodyLargeWidth),
+        )
+    val BodyMediumVariationSettings =
+        FontVariation.Settings(
+            FontVariation.Setting("wdth", TypeScaleTokens.BodyMediumWidth),
+            FontVariation.Setting("wght", TypeScaleTokens.BodyMediumWeight),
+        )
+    val BodySmallVariationSettings =
+        FontVariation.Settings(
+            FontVariation.Setting("wght", TypeScaleTokens.BodySmallWeight),
+            FontVariation.Setting("wdth", TypeScaleTokens.BodySmallWidth),
+        )
+    val DisplayLargeVariationSettings =
+        FontVariation.Settings(
+            FontVariation.Setting("wdth", TypeScaleTokens.DisplayLargeWidth),
+            FontVariation.Setting("wght", TypeScaleTokens.DisplayLargeWeight),
+        )
+    val DisplayMediumVariationSettings =
+        FontVariation.Settings(
+            FontVariation.Setting("wght", TypeScaleTokens.DisplayMediumWeight),
+            FontVariation.Setting("wdth", TypeScaleTokens.DisplayMediumWidth),
+        )
+    val DisplaySmallVariationSettings =
+        FontVariation.Settings(
+            FontVariation.Setting("wght", TypeScaleTokens.DisplaySmallWeight),
+            FontVariation.Setting("wdth", TypeScaleTokens.DisplaySmallWidth),
+        )
+    val LabelLargeVariationSettings =
+        FontVariation.Settings(
+            FontVariation.Setting("wght", TypeScaleTokens.LabelLargeWeight),
+            FontVariation.Setting("wdth", TypeScaleTokens.LabelLargeWidth),
+        )
+    val LabelMediumVariationSettings =
+        FontVariation.Settings(
+            FontVariation.Setting("wdth", TypeScaleTokens.LabelMediumWidth),
+            FontVariation.Setting("wght", TypeScaleTokens.LabelMediumWeight),
+        )
+    val LabelSmallVariationSettings =
+        FontVariation.Settings(
+            FontVariation.Setting("wdth", TypeScaleTokens.LabelSmallWidth),
+            FontVariation.Setting("wght", TypeScaleTokens.LabelSmallWeight),
+        )
+    val NumeralExtraLargeVariationSettings =
+        FontVariation.Settings(
+            FontVariation.Setting("wdth", TypeScaleTokens.NumeralExtraLargeWidth),
+            FontVariation.Setting("wght", TypeScaleTokens.NumeralExtraLargeWeight),
+        )
+    val NumeralExtraSmallVariationSettings =
+        FontVariation.Settings(
+            FontVariation.Setting("wdth", TypeScaleTokens.NumeralExtraSmallWidth),
+            FontVariation.Setting("wght", TypeScaleTokens.NumeralExtraSmallWeight),
+        )
+    val NumeralLargeVariationSettings =
+        FontVariation.Settings(
+            FontVariation.Setting("wdth", TypeScaleTokens.NumeralLargeWidth),
+            FontVariation.Setting("wght", TypeScaleTokens.NumeralLargeWeight),
+        )
+    val NumeralMediumVariationSettings =
+        FontVariation.Settings(
+            FontVariation.Setting("wght", TypeScaleTokens.NumeralMediumWeight),
+            FontVariation.Setting("wdth", TypeScaleTokens.NumeralMediumWidth),
+        )
+    val NumeralSmallVariationSettings =
+        FontVariation.Settings(
+            FontVariation.Setting("wdth", TypeScaleTokens.NumeralSmallWidth),
+            FontVariation.Setting("wght", TypeScaleTokens.NumeralSmallWeight),
+        )
+    val TitleLargeVariationSettings =
+        FontVariation.Settings(
+            FontVariation.Setting("wght", TypeScaleTokens.TitleLargeWeight),
+            FontVariation.Setting("wdth", TypeScaleTokens.TitleLargeWidth),
+        )
+    val TitleMediumVariationSettings =
+        FontVariation.Settings(
+            FontVariation.Setting("wght", TypeScaleTokens.TitleMediumWeight),
+            FontVariation.Setting("wdth", TypeScaleTokens.TitleMediumWidth),
+        )
+    val TitleSmallVariationSettings =
+        FontVariation.Settings(
+            FontVariation.Setting("wdth", TypeScaleTokens.TitleSmallWidth),
+            FontVariation.Setting("wght", TypeScaleTokens.TitleSmallWeight),
+        )
+}
diff --git a/wear/compose/integration-tests/demos/build.gradle b/wear/compose/integration-tests/demos/build.gradle
index 275bbeba..5a629cc 100644
--- a/wear/compose/integration-tests/demos/build.gradle
+++ b/wear/compose/integration-tests/demos/build.gradle
@@ -25,8 +25,8 @@
     defaultConfig {
         applicationId "androidx.wear.compose.integration.demos"
         minSdk 25
-        versionCode 28
-        versionName "1.28"
+        versionCode 31
+        versionName "1.31"
     }
 
     buildTypes {
@@ -61,6 +61,7 @@
     implementation(project(":wear:compose:compose-foundation-samples"))
     implementation(project(':wear:compose:compose-material'))
     implementation(project(":wear:compose:compose-material-samples"))
+    implementation(project(':wear:compose:compose-material3'))
     implementation(project(':wear:compose:integration-tests:demos:common'))
     implementation(project(":wear:compose:compose-material3-integration-tests"))
 
diff --git a/wear/compose/integration-tests/demos/common/src/main/java/androidx/wear/compose/integration/demos/common/SizedContainer.kt b/wear/compose/integration-tests/demos/common/src/main/java/androidx/wear/compose/integration/demos/common/SizedContainer.kt
new file mode 100644
index 0000000..f9c6f7e
--- /dev/null
+++ b/wear/compose/integration-tests/demos/common/src/main/java/androidx/wear/compose/integration/demos/common/SizedContainer.kt
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.integration.demos.common
+
+import android.content.res.Configuration
+import androidx.compose.foundation.background
+import androidx.compose.foundation.border
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.wrapContentSize
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.derivedStateOf
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.RectangleShape
+import androidx.compose.ui.platform.LocalConfiguration
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.dp
+import kotlin.math.roundToInt
+
+/*
+ * Component that show its content as it is on a watch and wraps it in a SizedContainer on
+ * bigger screens
+ */
+@Composable
+fun AdaptiveScreen(
+    screenSizeDp: Int = 220,
+    zoomLevel: Float = 1.5f,
+    content: @Composable BoxScope.() -> Unit
+) {
+    if (LocalConfiguration.current.screenWidthDp < 300) {
+        Box(Modifier.fillMaxSize(), content = content)
+    } else {
+        SizedContainer(
+            screenSize = screenSizeDp,
+            zoomLevel = zoomLevel,
+            roundScreen = true,
+            modifier = Modifier.fillMaxSize().padding(10.dp).wrapContentSize(Alignment.TopCenter),
+            content = content
+        )
+    }
+}
+
+/*
+ * Component to show a watch UI on bigger screens (Phone/tablet).
+ *
+ * Composes the `content` inside a circle/square of the given size, also changing the configuration
+ * in `LocalConfiguration.current` to make the inner composable believe the screen is that size &
+ * shape.
+ * Works with almost all Composables, the only know exception is Dialog, that is designed to be
+ * full-screen.
+ * Also applies a zoom effect.
+ */
+@Composable
+fun SizedContainer(
+    screenSize: Int,
+    roundScreen: Boolean,
+    modifier: Modifier = Modifier,
+    zoomLevel: Float = 1.5f,
+    content: @Composable BoxScope.() -> Unit,
+) {
+    val currentConfig = LocalConfiguration.current
+    val config by
+        remember(screenSize, roundScreen) {
+            derivedStateOf {
+                Configuration().apply {
+                    setTo(currentConfig)
+                    screenWidthDp = screenSize
+                    screenHeightDp = screenSize
+                    densityDpi = (320 * zoomLevel).roundToInt()
+                    // Set the screen to round.
+                    screenLayout =
+                        (screenLayout and Configuration.SCREENLAYOUT_ROUND_MASK.inv()) or
+                            if (roundScreen) {
+                                Configuration.SCREENLAYOUT_ROUND_YES
+                            } else {
+                                Configuration.SCREENLAYOUT_ROUND_NO
+                            }
+                }
+            }
+        }
+    val currentDensity = LocalDensity.current
+    val density =
+        object : Density {
+            override val density: Float
+                get() = currentDensity.density * zoomLevel
+
+            override val fontScale: Float
+                get() = currentDensity.fontScale
+        }
+
+    CompositionLocalProvider(LocalConfiguration provides config, LocalDensity provides density) {
+        val shape = if (roundScreen) CircleShape else RectangleShape
+
+        Box(
+            modifier =
+                modifier
+                    .border(2.dp, Color.DarkGray, shape)
+                    .padding(2.dp)
+                    .clip(shape)
+                    .size(screenSize.dp)
+                    .background(Color.Black),
+            contentAlignment = Alignment.Center,
+            content = content,
+        )
+    }
+}
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/CurvedLayoutDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/CurvedLayoutDemo.kt
index c99a96f..21c3c97 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/CurvedLayoutDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/CurvedLayoutDemo.kt
@@ -46,6 +46,7 @@
 import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.em
 import androidx.compose.ui.unit.sp
 import androidx.wear.compose.foundation.AnchorType
 import androidx.wear.compose.foundation.CurvedAlignment
@@ -55,6 +56,7 @@
 import androidx.wear.compose.foundation.CurvedScope
 import androidx.wear.compose.foundation.CurvedTextStyle
 import androidx.wear.compose.foundation.angularSize
+import androidx.wear.compose.foundation.angularSizeDp
 import androidx.wear.compose.foundation.background
 import androidx.wear.compose.foundation.basicCurvedText
 import androidx.wear.compose.foundation.curvedBox
@@ -64,6 +66,7 @@
 import androidx.wear.compose.foundation.padding
 import androidx.wear.compose.foundation.sizeIn
 import androidx.wear.compose.foundation.weight
+import androidx.wear.compose.material.MaterialTheme
 import androidx.wear.compose.material.Text
 import androidx.wear.compose.material.ToggleButton
 import androidx.wear.compose.material.curvedText
@@ -358,3 +361,55 @@
 private fun WhiteCircle() {
     Box(modifier = Modifier.size(30.dp).clip(CircleShape).background(Color.White))
 }
+
+@Composable
+fun CurvedSpacingEmDemo() {
+    val style = CurvedTextStyle(MaterialTheme.typography.body1)
+    repeat(2) {
+        CurvedLayout(
+            anchor = if (it == 0) 270f else 90f,
+            angularDirection =
+                if (it == 0) CurvedDirection.Angular.Clockwise
+                else CurvedDirection.Angular.CounterClockwise,
+            modifier = Modifier.size(300.dp),
+        ) {
+            listOf(-0.1f, 0f, 0.05f, 0.1f, 0.15f).forEachIndexed { ix, spacing ->
+                if (ix > 0) {
+                    curvedBox(modifier = CurvedModifier.angularSizeDp(10.dp)) {}
+                }
+                basicCurvedText(
+                    "| $spacing em |",
+                    style = style.copy(letterSpacing = spacing.em),
+                    modifier =
+                        CurvedModifier.background(if (ix % 2 == 0) Color.DarkGray else Color.Gray)
+                )
+            }
+        }
+    }
+}
+
+@Composable
+fun CurvedSpacingSpDemo() {
+    val style = CurvedTextStyle(MaterialTheme.typography.body1)
+    repeat(2) {
+        CurvedLayout(
+            anchor = if (it == 0) 270f else 90f,
+            angularDirection =
+                if (it == 0) CurvedDirection.Angular.Clockwise
+                else CurvedDirection.Angular.CounterClockwise,
+            modifier = Modifier.size(300.dp),
+        ) {
+            listOf(-1f, 0f, 1f, 2f).forEachIndexed { ix, spacing ->
+                if (ix > 0) {
+                    curvedBox(modifier = CurvedModifier.angularSizeDp(10.dp)) {}
+                }
+                basicCurvedText(
+                    "| $spacing sp |",
+                    style = style.copy(letterSpacing = spacing.sp),
+                    modifier =
+                        CurvedModifier.background(if (ix % 2 == 0) Color.DarkGray else Color.Gray)
+                )
+            }
+        }
+    }
+}
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoApp.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoApp.kt
index d05ed51..650517cd 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoApp.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoApp.kt
@@ -21,6 +21,7 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.remember
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
@@ -53,8 +54,10 @@
     onNavigateTo: (Demo) -> Unit,
     onNavigateBack: () -> Unit,
 ) {
-    val swipeToDismissState = swipeDismissStateWithNavigation(onNavigateBack)
-    DisplayDemo(swipeToDismissState, currentDemo, parentDemo, onNavigateTo, onNavigateBack)
+    androidx.wear.compose.material3.AppScaffold(timeText = {}) {
+        val swipeToDismissState = swipeDismissStateWithNavigation(onNavigateBack)
+        DisplayDemo(swipeToDismissState, currentDemo, parentDemo, onNavigateTo, onNavigateBack)
+    }
 }
 
 @Composable
@@ -99,45 +102,65 @@
 @Composable
 internal fun BoxScope.DisplayDemoList(category: DemoCategory, onNavigateTo: (Demo) -> Unit) {
     val state = category.getScrollStateOrInit { rememberScalingLazyListState() }
-
-    ScalingLazyColumn(
-        horizontalAlignment = Alignment.CenterHorizontally,
-        modifier = Modifier.fillMaxWidth().testTag(DemoListTag),
-        state = state,
-        autoCentering = AutoCenteringParams(itemIndex = if (category.demos.size >= 2) 2 else 1),
-    ) {
-        item {
-            ListHeader {
-                Text(
-                    text = category.title,
-                    style = MaterialTheme.typography.caption1,
-                    color = Color.White,
-                    textAlign = TextAlign.Center,
-                    modifier = Modifier.fillMaxWidth()
-                )
+    val scaffoldWrapper =
+        @Composable { it: @Composable () -> Unit ->
+            // Only material3 demos benefit from the Material3 ScreenScaffold
+            if (category.materialVersion == 3) {
+                val timeText = @Composable { androidx.wear.compose.material3.TimeText { time() } }
+                androidx.wear.compose.material3.ScreenScaffold(
+                    scrollState = state,
+                    timeText = remember { timeText },
+                ) {
+                    it()
+                }
+            } else {
+                it()
             }
         }
-        category.demos.forEach { demo ->
+    scaffoldWrapper {
+        ScalingLazyColumn(
+            horizontalAlignment = Alignment.CenterHorizontally,
+            modifier = Modifier.fillMaxWidth().testTag(DemoListTag),
+            state = state,
+            autoCentering = AutoCenteringParams(itemIndex = if (category.demos.size >= 2) 2 else 1),
+        ) {
             item {
-                Chip(
-                    onClick = { onNavigateTo(demo) },
-                    colors = ChipDefaults.secondaryChipColors(),
-                    label = {
-                        Text(text = demo.title, modifier = Modifier.fillMaxWidth(), maxLines = 2)
-                    },
-                    modifier = Modifier.fillMaxWidth()
-                )
+                ListHeader {
+                    Text(
+                        text = category.title,
+                        style = MaterialTheme.typography.caption1,
+                        color = Color.White,
+                        textAlign = TextAlign.Center,
+                        modifier = Modifier.fillMaxWidth()
+                    )
+                }
             }
-            demo.description?.let { description ->
+            category.demos.forEach { demo ->
                 item {
-                    CompositionLocalProvider(
-                        LocalTextStyle provides MaterialTheme.typography.caption3
-                    ) {
-                        Text(
-                            text = description,
-                            modifier = Modifier.fillMaxWidth().align(Alignment.Center),
-                            textAlign = TextAlign.Center
-                        )
+                    Chip(
+                        onClick = { onNavigateTo(demo) },
+                        colors = ChipDefaults.secondaryChipColors(),
+                        label = {
+                            Text(
+                                text = demo.title,
+                                modifier = Modifier.fillMaxWidth(),
+                                maxLines = 2
+                            )
+                        },
+                        modifier = Modifier.fillMaxWidth()
+                    )
+                }
+                demo.description?.let { description ->
+                    item {
+                        CompositionLocalProvider(
+                            LocalTextStyle provides MaterialTheme.typography.caption3
+                        ) {
+                            Text(
+                                text = description,
+                                modifier = Modifier.fillMaxWidth().align(Alignment.Center),
+                                textAlign = TextAlign.Center
+                            )
+                        }
                     }
                 }
             }
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/FoundationDemos.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/FoundationDemos.kt
index fb61464..686d208 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/FoundationDemos.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/FoundationDemos.kt
@@ -117,6 +117,8 @@
                     ComposableDemo("Font Weight") { CurvedFontWeight() },
                     ComposableDemo("Fonts") { CurvedFonts() },
                     ComposableDemo("Curved Icons") { CurvedIconsDemo() },
+                    ComposableDemo("Letter Spacing (em)") { CurvedSpacingEmDemo() },
+                    ComposableDemo("Letter Spacing (sp)") { CurvedSpacingSpDemo() },
                 )
             ),
             ComposableDemo("Scrollable Column") { ScrollableColumnDemo() },
diff --git a/wear/compose/integration-tests/macrobenchmark-target/build.gradle b/wear/compose/integration-tests/macrobenchmark-target/build.gradle
index b6d82c7..96f05c4 100644
--- a/wear/compose/integration-tests/macrobenchmark-target/build.gradle
+++ b/wear/compose/integration-tests/macrobenchmark-target/build.gradle
@@ -46,6 +46,7 @@
     implementation(project(":profileinstaller:profileinstaller"))
     implementation project(path: ':wear:compose:compose-foundation')
     implementation project(path: ':wear:compose:compose-material')
+    implementation project(path: ':wear:compose:compose-material3')
     implementation project(path: ':wear:compose:compose-navigation')
     implementation(project(path:':compose:runtime:runtime-tracing'))
     implementation(project(path:':tracing:tracing-perfetto'))
diff --git a/wear/compose/integration-tests/macrobenchmark-target/src/main/AndroidManifest.xml b/wear/compose/integration-tests/macrobenchmark-target/src/main/AndroidManifest.xml
index 39a5325..26090ac6 100644
--- a/wear/compose/integration-tests/macrobenchmark-target/src/main/AndroidManifest.xml
+++ b/wear/compose/integration-tests/macrobenchmark-target/src/main/AndroidManifest.xml
@@ -104,6 +104,15 @@
             </intent-filter>
         </activity>
 
+        <activity
+            android:name=".AnimatedTextActivity"
+            android:exported="true"
+            android:theme="@style/AppTheme">
+            <intent-filter>
+                <action android:name="androidx.wear.compose.integration.macrobenchmark.target.ANIMATED_TEXT_ACTIVITY" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
     </application>
 
     <uses-permission android:name="android.permission.WAKE_LOCK" />
diff --git a/wear/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/compose/integration/macrobenchmark/target/AnimatedTextActivity.kt b/wear/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/compose/integration/macrobenchmark/target/AnimatedTextActivity.kt
new file mode 100644
index 0000000..062c26c
--- /dev/null
+++ b/wear/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/compose/integration/macrobenchmark/target/AnimatedTextActivity.kt
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.integration.macrobenchmark.target
+
+import android.os.Build
+import android.os.Bundle
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
+import androidx.annotation.RequiresApi
+import androidx.compose.animation.core.Animatable
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.semantics.contentDescription
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.font.Font
+import androidx.compose.ui.text.font.FontVariation
+import androidx.compose.ui.text.font.toFontFamily
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.sp
+import androidx.wear.compose.material.Text
+import androidx.wear.compose.material3.AnimatedText
+import androidx.wear.compose.material3.rememberAnimatedTextFontRegistry
+import kotlinx.coroutines.launch
+
+class AnimatedTextActivity : ComponentActivity() {
+
+    @RequiresApi(Build.VERSION_CODES.S)
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+
+        setContent { AnimatedTextScreen() }
+    }
+}
+
+@RequiresApi(Build.VERSION_CODES.S)
+@Composable
+private fun AnimatedTextScreen() {
+    val scope = rememberCoroutineScope()
+    val animatable = remember { Animatable(0.5f) }
+    val textStyle = remember {
+        TextStyle.Default.copy(
+            fontFamily = Font(R.font.robotoflex_variable).toFontFamily(),
+            fontSize = 50.sp
+        )
+    }
+    val fontRegistry =
+        rememberAnimatedTextFontRegistry(
+            startFontVariationSettings =
+                FontVariation.Settings(FontVariation.width(10f), FontVariation.weight(100)),
+            endFontVariationSettings =
+                FontVariation.Settings(FontVariation.width(100f), FontVariation.weight(900)),
+            textStyle = textStyle
+        )
+
+    Row(
+        modifier = Modifier.fillMaxSize(),
+        horizontalArrangement = Arrangement.Center,
+        verticalAlignment = Alignment.CenterVertically
+    ) {
+        var textValue by remember { mutableIntStateOf(150) }
+        Box(
+            modifier =
+                Modifier.weight(1f)
+                    .semantics { contentDescription = "minusContentDescription" }
+                    .clickable {
+                        textValue -= 1
+                        scope.launch {
+                            animatable.animateTo(0f)
+                            animatable.animateTo(0.5f)
+                        }
+                    },
+            contentAlignment = Alignment.Center
+        ) {
+            Text("-", fontSize = 30.sp, textAlign = TextAlign.Center)
+        }
+        Box(modifier = Modifier.weight(2f), contentAlignment = Alignment.Center) {
+            AnimatedText(
+                text = textValue.toString(),
+                fontRegistry = fontRegistry,
+                progressFraction = { animatable.value }
+            )
+        }
+        Box(
+            modifier =
+                Modifier.weight(1f)
+                    .semantics { contentDescription = "plusContentDescription" }
+                    .clickable {
+                        textValue += 1
+                        scope.launch {
+                            animatable.animateTo(1f)
+                            animatable.animateTo(0.5f)
+                        }
+                    },
+            contentAlignment = Alignment.Center
+        ) {
+            Text("+", fontSize = 30.sp)
+        }
+    }
+}
diff --git a/wear/compose/integration-tests/macrobenchmark-target/src/main/res/font/robotoflex_variable.ttf b/wear/compose/integration-tests/macrobenchmark-target/src/main/res/font/robotoflex_variable.ttf
new file mode 100644
index 0000000..c39aafb
--- /dev/null
+++ b/wear/compose/integration-tests/macrobenchmark-target/src/main/res/font/robotoflex_variable.ttf
Binary files differ
diff --git a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/AnimatedTextBenchmark.kt b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/AnimatedTextBenchmark.kt
new file mode 100644
index 0000000..fd00cbd
--- /dev/null
+++ b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/AnimatedTextBenchmark.kt
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.integration.macrobenchmark
+
+import android.content.Intent
+import androidx.benchmark.macro.CompilationMode
+import androidx.benchmark.macro.ExperimentalMetricApi
+import androidx.benchmark.macro.FrameTimingGfxInfoMetric
+import androidx.benchmark.macro.MemoryUsageMetric
+import androidx.benchmark.macro.junit4.MacrobenchmarkRule
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import androidx.test.uiautomator.By
+import androidx.wear.compose.integration.macrobenchmark.test.disableChargingExperience
+import androidx.wear.compose.integration.macrobenchmark.test.enableChargingExperience
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.runBlocking
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@LargeTest
+@RunWith(AndroidJUnit4::class)
+class AnimatedTextBenchmark {
+
+    @get:Rule val benchmarkRule = MacrobenchmarkRule()
+
+    @Before
+    fun setUp() {
+        disableChargingExperience()
+    }
+
+    @After
+    fun destroy() {
+        enableChargingExperience()
+    }
+
+    @OptIn(ExperimentalMetricApi::class)
+    @Test
+    fun testAnimatedText() {
+        benchmarkRule.measureRepeated(
+            packageName = PACKAGE_NAME,
+            metrics =
+                listOf(
+                    FrameTimingGfxInfoMetric(),
+                    MemoryUsageMetric(MemoryUsageMetric.Mode.Last),
+                ),
+            compilationMode = CompilationMode.Full(),
+            iterations = 10,
+            setupBlock = {
+                val intent = Intent()
+                intent.action = ANIMATED_TEXT_ACTION
+                startActivityAndWait(intent)
+            }
+        ) {
+            runBlocking {
+                val plusButton = device.findObject(By.desc("plusContentDescription"))
+                val minusButton = device.findObject(By.desc("minusContentDescription"))
+                repeat(3) {
+                    plusButton.click()
+                    delay(250L)
+                }
+                repeat(3) {
+                    minusButton.click()
+                    delay(250L)
+                }
+            }
+        }
+    }
+
+    companion object {
+        private const val PACKAGE_NAME = "androidx.wear.compose.integration.macrobenchmark.target"
+        private const val ANIMATED_TEXT_ACTION = "$PACKAGE_NAME.ANIMATED_TEXT_ACTIVITY"
+    }
+}
diff --git a/wear/compose/integration-tests/navigation/build.gradle b/wear/compose/integration-tests/navigation/build.gradle
index 64f02c2..ca96d2b 100644
--- a/wear/compose/integration-tests/navigation/build.gradle
+++ b/wear/compose/integration-tests/navigation/build.gradle
@@ -54,6 +54,6 @@
     implementation(project(':wear:compose:compose-navigation'))
 
     // Align dependencies in debugRuntimeClasspath and debugAndroidTestRuntimeClasspath.
-    androidTestImplementation("androidx.lifecycle:lifecycle-common:2.8.2")
-    androidTestImplementation("androidx.annotation:annotation:1.8.0")
+    androidTestImplementation("androidx.lifecycle:lifecycle-common:2.8.3")
+    androidTestImplementation(project(":annotation:annotation"))
 }
diff --git a/wear/protolayout/protolayout-expression-pipeline/api/1.2.0-beta01.txt b/wear/protolayout/protolayout-expression-pipeline/api/1.2.0-beta01.txt
new file mode 100644
index 0000000..28d52cc
--- /dev/null
+++ b/wear/protolayout/protolayout-expression-pipeline/api/1.2.0-beta01.txt
@@ -0,0 +1,80 @@
+// Signature format: 4.0
+package androidx.wear.protolayout.expression.pipeline {
+
+  public interface BoundDynamicType extends java.lang.AutoCloseable {
+    method @UiThread public void close();
+    method @UiThread public void startEvaluation();
+  }
+
+  public abstract class DynamicTypeBindingRequest {
+    method public static androidx.wear.protolayout.expression.pipeline.DynamicTypeBindingRequest forDynamicBool(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool, java.util.concurrent.Executor, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.lang.Boolean!>);
+    method public static androidx.wear.protolayout.expression.pipeline.DynamicTypeBindingRequest forDynamicColor(androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor, java.util.concurrent.Executor, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.lang.Integer!>);
+    method public static androidx.wear.protolayout.expression.pipeline.DynamicTypeBindingRequest forDynamicDuration(androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration, java.util.concurrent.Executor, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.time.Duration!>);
+    method public static androidx.wear.protolayout.expression.pipeline.DynamicTypeBindingRequest forDynamicFloat(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat, java.util.concurrent.Executor, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.lang.Float!>);
+    method public static androidx.wear.protolayout.expression.pipeline.DynamicTypeBindingRequest forDynamicInstant(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant, java.util.concurrent.Executor, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.time.Instant!>);
+    method public static androidx.wear.protolayout.expression.pipeline.DynamicTypeBindingRequest forDynamicInt32(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32, java.util.concurrent.Executor, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.lang.Integer!>);
+    method public static androidx.wear.protolayout.expression.pipeline.DynamicTypeBindingRequest forDynamicString(androidx.wear.protolayout.expression.DynamicBuilders.DynamicString, android.icu.util.ULocale, java.util.concurrent.Executor, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.lang.String!>);
+  }
+
+  public class DynamicTypeEvaluator {
+    ctor public DynamicTypeEvaluator(androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config);
+    method public androidx.wear.protolayout.expression.pipeline.BoundDynamicType bind(androidx.wear.protolayout.expression.pipeline.DynamicTypeBindingRequest) throws androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.EvaluationException;
+  }
+
+  public static final class DynamicTypeEvaluator.Config {
+    method public androidx.wear.protolayout.expression.pipeline.QuotaManager? getAnimationQuotaManager();
+    method @VisibleForTesting public java.util.function.Supplier<java.time.Instant!>? getClock();
+    method public androidx.wear.protolayout.expression.pipeline.QuotaManager? getDynamicTypesQuotaManager();
+    method public java.util.Map<androidx.wear.protolayout.expression.PlatformDataKey<? extends java.lang.Object!>!,androidx.wear.protolayout.expression.pipeline.PlatformDataProvider!> getPlatformDataProviders();
+    method public androidx.wear.protolayout.expression.pipeline.PlatformTimeUpdateNotifier? getPlatformTimeUpdateNotifier();
+    method public androidx.wear.protolayout.expression.pipeline.StateStore? getStateStore();
+  }
+
+  public static final class DynamicTypeEvaluator.Config.Builder {
+    ctor public DynamicTypeEvaluator.Config.Builder();
+    method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder addPlatformDataProvider(androidx.wear.protolayout.expression.pipeline.PlatformDataProvider, java.util.Set<androidx.wear.protolayout.expression.PlatformDataKey<? extends java.lang.Object!>!>);
+    method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config build();
+    method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder setAnimationQuotaManager(androidx.wear.protolayout.expression.pipeline.QuotaManager);
+    method @VisibleForTesting public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder setClock(java.util.function.Supplier<java.time.Instant!>);
+    method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder setDynamicTypesQuotaManager(androidx.wear.protolayout.expression.pipeline.QuotaManager);
+    method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder setPlatformTimeUpdateNotifier(androidx.wear.protolayout.expression.pipeline.PlatformTimeUpdateNotifier);
+    method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder setStateStore(androidx.wear.protolayout.expression.pipeline.StateStore);
+  }
+
+  public static class DynamicTypeEvaluator.EvaluationException extends java.lang.Exception {
+    ctor public DynamicTypeEvaluator.EvaluationException(String);
+  }
+
+  public interface DynamicTypeValueReceiver<T> {
+    method public void onData(T);
+    method public void onInvalidated();
+  }
+
+  public interface PlatformDataProvider {
+    method public void clearReceiver();
+    method public void setReceiver(java.util.concurrent.Executor, androidx.wear.protolayout.expression.pipeline.PlatformDataReceiver);
+  }
+
+  public interface PlatformDataReceiver {
+    method public void onData(androidx.wear.protolayout.expression.PlatformDataValues);
+    method public void onInvalidated(java.util.Set<androidx.wear.protolayout.expression.PlatformDataKey<? extends java.lang.Object!>!>);
+  }
+
+  public interface PlatformTimeUpdateNotifier {
+    method public void clearReceiver();
+    method public void setReceiver(java.util.concurrent.Executor, Runnable);
+  }
+
+  public interface QuotaManager {
+    method public void releaseQuota(int);
+    method public boolean tryAcquireQuota(int);
+  }
+
+  public final class StateStore {
+    method public static androidx.wear.protolayout.expression.pipeline.StateStore create(java.util.Map<androidx.wear.protolayout.expression.AppDataKey<? extends java.lang.Object!>!,androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<? extends java.lang.Object!>!>);
+    method public static int getMaxStateEntryCount();
+    method @UiThread public void setAppStateEntryValues(java.util.Map<androidx.wear.protolayout.expression.AppDataKey<? extends java.lang.Object!>!,androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<? extends java.lang.Object!>!>);
+  }
+
+}
+
diff --git a/wear/protolayout/protolayout-expression-pipeline/api/current.ignore b/wear/protolayout/protolayout-expression-pipeline/api/current.ignore
new file mode 100644
index 0000000..445e09a
--- /dev/null
+++ b/wear/protolayout/protolayout-expression-pipeline/api/current.ignore
@@ -0,0 +1,11 @@
+// Baseline format: 1.0
+InvalidNullConversion: androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config#getPlatformDataProviders():
+    Attempted to remove nullability from java.lang.Object (was NONNULL) in method androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.getPlatformDataProviders()
+InvalidNullConversion: androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder#addPlatformDataProvider(androidx.wear.protolayout.expression.pipeline.PlatformDataProvider, java.util.Set<androidx.wear.protolayout.expression.PlatformDataKey<?>>) parameter #1:
+    Attempted to remove nullability from java.lang.Object (was NONNULL) in parameter arg2 in androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder.addPlatformDataProvider(androidx.wear.protolayout.expression.pipeline.PlatformDataProvider arg1, java.util.Set<androidx.wear.protolayout.expression.PlatformDataKey<?>> arg2)
+InvalidNullConversion: androidx.wear.protolayout.expression.pipeline.PlatformDataReceiver#onInvalidated(java.util.Set<androidx.wear.protolayout.expression.PlatformDataKey<?>>) parameter #0:
+    Attempted to remove nullability from java.lang.Object (was NONNULL) in parameter arg1 in androidx.wear.protolayout.expression.pipeline.PlatformDataReceiver.onInvalidated(java.util.Set<androidx.wear.protolayout.expression.PlatformDataKey<?>> arg1)
+InvalidNullConversion: androidx.wear.protolayout.expression.pipeline.StateStore#create(java.util.Map<androidx.wear.protolayout.expression.AppDataKey<?>,androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<?>>) parameter #0:
+    Attempted to remove nullability from java.lang.Object (was NONNULL) in parameter arg1 in androidx.wear.protolayout.expression.pipeline.StateStore.create(java.util.Map<androidx.wear.protolayout.expression.AppDataKey<?>,androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<?>> arg1)
+InvalidNullConversion: androidx.wear.protolayout.expression.pipeline.StateStore#setAppStateEntryValues(java.util.Map<androidx.wear.protolayout.expression.AppDataKey<?>,androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<?>>) parameter #0:
+    Attempted to remove nullability from java.lang.Object (was NONNULL) in parameter arg1 in androidx.wear.protolayout.expression.pipeline.StateStore.setAppStateEntryValues(java.util.Map<androidx.wear.protolayout.expression.AppDataKey<?>,androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<?>> arg1)
diff --git a/wear/protolayout/protolayout-expression-pipeline/api/res-1.2.0-beta01.txt b/wear/protolayout/protolayout-expression-pipeline/api/res-1.2.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wear/protolayout/protolayout-expression-pipeline/api/res-1.2.0-beta01.txt
diff --git a/wear/protolayout/protolayout-expression-pipeline/api/restricted_1.2.0-beta01.txt b/wear/protolayout/protolayout-expression-pipeline/api/restricted_1.2.0-beta01.txt
new file mode 100644
index 0000000..c879bf4
--- /dev/null
+++ b/wear/protolayout/protolayout-expression-pipeline/api/restricted_1.2.0-beta01.txt
@@ -0,0 +1,82 @@
+// Signature format: 4.0
+package androidx.wear.protolayout.expression.pipeline {
+
+  public interface BoundDynamicType extends java.lang.AutoCloseable {
+    method @UiThread public void close();
+    method @UiThread public void startEvaluation();
+  }
+
+  public abstract class DynamicTypeBindingRequest {
+    method public static androidx.wear.protolayout.expression.pipeline.DynamicTypeBindingRequest forDynamicBool(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool, java.util.concurrent.Executor, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.lang.Boolean!>);
+    method public static androidx.wear.protolayout.expression.pipeline.DynamicTypeBindingRequest forDynamicColor(androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor, java.util.concurrent.Executor, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.lang.Integer!>);
+    method public static androidx.wear.protolayout.expression.pipeline.DynamicTypeBindingRequest forDynamicDuration(androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration, java.util.concurrent.Executor, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.time.Duration!>);
+    method public static androidx.wear.protolayout.expression.pipeline.DynamicTypeBindingRequest forDynamicFloat(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat, java.util.concurrent.Executor, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.lang.Float!>);
+    method public static androidx.wear.protolayout.expression.pipeline.DynamicTypeBindingRequest forDynamicInstant(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant, java.util.concurrent.Executor, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.time.Instant!>);
+    method public static androidx.wear.protolayout.expression.pipeline.DynamicTypeBindingRequest forDynamicInt32(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32, java.util.concurrent.Executor, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.lang.Integer!>);
+    method public static androidx.wear.protolayout.expression.pipeline.DynamicTypeBindingRequest forDynamicString(androidx.wear.protolayout.expression.DynamicBuilders.DynamicString, android.icu.util.ULocale, java.util.concurrent.Executor, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.lang.String!>);
+  }
+
+  public class DynamicTypeEvaluator {
+    ctor public DynamicTypeEvaluator(androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config);
+    method public androidx.wear.protolayout.expression.pipeline.BoundDynamicType bind(androidx.wear.protolayout.expression.pipeline.DynamicTypeBindingRequest) throws androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.EvaluationException;
+  }
+
+  public static final class DynamicTypeEvaluator.Config {
+    method public androidx.wear.protolayout.expression.pipeline.QuotaManager? getAnimationQuotaManager();
+    method @VisibleForTesting public java.util.function.Supplier<java.time.Instant!>? getClock();
+    method public androidx.wear.protolayout.expression.pipeline.QuotaManager? getDynamicTypesQuotaManager();
+    method public java.util.Map<androidx.wear.protolayout.expression.PlatformDataKey<? extends java.lang.Object!>!,androidx.wear.protolayout.expression.pipeline.PlatformDataProvider!> getPlatformDataProviders();
+    method public androidx.wear.protolayout.expression.pipeline.PlatformTimeUpdateNotifier? getPlatformTimeUpdateNotifier();
+    method public androidx.wear.protolayout.expression.pipeline.StateStore? getStateStore();
+  }
+
+  public static final class DynamicTypeEvaluator.Config.Builder {
+    ctor public DynamicTypeEvaluator.Config.Builder();
+    method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder addPlatformDataProvider(androidx.wear.protolayout.expression.pipeline.PlatformDataProvider, java.util.Set<androidx.wear.protolayout.expression.PlatformDataKey<? extends java.lang.Object!>!>);
+    method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config build();
+    method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder setAnimationQuotaManager(androidx.wear.protolayout.expression.pipeline.QuotaManager);
+    method @VisibleForTesting public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder setClock(java.util.function.Supplier<java.time.Instant!>);
+    method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder setDynamicTypesQuotaManager(androidx.wear.protolayout.expression.pipeline.QuotaManager);
+    method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder setPlatformTimeUpdateNotifier(androidx.wear.protolayout.expression.pipeline.PlatformTimeUpdateNotifier);
+    method public androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder setStateStore(androidx.wear.protolayout.expression.pipeline.StateStore);
+  }
+
+  public static class DynamicTypeEvaluator.EvaluationException extends java.lang.Exception {
+    ctor public DynamicTypeEvaluator.EvaluationException(String);
+  }
+
+  public interface DynamicTypeValueReceiver<T> {
+    method public void onData(T);
+    method public void onInvalidated();
+  }
+
+  public interface PlatformDataProvider {
+    method public void clearReceiver();
+    method public void setReceiver(java.util.concurrent.Executor, androidx.wear.protolayout.expression.pipeline.PlatformDataReceiver);
+  }
+
+  public interface PlatformDataReceiver {
+    method public void onData(androidx.wear.protolayout.expression.PlatformDataValues);
+    method public void onInvalidated(java.util.Set<androidx.wear.protolayout.expression.PlatformDataKey<? extends java.lang.Object!>!>);
+  }
+
+  public interface PlatformTimeUpdateNotifier {
+    method public void clearReceiver();
+    method public void setReceiver(java.util.concurrent.Executor, Runnable);
+  }
+
+  public interface QuotaManager {
+    method public void releaseQuota(int);
+    method public boolean tryAcquireQuota(int);
+  }
+
+  public final class StateStore {
+    ctor @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public StateStore(java.util.Map<androidx.wear.protolayout.expression.AppDataKey<? extends java.lang.Object!>!,androidx.wear.protolayout.expression.proto.DynamicDataProto.DynamicDataValue!>);
+    method public static androidx.wear.protolayout.expression.pipeline.StateStore create(java.util.Map<androidx.wear.protolayout.expression.AppDataKey<? extends java.lang.Object!>!,androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<? extends java.lang.Object!>!>);
+    method public static int getMaxStateEntryCount();
+    method @UiThread public void setAppStateEntryValues(java.util.Map<androidx.wear.protolayout.expression.AppDataKey<? extends java.lang.Object!>!,androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<? extends java.lang.Object!>!>);
+    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @UiThread public void setAppStateEntryValuesProto(java.util.Map<androidx.wear.protolayout.expression.AppDataKey<? extends java.lang.Object!>!,androidx.wear.protolayout.expression.proto.DynamicDataProto.DynamicDataValue!>);
+  }
+
+}
+
diff --git a/wear/protolayout/protolayout-expression-pipeline/api/restricted_current.ignore b/wear/protolayout/protolayout-expression-pipeline/api/restricted_current.ignore
new file mode 100644
index 0000000..2813036
--- /dev/null
+++ b/wear/protolayout/protolayout-expression-pipeline/api/restricted_current.ignore
@@ -0,0 +1,15 @@
+// Baseline format: 1.0
+InvalidNullConversion: androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config#getPlatformDataProviders():
+    Attempted to remove nullability from java.lang.Object (was NONNULL) in method androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.getPlatformDataProviders()
+InvalidNullConversion: androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder#addPlatformDataProvider(androidx.wear.protolayout.expression.pipeline.PlatformDataProvider, java.util.Set<androidx.wear.protolayout.expression.PlatformDataKey<?>>) parameter #1:
+    Attempted to remove nullability from java.lang.Object (was NONNULL) in parameter arg2 in androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator.Config.Builder.addPlatformDataProvider(androidx.wear.protolayout.expression.pipeline.PlatformDataProvider arg1, java.util.Set<androidx.wear.protolayout.expression.PlatformDataKey<?>> arg2)
+InvalidNullConversion: androidx.wear.protolayout.expression.pipeline.PlatformDataReceiver#onInvalidated(java.util.Set<androidx.wear.protolayout.expression.PlatformDataKey<?>>) parameter #0:
+    Attempted to remove nullability from java.lang.Object (was NONNULL) in parameter arg1 in androidx.wear.protolayout.expression.pipeline.PlatformDataReceiver.onInvalidated(java.util.Set<androidx.wear.protolayout.expression.PlatformDataKey<?>> arg1)
+InvalidNullConversion: androidx.wear.protolayout.expression.pipeline.StateStore#StateStore(java.util.Map<androidx.wear.protolayout.expression.AppDataKey<?>,androidx.wear.protolayout.expression.proto.DynamicDataProto.DynamicDataValue>) parameter #0:
+    Attempted to remove nullability from java.lang.Object (was NONNULL) in parameter arg1 in androidx.wear.protolayout.expression.pipeline.StateStore(java.util.Map<androidx.wear.protolayout.expression.AppDataKey<?>,androidx.wear.protolayout.expression.proto.DynamicDataProto.DynamicDataValue> arg1)
+InvalidNullConversion: androidx.wear.protolayout.expression.pipeline.StateStore#create(java.util.Map<androidx.wear.protolayout.expression.AppDataKey<?>,androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<?>>) parameter #0:
+    Attempted to remove nullability from java.lang.Object (was NONNULL) in parameter arg1 in androidx.wear.protolayout.expression.pipeline.StateStore.create(java.util.Map<androidx.wear.protolayout.expression.AppDataKey<?>,androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<?>> arg1)
+InvalidNullConversion: androidx.wear.protolayout.expression.pipeline.StateStore#setAppStateEntryValues(java.util.Map<androidx.wear.protolayout.expression.AppDataKey<?>,androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<?>>) parameter #0:
+    Attempted to remove nullability from java.lang.Object (was NONNULL) in parameter arg1 in androidx.wear.protolayout.expression.pipeline.StateStore.setAppStateEntryValues(java.util.Map<androidx.wear.protolayout.expression.AppDataKey<?>,androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<?>> arg1)
+InvalidNullConversion: androidx.wear.protolayout.expression.pipeline.StateStore#setAppStateEntryValuesProto(java.util.Map<androidx.wear.protolayout.expression.AppDataKey<?>,androidx.wear.protolayout.expression.proto.DynamicDataProto.DynamicDataValue>) parameter #0:
+    Attempted to remove nullability from java.lang.Object (was NONNULL) in parameter arg1 in androidx.wear.protolayout.expression.pipeline.StateStore.setAppStateEntryValuesProto(java.util.Map<androidx.wear.protolayout.expression.AppDataKey<?>,androidx.wear.protolayout.expression.proto.DynamicDataProto.DynamicDataValue> arg1)
diff --git a/wear/protolayout/protolayout-expression/api/1.2.0-beta01.txt b/wear/protolayout/protolayout-expression/api/1.2.0-beta01.txt
new file mode 100644
index 0000000..c0f192c
--- /dev/null
+++ b/wear/protolayout/protolayout-expression/api/1.2.0-beta01.txt
@@ -0,0 +1,407 @@
+// Signature format: 4.0
+package androidx.wear.protolayout.expression {
+
+  public final class AnimationParameterBuilders {
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int REPEAT_MODE_RESTART = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int REPEAT_MODE_REVERSE = 2; // 0x2
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int REPEAT_MODE_UNKNOWN = 0; // 0x0
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class AnimationParameterBuilders.AnimationParameters {
+    method @IntRange(from=0) public long getDelayMillis();
+    method @IntRange(from=0) public long getDurationMillis();
+    method public androidx.wear.protolayout.expression.AnimationParameterBuilders.Easing? getEasing();
+  }
+
+  public static final class AnimationParameterBuilders.AnimationParameters.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public AnimationParameterBuilders.AnimationParameters.Builder();
+    method public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters.Builder setDelayMillis(@IntRange(from=0) long);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters.Builder setDurationMillis(@IntRange(from=0) long);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters.Builder setEasing(androidx.wear.protolayout.expression.AnimationParameterBuilders.Easing);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class AnimationParameterBuilders.AnimationSpec {
+    method public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters? getAnimationParameters();
+    method public androidx.wear.protolayout.expression.AnimationParameterBuilders.Repeatable? getRepeatable();
+  }
+
+  public static final class AnimationParameterBuilders.AnimationSpec.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public AnimationParameterBuilders.AnimationSpec.Builder();
+    method public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec.Builder setAnimationParameters(androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec.Builder setRepeatable(androidx.wear.protolayout.expression.AnimationParameterBuilders.Repeatable);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static interface AnimationParameterBuilders.Easing {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.AnimationParameterBuilders.Easing cubicBezier(float, float, float, float);
+    method public static androidx.wear.protolayout.expression.AnimationParameterBuilders.Easing fromByteArray(byte[]);
+    method public default byte[] toEasingByteArray();
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final androidx.wear.protolayout.expression.AnimationParameterBuilders.Easing FAST_OUT_LINEAR_IN_EASING;
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final androidx.wear.protolayout.expression.AnimationParameterBuilders.Easing FAST_OUT_SLOW_IN_EASING;
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final androidx.wear.protolayout.expression.AnimationParameterBuilders.Easing LINEAR_OUT_SLOW_IN_EASING;
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class AnimationParameterBuilders.Repeatable {
+    method public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters? getForwardRepeatOverride();
+    method public int getIterations();
+    method public int getRepeatMode();
+    method public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters? getReverseRepeatOverride();
+    method public boolean hasInfiniteIteration();
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final androidx.wear.protolayout.expression.AnimationParameterBuilders.Repeatable INFINITE_REPEATABLE_WITH_RESTART;
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final androidx.wear.protolayout.expression.AnimationParameterBuilders.Repeatable INFINITE_REPEATABLE_WITH_REVERSE;
+  }
+
+  public static final class AnimationParameterBuilders.Repeatable.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public AnimationParameterBuilders.Repeatable.Builder();
+    method public androidx.wear.protolayout.expression.AnimationParameterBuilders.Repeatable build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.Repeatable.Builder setForwardRepeatOverride(androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.Repeatable.Builder setIterations(@IntRange(from=1) int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.Repeatable.Builder setRepeatMode(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.Repeatable.Builder setReverseRepeatOverride(androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters);
+  }
+
+  public final class AppDataKey<T extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType> extends androidx.wear.protolayout.expression.DynamicDataKey<T!> {
+    ctor public AppDataKey(String);
+  }
+
+  public class ConditionScopes {
+  }
+
+  public static class ConditionScopes.ConditionScope<T extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType, RawT> {
+    method public androidx.wear.protolayout.expression.ConditionScopes.IfTrueScope<T!,RawT!> use(RawT!);
+    method public androidx.wear.protolayout.expression.ConditionScopes.IfTrueScope<T!,RawT!> use(T!);
+  }
+
+  public static class ConditionScopes.IfTrueScope<T extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType, RawT> {
+    method public T! elseUse(RawT!);
+    method public T! elseUse(T!);
+  }
+
+  public final class DynamicBuilders {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static interface DynamicBuilders.DynamicBool extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool and(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool constant(boolean);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool eq(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool!>);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool fromByteArray(byte[], int, int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool ne(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool negate();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool or(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+    method public default byte[] toDynamicBoolByteArray();
+    method public default int toDynamicBoolByteArray(byte[]);
+    method public default int toDynamicBoolByteArray(byte[], int, int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static interface DynamicBuilders.DynamicColor extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor animate();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor animate(androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor animate(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor!>);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor animate(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor!>, androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor animate(@ColorInt int, @ColorInt int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor animate(@ColorInt int, @ColorInt int, androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor constant(@ColorInt int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor!>);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor fromByteArray(byte[], int, int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.ConditionScopes.ConditionScope<androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor!,java.lang.Integer!> onCondition(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+    method public default byte[] toDynamicColorByteArray();
+    method public default int toDynamicColorByteArray(byte[]);
+    method public default int toDynamicColorByteArray(byte[], int, int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static interface DynamicBuilders.DynamicDuration extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration!>);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration fromByteArray(byte[], int, int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getHoursPart();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getIntDaysPart();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getMinutesPart();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getSecondsPart();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.ConditionScopes.ConditionScope<androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration!,java.time.Duration!> onCondition(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+    method public default byte[] toDynamicDurationByteArray();
+    method public default int toDynamicDurationByteArray(byte[]);
+    method public default int toDynamicDurationByteArray(byte[], int, int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntDays();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntHours();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntMinutes();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntSeconds();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration withSecondsPrecision(java.time.Duration);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static interface DynamicBuilders.DynamicFloat extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat animate();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat animate(androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat animate(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat!>);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat animate(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat!>, androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat animate(float, float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat animate(float, float, androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 asInt();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat constant(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat div(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat div(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat div(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool eq(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool eq(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicString format();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicString format(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat.FloatFormatter);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat!>);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat fromByteArray(byte[], int, int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gt(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gt(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gte(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gte(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool lt(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool lt(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool lte(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool lte(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat minus(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat minus(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat minus(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool ne(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool ne(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.ConditionScopes.ConditionScope<androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat!,java.lang.Float!> onCondition(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat plus(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat plus(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat plus(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat rem(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat rem(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat rem(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat times(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat times(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat times(float);
+    method public default byte[] toDynamicFloatByteArray();
+    method public default int toDynamicFloatByteArray(byte[]);
+    method public default int toDynamicFloatByteArray(byte[], int, int);
+  }
+
+  public static class DynamicBuilders.DynamicFloat.FloatFormatter {
+    method @IntRange(from=0) public int getMaxFractionDigits();
+    method @IntRange(from=0) public int getMinFractionDigits();
+    method @IntRange(from=0) public int getMinIntegerDigits();
+    method public boolean isGroupingUsed();
+  }
+
+  public static final class DynamicBuilders.DynamicFloat.FloatFormatter.Builder {
+    ctor public DynamicBuilders.DynamicFloat.FloatFormatter.Builder();
+    method public androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat.FloatFormatter build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat.FloatFormatter.Builder setGroupingUsed(boolean);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat.FloatFormatter.Builder setMaxFractionDigits(@IntRange(from=0) int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat.FloatFormatter.Builder setMinFractionDigits(@IntRange(from=0) int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat.FloatFormatter.Builder setMinIntegerDigits(@IntRange(from=0) int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static interface DynamicBuilders.DynamicInstant extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration durationUntil(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant!>);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant fromByteArray(byte[], int, int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getDayOfMonth(java.time.ZoneId);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getDayOfWeek(java.time.ZoneId);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getHour(java.time.ZoneId);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getMinute(java.time.ZoneId);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getMonth(java.time.ZoneId);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getSecond(java.time.ZoneId);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getYear(java.time.ZoneId);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.ConditionScopes.ConditionScope<androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant!,java.time.Instant!> onCondition(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant platformTimeWithSecondsPrecision();
+    method public default byte[] toDynamicInstantByteArray();
+    method public default int toDynamicInstantByteArray(byte[]);
+    method public default int toDynamicInstantByteArray(byte[], int, int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant withSecondsPrecision(java.time.Instant);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static interface DynamicBuilders.DynamicInt32 extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 animate();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 animate(androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 animate(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32!>);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 animate(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32!>, androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 animate(int, int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 animate(int, int, androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat asFloat();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 constant(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat div(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 div(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat div(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 div(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool eq(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool eq(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicString format();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicString format(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32.IntFormatter);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32!>);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 fromByteArray(byte[], int, int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gt(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gt(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gte(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gte(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool lt(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool lt(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool lte(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool lte(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat minus(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 minus(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat minus(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 minus(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool ne(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool ne(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.ConditionScopes.ConditionScope<androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32!,java.lang.Integer!> onCondition(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat plus(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 plus(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat plus(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 plus(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat rem(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 rem(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat rem(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 rem(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat times(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 times(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat times(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 times(int);
+    method public default byte[] toDynamicInt32ByteArray();
+    method public default int toDynamicInt32ByteArray(byte[]);
+    method public default int toDynamicInt32ByteArray(byte[], int, int);
+  }
+
+  public static class DynamicBuilders.DynamicInt32.IntFormatter {
+    method @IntRange(from=0) public int getMinIntegerDigits();
+    method public boolean isGroupingUsed();
+  }
+
+  public static final class DynamicBuilders.DynamicInt32.IntFormatter.Builder {
+    ctor public DynamicBuilders.DynamicInt32.IntFormatter.Builder();
+    method public androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32.IntFormatter build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32.IntFormatter.Builder setGroupingUsed(boolean);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32.IntFormatter.Builder setMinIntegerDigits(@IntRange(from=0) int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static interface DynamicBuilders.DynamicString extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicString concat(androidx.wear.protolayout.expression.DynamicBuilders.DynamicString);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicString constant(String);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicString from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicString!>);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicString fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicString fromByteArray(byte[], int, int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.ConditionScopes.ConditionScope<androidx.wear.protolayout.expression.DynamicBuilders.DynamicString!,java.lang.String!> onCondition(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+    method public default byte[] toDynamicStringByteArray();
+    method public default int toDynamicStringByteArray(byte[]);
+    method public default int toDynamicStringByteArray(byte[], int, int);
+  }
+
+  public static interface DynamicBuilders.DynamicType {
+  }
+
+  public final class DynamicDataBuilders {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static interface DynamicDataBuilders.DynamicDataValue<T extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType> {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool!> fromBool(boolean);
+    method public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<? extends java.lang.Object!> fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<? extends java.lang.Object!> fromByteArray(byte[], int, int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor!> fromColor(@ColorInt int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration!> fromDuration(java.time.Duration);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat!> fromFloat(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant!> fromInstant(java.time.Instant);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32!> fromInt(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<androidx.wear.protolayout.expression.DynamicBuilders.DynamicString!> fromString(String);
+    method public default boolean getBoolValue();
+    method @ColorInt public default int getColorValue();
+    method public default java.time.Duration getDurationValue();
+    method public default float getFloatValue();
+    method public default java.time.Instant getInstantValue();
+    method public default int getIntValue();
+    method public default String getStringValue();
+    method public default boolean hasBoolValue();
+    method public default boolean hasColorValue();
+    method public default boolean hasDurationValue();
+    method public default boolean hasFloatValue();
+    method public default boolean hasInstantValue();
+    method public default boolean hasIntValue();
+    method public default boolean hasStringValue();
+    method public default byte[] toDynamicDataValueByteArray();
+    method public default int toDynamicDataValueByteArray(byte[]);
+    method public default int toDynamicDataValueByteArray(byte[], int, int);
+  }
+
+  public abstract class DynamicDataKey<T extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType> {
+    method public String getKey();
+    method public String getNamespace();
+  }
+
+  @SuppressCompatibility @RequiresOptIn(level=androidx.annotation.RequiresOptIn.Level.ERROR) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD}) public @interface ExperimentalProtoLayoutExtensionApi {
+  }
+
+  public final class PlatformDataKey<T extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType> extends androidx.wear.protolayout.expression.DynamicDataKey<T!> {
+    ctor public PlatformDataKey(String, String);
+  }
+
+  public final class PlatformDataValues {
+    method public java.util.Map<androidx.wear.protolayout.expression.PlatformDataKey<? extends java.lang.Object!>!,androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<? extends java.lang.Object!>!> getAll();
+    method public static <T extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType> androidx.wear.protolayout.expression.PlatformDataValues of(androidx.wear.protolayout.expression.PlatformDataKey<T!>, androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<T!>);
+  }
+
+  public static final class PlatformDataValues.Builder {
+    ctor public PlatformDataValues.Builder();
+    method public androidx.wear.protolayout.expression.PlatformDataValues build();
+    method public <T extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType> androidx.wear.protolayout.expression.PlatformDataValues.Builder put(androidx.wear.protolayout.expression.PlatformDataKey<T!>, androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<T!>);
+    method public androidx.wear.protolayout.expression.PlatformDataValues.Builder putAll(androidx.wear.protolayout.expression.PlatformDataValues);
+  }
+
+  public class PlatformHealthSources {
+    method @RequiresPermission(android.Manifest.permission.ACTIVITY_RECOGNITION) @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat dailyCalories();
+    method @RequiresPermission(android.Manifest.permission.ACTIVITY_RECOGNITION) @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat dailyDistanceMeters();
+    method @RequiresPermission(android.Manifest.permission.ACTIVITY_RECOGNITION) @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat dailyFloors();
+    method @RequiresPermission(android.Manifest.permission.ACTIVITY_RECOGNITION) @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 dailySteps();
+    method @RequiresPermission(android.Manifest.permission.BODY_SENSORS) @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.PlatformHealthSources.DynamicHeartRateAccuracy heartRateAccuracy();
+    method @RequiresPermission(android.Manifest.permission.BODY_SENSORS) @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat heartRateBpm();
+    field public static final int HEART_RATE_ACCURACY_HIGH = 5; // 0x5
+    field public static final int HEART_RATE_ACCURACY_LOW = 3; // 0x3
+    field public static final int HEART_RATE_ACCURACY_MEDIUM = 4; // 0x4
+    field public static final int HEART_RATE_ACCURACY_NO_CONTACT = 1; // 0x1
+    field public static final int HEART_RATE_ACCURACY_UNKNOWN = 0; // 0x0
+    field public static final int HEART_RATE_ACCURACY_UNRELIABLE = 2; // 0x2
+  }
+
+  public static final class PlatformHealthSources.DynamicHeartRateAccuracy implements androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.PlatformHealthSources.DynamicHeartRateAccuracy constant(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<androidx.wear.protolayout.expression.PlatformHealthSources.DynamicHeartRateAccuracy!> dynamicDataValueOf(int);
+  }
+
+  public static class PlatformHealthSources.Keys {
+    field @RequiresPermission(android.Manifest.permission.ACTIVITY_RECOGNITION) public static final androidx.wear.protolayout.expression.PlatformDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat!> DAILY_CALORIES;
+    field @RequiresPermission(android.Manifest.permission.ACTIVITY_RECOGNITION) public static final androidx.wear.protolayout.expression.PlatformDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat!> DAILY_DISTANCE_METERS;
+    field @RequiresPermission(android.Manifest.permission.ACTIVITY_RECOGNITION) public static final androidx.wear.protolayout.expression.PlatformDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat!> DAILY_FLOORS;
+    field @RequiresPermission(android.Manifest.permission.ACTIVITY_RECOGNITION) public static final androidx.wear.protolayout.expression.PlatformDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32!> DAILY_STEPS;
+    field @RequiresPermission(android.Manifest.permission.BODY_SENSORS) public static final androidx.wear.protolayout.expression.PlatformDataKey<androidx.wear.protolayout.expression.PlatformHealthSources.DynamicHeartRateAccuracy!> HEART_RATE_ACCURACY;
+    field @RequiresPermission(android.Manifest.permission.BODY_SENSORS) public static final androidx.wear.protolayout.expression.PlatformDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat!> HEART_RATE_BPM;
+  }
+
+  @SuppressCompatibility @RequiresOptIn(level=androidx.annotation.RequiresOptIn.Level.ERROR) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD}) public @interface ProtoLayoutExperimental {
+  }
+
+  @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.FIELD}) @kotlin.annotation.MustBeDocumented public @interface RequiresSchemaVersion {
+    method public abstract int major();
+    method public abstract int minor();
+  }
+
+  public final class VersionBuilders {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class VersionBuilders.VersionInfo implements java.lang.Comparable<androidx.wear.protolayout.expression.VersionBuilders.VersionInfo!> {
+    method public int compareTo(androidx.wear.protolayout.expression.VersionBuilders.VersionInfo);
+    method public int getMajor();
+    method public int getMinor();
+  }
+
+  public static final class VersionBuilders.VersionInfo.Builder {
+    ctor public VersionBuilders.VersionInfo.Builder();
+    method public androidx.wear.protolayout.expression.VersionBuilders.VersionInfo build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.expression.VersionBuilders.VersionInfo.Builder setMajor(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.expression.VersionBuilders.VersionInfo.Builder setMinor(int);
+  }
+
+}
+
diff --git a/wear/protolayout/protolayout-expression/api/current.ignore b/wear/protolayout/protolayout-expression/api/current.ignore
new file mode 100644
index 0000000..289bfe6
--- /dev/null
+++ b/wear/protolayout/protolayout-expression/api/current.ignore
@@ -0,0 +1,7 @@
+// Baseline format: 1.0
+InvalidNullConversion: androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue#fromByteArray(byte[]):
+    Attempted to remove nullability from java.lang.Object (was NONNULL) in method androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue.fromByteArray(byte[])
+InvalidNullConversion: androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue#fromByteArray(byte[], int, int):
+    Attempted to remove nullability from java.lang.Object (was NONNULL) in method androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue.fromByteArray(byte[],int,int)
+InvalidNullConversion: androidx.wear.protolayout.expression.PlatformDataValues#getAll():
+    Attempted to remove nullability from java.lang.Object (was NONNULL) in method androidx.wear.protolayout.expression.PlatformDataValues.getAll()
diff --git a/wear/protolayout/protolayout-expression/api/res-1.2.0-beta01.txt b/wear/protolayout/protolayout-expression/api/res-1.2.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wear/protolayout/protolayout-expression/api/res-1.2.0-beta01.txt
diff --git a/wear/protolayout/protolayout-expression/api/restricted_1.2.0-beta01.txt b/wear/protolayout/protolayout-expression/api/restricted_1.2.0-beta01.txt
new file mode 100644
index 0000000..c0f192c
--- /dev/null
+++ b/wear/protolayout/protolayout-expression/api/restricted_1.2.0-beta01.txt
@@ -0,0 +1,407 @@
+// Signature format: 4.0
+package androidx.wear.protolayout.expression {
+
+  public final class AnimationParameterBuilders {
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int REPEAT_MODE_RESTART = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int REPEAT_MODE_REVERSE = 2; // 0x2
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int REPEAT_MODE_UNKNOWN = 0; // 0x0
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class AnimationParameterBuilders.AnimationParameters {
+    method @IntRange(from=0) public long getDelayMillis();
+    method @IntRange(from=0) public long getDurationMillis();
+    method public androidx.wear.protolayout.expression.AnimationParameterBuilders.Easing? getEasing();
+  }
+
+  public static final class AnimationParameterBuilders.AnimationParameters.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public AnimationParameterBuilders.AnimationParameters.Builder();
+    method public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters.Builder setDelayMillis(@IntRange(from=0) long);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters.Builder setDurationMillis(@IntRange(from=0) long);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters.Builder setEasing(androidx.wear.protolayout.expression.AnimationParameterBuilders.Easing);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class AnimationParameterBuilders.AnimationSpec {
+    method public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters? getAnimationParameters();
+    method public androidx.wear.protolayout.expression.AnimationParameterBuilders.Repeatable? getRepeatable();
+  }
+
+  public static final class AnimationParameterBuilders.AnimationSpec.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public AnimationParameterBuilders.AnimationSpec.Builder();
+    method public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec.Builder setAnimationParameters(androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec.Builder setRepeatable(androidx.wear.protolayout.expression.AnimationParameterBuilders.Repeatable);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static interface AnimationParameterBuilders.Easing {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.AnimationParameterBuilders.Easing cubicBezier(float, float, float, float);
+    method public static androidx.wear.protolayout.expression.AnimationParameterBuilders.Easing fromByteArray(byte[]);
+    method public default byte[] toEasingByteArray();
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final androidx.wear.protolayout.expression.AnimationParameterBuilders.Easing FAST_OUT_LINEAR_IN_EASING;
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final androidx.wear.protolayout.expression.AnimationParameterBuilders.Easing FAST_OUT_SLOW_IN_EASING;
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final androidx.wear.protolayout.expression.AnimationParameterBuilders.Easing LINEAR_OUT_SLOW_IN_EASING;
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class AnimationParameterBuilders.Repeatable {
+    method public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters? getForwardRepeatOverride();
+    method public int getIterations();
+    method public int getRepeatMode();
+    method public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters? getReverseRepeatOverride();
+    method public boolean hasInfiniteIteration();
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final androidx.wear.protolayout.expression.AnimationParameterBuilders.Repeatable INFINITE_REPEATABLE_WITH_RESTART;
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final androidx.wear.protolayout.expression.AnimationParameterBuilders.Repeatable INFINITE_REPEATABLE_WITH_REVERSE;
+  }
+
+  public static final class AnimationParameterBuilders.Repeatable.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public AnimationParameterBuilders.Repeatable.Builder();
+    method public androidx.wear.protolayout.expression.AnimationParameterBuilders.Repeatable build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.Repeatable.Builder setForwardRepeatOverride(androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.Repeatable.Builder setIterations(@IntRange(from=1) int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.Repeatable.Builder setRepeatMode(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.Repeatable.Builder setReverseRepeatOverride(androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters);
+  }
+
+  public final class AppDataKey<T extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType> extends androidx.wear.protolayout.expression.DynamicDataKey<T!> {
+    ctor public AppDataKey(String);
+  }
+
+  public class ConditionScopes {
+  }
+
+  public static class ConditionScopes.ConditionScope<T extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType, RawT> {
+    method public androidx.wear.protolayout.expression.ConditionScopes.IfTrueScope<T!,RawT!> use(RawT!);
+    method public androidx.wear.protolayout.expression.ConditionScopes.IfTrueScope<T!,RawT!> use(T!);
+  }
+
+  public static class ConditionScopes.IfTrueScope<T extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType, RawT> {
+    method public T! elseUse(RawT!);
+    method public T! elseUse(T!);
+  }
+
+  public final class DynamicBuilders {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static interface DynamicBuilders.DynamicBool extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool and(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool constant(boolean);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool eq(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool!>);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool fromByteArray(byte[], int, int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool ne(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool negate();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool or(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+    method public default byte[] toDynamicBoolByteArray();
+    method public default int toDynamicBoolByteArray(byte[]);
+    method public default int toDynamicBoolByteArray(byte[], int, int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static interface DynamicBuilders.DynamicColor extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor animate();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor animate(androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor animate(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor!>);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor animate(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor!>, androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor animate(@ColorInt int, @ColorInt int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor animate(@ColorInt int, @ColorInt int, androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor constant(@ColorInt int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor!>);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor fromByteArray(byte[], int, int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.ConditionScopes.ConditionScope<androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor!,java.lang.Integer!> onCondition(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+    method public default byte[] toDynamicColorByteArray();
+    method public default int toDynamicColorByteArray(byte[]);
+    method public default int toDynamicColorByteArray(byte[], int, int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static interface DynamicBuilders.DynamicDuration extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration!>);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration fromByteArray(byte[], int, int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getHoursPart();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getIntDaysPart();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getMinutesPart();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getSecondsPart();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.ConditionScopes.ConditionScope<androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration!,java.time.Duration!> onCondition(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+    method public default byte[] toDynamicDurationByteArray();
+    method public default int toDynamicDurationByteArray(byte[]);
+    method public default int toDynamicDurationByteArray(byte[], int, int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntDays();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntHours();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntMinutes();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntSeconds();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration withSecondsPrecision(java.time.Duration);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static interface DynamicBuilders.DynamicFloat extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat animate();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat animate(androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat animate(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat!>);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat animate(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat!>, androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat animate(float, float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat animate(float, float, androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 asInt();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat constant(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat div(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat div(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat div(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool eq(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool eq(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicString format();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicString format(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat.FloatFormatter);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat!>);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat fromByteArray(byte[], int, int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gt(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gt(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gte(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gte(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool lt(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool lt(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool lte(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool lte(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat minus(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat minus(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat minus(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool ne(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool ne(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.ConditionScopes.ConditionScope<androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat!,java.lang.Float!> onCondition(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat plus(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat plus(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat plus(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat rem(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat rem(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat rem(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat times(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat times(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat times(float);
+    method public default byte[] toDynamicFloatByteArray();
+    method public default int toDynamicFloatByteArray(byte[]);
+    method public default int toDynamicFloatByteArray(byte[], int, int);
+  }
+
+  public static class DynamicBuilders.DynamicFloat.FloatFormatter {
+    method @IntRange(from=0) public int getMaxFractionDigits();
+    method @IntRange(from=0) public int getMinFractionDigits();
+    method @IntRange(from=0) public int getMinIntegerDigits();
+    method public boolean isGroupingUsed();
+  }
+
+  public static final class DynamicBuilders.DynamicFloat.FloatFormatter.Builder {
+    ctor public DynamicBuilders.DynamicFloat.FloatFormatter.Builder();
+    method public androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat.FloatFormatter build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat.FloatFormatter.Builder setGroupingUsed(boolean);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat.FloatFormatter.Builder setMaxFractionDigits(@IntRange(from=0) int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat.FloatFormatter.Builder setMinFractionDigits(@IntRange(from=0) int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat.FloatFormatter.Builder setMinIntegerDigits(@IntRange(from=0) int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static interface DynamicBuilders.DynamicInstant extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration durationUntil(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant!>);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant fromByteArray(byte[], int, int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getDayOfMonth(java.time.ZoneId);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getDayOfWeek(java.time.ZoneId);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getHour(java.time.ZoneId);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getMinute(java.time.ZoneId);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getMonth(java.time.ZoneId);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getSecond(java.time.ZoneId);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getYear(java.time.ZoneId);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.ConditionScopes.ConditionScope<androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant!,java.time.Instant!> onCondition(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant platformTimeWithSecondsPrecision();
+    method public default byte[] toDynamicInstantByteArray();
+    method public default int toDynamicInstantByteArray(byte[]);
+    method public default int toDynamicInstantByteArray(byte[], int, int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant withSecondsPrecision(java.time.Instant);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static interface DynamicBuilders.DynamicInt32 extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 animate();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 animate(androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 animate(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32!>);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 animate(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32!>, androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 animate(int, int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 animate(int, int, androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat asFloat();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 constant(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat div(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 div(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat div(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 div(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool eq(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool eq(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicString format();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicString format(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32.IntFormatter);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32!>);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 fromByteArray(byte[], int, int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gt(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gt(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gte(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gte(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool lt(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool lt(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool lte(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool lte(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat minus(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 minus(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat minus(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 minus(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool ne(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool ne(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.ConditionScopes.ConditionScope<androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32!,java.lang.Integer!> onCondition(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat plus(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 plus(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat plus(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 plus(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat rem(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 rem(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat rem(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 rem(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat times(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 times(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat times(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 times(int);
+    method public default byte[] toDynamicInt32ByteArray();
+    method public default int toDynamicInt32ByteArray(byte[]);
+    method public default int toDynamicInt32ByteArray(byte[], int, int);
+  }
+
+  public static class DynamicBuilders.DynamicInt32.IntFormatter {
+    method @IntRange(from=0) public int getMinIntegerDigits();
+    method public boolean isGroupingUsed();
+  }
+
+  public static final class DynamicBuilders.DynamicInt32.IntFormatter.Builder {
+    ctor public DynamicBuilders.DynamicInt32.IntFormatter.Builder();
+    method public androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32.IntFormatter build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32.IntFormatter.Builder setGroupingUsed(boolean);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32.IntFormatter.Builder setMinIntegerDigits(@IntRange(from=0) int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static interface DynamicBuilders.DynamicString extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicString concat(androidx.wear.protolayout.expression.DynamicBuilders.DynamicString);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicString constant(String);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicString from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicString!>);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicString fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicString fromByteArray(byte[], int, int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.ConditionScopes.ConditionScope<androidx.wear.protolayout.expression.DynamicBuilders.DynamicString!,java.lang.String!> onCondition(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+    method public default byte[] toDynamicStringByteArray();
+    method public default int toDynamicStringByteArray(byte[]);
+    method public default int toDynamicStringByteArray(byte[], int, int);
+  }
+
+  public static interface DynamicBuilders.DynamicType {
+  }
+
+  public final class DynamicDataBuilders {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static interface DynamicDataBuilders.DynamicDataValue<T extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType> {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool!> fromBool(boolean);
+    method public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<? extends java.lang.Object!> fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<? extends java.lang.Object!> fromByteArray(byte[], int, int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor!> fromColor(@ColorInt int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration!> fromDuration(java.time.Duration);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat!> fromFloat(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant!> fromInstant(java.time.Instant);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32!> fromInt(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<androidx.wear.protolayout.expression.DynamicBuilders.DynamicString!> fromString(String);
+    method public default boolean getBoolValue();
+    method @ColorInt public default int getColorValue();
+    method public default java.time.Duration getDurationValue();
+    method public default float getFloatValue();
+    method public default java.time.Instant getInstantValue();
+    method public default int getIntValue();
+    method public default String getStringValue();
+    method public default boolean hasBoolValue();
+    method public default boolean hasColorValue();
+    method public default boolean hasDurationValue();
+    method public default boolean hasFloatValue();
+    method public default boolean hasInstantValue();
+    method public default boolean hasIntValue();
+    method public default boolean hasStringValue();
+    method public default byte[] toDynamicDataValueByteArray();
+    method public default int toDynamicDataValueByteArray(byte[]);
+    method public default int toDynamicDataValueByteArray(byte[], int, int);
+  }
+
+  public abstract class DynamicDataKey<T extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType> {
+    method public String getKey();
+    method public String getNamespace();
+  }
+
+  @SuppressCompatibility @RequiresOptIn(level=androidx.annotation.RequiresOptIn.Level.ERROR) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD}) public @interface ExperimentalProtoLayoutExtensionApi {
+  }
+
+  public final class PlatformDataKey<T extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType> extends androidx.wear.protolayout.expression.DynamicDataKey<T!> {
+    ctor public PlatformDataKey(String, String);
+  }
+
+  public final class PlatformDataValues {
+    method public java.util.Map<androidx.wear.protolayout.expression.PlatformDataKey<? extends java.lang.Object!>!,androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<? extends java.lang.Object!>!> getAll();
+    method public static <T extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType> androidx.wear.protolayout.expression.PlatformDataValues of(androidx.wear.protolayout.expression.PlatformDataKey<T!>, androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<T!>);
+  }
+
+  public static final class PlatformDataValues.Builder {
+    ctor public PlatformDataValues.Builder();
+    method public androidx.wear.protolayout.expression.PlatformDataValues build();
+    method public <T extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType> androidx.wear.protolayout.expression.PlatformDataValues.Builder put(androidx.wear.protolayout.expression.PlatformDataKey<T!>, androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<T!>);
+    method public androidx.wear.protolayout.expression.PlatformDataValues.Builder putAll(androidx.wear.protolayout.expression.PlatformDataValues);
+  }
+
+  public class PlatformHealthSources {
+    method @RequiresPermission(android.Manifest.permission.ACTIVITY_RECOGNITION) @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat dailyCalories();
+    method @RequiresPermission(android.Manifest.permission.ACTIVITY_RECOGNITION) @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat dailyDistanceMeters();
+    method @RequiresPermission(android.Manifest.permission.ACTIVITY_RECOGNITION) @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat dailyFloors();
+    method @RequiresPermission(android.Manifest.permission.ACTIVITY_RECOGNITION) @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 dailySteps();
+    method @RequiresPermission(android.Manifest.permission.BODY_SENSORS) @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.PlatformHealthSources.DynamicHeartRateAccuracy heartRateAccuracy();
+    method @RequiresPermission(android.Manifest.permission.BODY_SENSORS) @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat heartRateBpm();
+    field public static final int HEART_RATE_ACCURACY_HIGH = 5; // 0x5
+    field public static final int HEART_RATE_ACCURACY_LOW = 3; // 0x3
+    field public static final int HEART_RATE_ACCURACY_MEDIUM = 4; // 0x4
+    field public static final int HEART_RATE_ACCURACY_NO_CONTACT = 1; // 0x1
+    field public static final int HEART_RATE_ACCURACY_UNKNOWN = 0; // 0x0
+    field public static final int HEART_RATE_ACCURACY_UNRELIABLE = 2; // 0x2
+  }
+
+  public static final class PlatformHealthSources.DynamicHeartRateAccuracy implements androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.PlatformHealthSources.DynamicHeartRateAccuracy constant(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<androidx.wear.protolayout.expression.PlatformHealthSources.DynamicHeartRateAccuracy!> dynamicDataValueOf(int);
+  }
+
+  public static class PlatformHealthSources.Keys {
+    field @RequiresPermission(android.Manifest.permission.ACTIVITY_RECOGNITION) public static final androidx.wear.protolayout.expression.PlatformDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat!> DAILY_CALORIES;
+    field @RequiresPermission(android.Manifest.permission.ACTIVITY_RECOGNITION) public static final androidx.wear.protolayout.expression.PlatformDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat!> DAILY_DISTANCE_METERS;
+    field @RequiresPermission(android.Manifest.permission.ACTIVITY_RECOGNITION) public static final androidx.wear.protolayout.expression.PlatformDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat!> DAILY_FLOORS;
+    field @RequiresPermission(android.Manifest.permission.ACTIVITY_RECOGNITION) public static final androidx.wear.protolayout.expression.PlatformDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32!> DAILY_STEPS;
+    field @RequiresPermission(android.Manifest.permission.BODY_SENSORS) public static final androidx.wear.protolayout.expression.PlatformDataKey<androidx.wear.protolayout.expression.PlatformHealthSources.DynamicHeartRateAccuracy!> HEART_RATE_ACCURACY;
+    field @RequiresPermission(android.Manifest.permission.BODY_SENSORS) public static final androidx.wear.protolayout.expression.PlatformDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat!> HEART_RATE_BPM;
+  }
+
+  @SuppressCompatibility @RequiresOptIn(level=androidx.annotation.RequiresOptIn.Level.ERROR) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD}) public @interface ProtoLayoutExperimental {
+  }
+
+  @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.FIELD}) @kotlin.annotation.MustBeDocumented public @interface RequiresSchemaVersion {
+    method public abstract int major();
+    method public abstract int minor();
+  }
+
+  public final class VersionBuilders {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class VersionBuilders.VersionInfo implements java.lang.Comparable<androidx.wear.protolayout.expression.VersionBuilders.VersionInfo!> {
+    method public int compareTo(androidx.wear.protolayout.expression.VersionBuilders.VersionInfo);
+    method public int getMajor();
+    method public int getMinor();
+  }
+
+  public static final class VersionBuilders.VersionInfo.Builder {
+    ctor public VersionBuilders.VersionInfo.Builder();
+    method public androidx.wear.protolayout.expression.VersionBuilders.VersionInfo build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.expression.VersionBuilders.VersionInfo.Builder setMajor(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.expression.VersionBuilders.VersionInfo.Builder setMinor(int);
+  }
+
+}
+
diff --git a/wear/protolayout/protolayout-expression/api/restricted_current.ignore b/wear/protolayout/protolayout-expression/api/restricted_current.ignore
new file mode 100644
index 0000000..289bfe6
--- /dev/null
+++ b/wear/protolayout/protolayout-expression/api/restricted_current.ignore
@@ -0,0 +1,7 @@
+// Baseline format: 1.0
+InvalidNullConversion: androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue#fromByteArray(byte[]):
+    Attempted to remove nullability from java.lang.Object (was NONNULL) in method androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue.fromByteArray(byte[])
+InvalidNullConversion: androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue#fromByteArray(byte[], int, int):
+    Attempted to remove nullability from java.lang.Object (was NONNULL) in method androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue.fromByteArray(byte[],int,int)
+InvalidNullConversion: androidx.wear.protolayout.expression.PlatformDataValues#getAll():
+    Attempted to remove nullability from java.lang.Object (was NONNULL) in method androidx.wear.protolayout.expression.PlatformDataValues.getAll()
diff --git a/wear/protolayout/protolayout-external-protobuf/api/1.2.0-beta01.txt b/wear/protolayout/protolayout-external-protobuf/api/1.2.0-beta01.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/wear/protolayout/protolayout-external-protobuf/api/1.2.0-beta01.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/wear/protolayout/protolayout-external-protobuf/api/restricted_1.2.0-beta01.txt b/wear/protolayout/protolayout-external-protobuf/api/restricted_1.2.0-beta01.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/wear/protolayout/protolayout-external-protobuf/api/restricted_1.2.0-beta01.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/wear/protolayout/protolayout-material-core/api/1.2.0-beta01.txt b/wear/protolayout/protolayout-material-core/api/1.2.0-beta01.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/wear/protolayout/protolayout-material-core/api/1.2.0-beta01.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/wear/protolayout/protolayout-material-core/api/res-1.2.0-beta01.txt b/wear/protolayout/protolayout-material-core/api/res-1.2.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wear/protolayout/protolayout-material-core/api/res-1.2.0-beta01.txt
diff --git a/wear/protolayout/protolayout-material-core/api/restricted_1.2.0-beta01.txt b/wear/protolayout/protolayout-material-core/api/restricted_1.2.0-beta01.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/wear/protolayout/protolayout-material-core/api/restricted_1.2.0-beta01.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/wear/protolayout/protolayout-material/api/1.2.0-beta01.txt b/wear/protolayout/protolayout-material/api/1.2.0-beta01.txt
new file mode 100644
index 0000000..c51a973
--- /dev/null
+++ b/wear/protolayout/protolayout-material/api/1.2.0-beta01.txt
@@ -0,0 +1,337 @@
+// Signature format: 4.0
+package androidx.wear.protolayout.material {
+
+  public class Button implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.Button? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.ButtonColors getButtonColors();
+    method public androidx.wear.protolayout.ModifiersBuilders.Clickable getClickable();
+    method public androidx.wear.protolayout.TypeBuilders.StringProp? getContentDescription();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getCustomContent();
+    method public String? getIconContent();
+    method public String? getImageContent();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension getSize();
+    method public String? getTextContent();
+  }
+
+  public static final class Button.Builder {
+    ctor public Button.Builder(android.content.Context, androidx.wear.protolayout.ModifiersBuilders.Clickable);
+    method public androidx.wear.protolayout.material.Button build();
+    method public androidx.wear.protolayout.material.Button.Builder setButtonColors(androidx.wear.protolayout.material.ButtonColors);
+    method public androidx.wear.protolayout.material.Button.Builder setContentDescription(androidx.wear.protolayout.TypeBuilders.StringProp);
+    method public androidx.wear.protolayout.material.Button.Builder setContentDescription(CharSequence);
+    method public androidx.wear.protolayout.material.Button.Builder setCustomContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.Button.Builder setIconContent(String);
+    method public androidx.wear.protolayout.material.Button.Builder setIconContent(String, androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method public androidx.wear.protolayout.material.Button.Builder setImageContent(String);
+    method public androidx.wear.protolayout.material.Button.Builder setSize(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method public androidx.wear.protolayout.material.Button.Builder setSize(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method public androidx.wear.protolayout.material.Button.Builder setTextContent(String);
+    method public androidx.wear.protolayout.material.Button.Builder setTextContent(String, int);
+  }
+
+  public class ButtonColors {
+    ctor public ButtonColors(androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp);
+    ctor public ButtonColors(@ColorInt int, @ColorInt int);
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getBackgroundColor();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getContentColor();
+    method public static androidx.wear.protolayout.material.ButtonColors primaryButtonColors(androidx.wear.protolayout.material.Colors);
+    method public static androidx.wear.protolayout.material.ButtonColors secondaryButtonColors(androidx.wear.protolayout.material.Colors);
+  }
+
+  public class ButtonDefaults {
+    method public static androidx.wear.protolayout.DimensionBuilders.DpProp recommendedIconSize(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method public static androidx.wear.protolayout.DimensionBuilders.DpProp recommendedIconSize(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp DEFAULT_SIZE;
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp EXTRA_LARGE_SIZE;
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp LARGE_SIZE;
+    field public static final androidx.wear.protolayout.material.ButtonColors PRIMARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ButtonColors SECONDARY_COLORS;
+  }
+
+  public class Chip implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.Chip? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.ChipColors getChipColors();
+    method public androidx.wear.protolayout.ModifiersBuilders.Clickable getClickable();
+    method public androidx.wear.protolayout.TypeBuilders.StringProp? getContentDescription();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getCustomContent();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension getHeight();
+    method public int getHorizontalAlignment();
+    method public String? getIconContent();
+    method public String? getPrimaryLabelContent();
+    method public String? getSecondaryLabelContent();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension getWidth();
+  }
+
+  public static final class Chip.Builder {
+    ctor public Chip.Builder(android.content.Context, androidx.wear.protolayout.ModifiersBuilders.Clickable, androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method public androidx.wear.protolayout.material.Chip build();
+    method public androidx.wear.protolayout.material.Chip.Builder setChipColors(androidx.wear.protolayout.material.ChipColors);
+    method public androidx.wear.protolayout.material.Chip.Builder setContentDescription(androidx.wear.protolayout.TypeBuilders.StringProp);
+    method public androidx.wear.protolayout.material.Chip.Builder setContentDescription(CharSequence);
+    method public androidx.wear.protolayout.material.Chip.Builder setCustomContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.Chip.Builder setHorizontalAlignment(int);
+    method public androidx.wear.protolayout.material.Chip.Builder setIconContent(String);
+    method public androidx.wear.protolayout.material.Chip.Builder setPrimaryLabelContent(String);
+    method public androidx.wear.protolayout.material.Chip.Builder setSecondaryLabelContent(String);
+    method public androidx.wear.protolayout.material.Chip.Builder setWidth(androidx.wear.protolayout.DimensionBuilders.ContainerDimension);
+    method public androidx.wear.protolayout.material.Chip.Builder setWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  public class ChipColors {
+    ctor public ChipColors(androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp);
+    ctor public ChipColors(androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp);
+    ctor public ChipColors(@ColorInt int, @ColorInt int);
+    ctor public ChipColors(@ColorInt int, @ColorInt int, @ColorInt int, @ColorInt int);
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getBackgroundColor();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getContentColor();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getIconColor();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getSecondaryContentColor();
+    method public static androidx.wear.protolayout.material.ChipColors primaryChipColors(androidx.wear.protolayout.material.Colors);
+    method public static androidx.wear.protolayout.material.ChipColors secondaryChipColors(androidx.wear.protolayout.material.Colors);
+  }
+
+  public class ChipDefaults {
+    field public static final androidx.wear.protolayout.material.ChipColors COMPACT_PRIMARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ChipColors COMPACT_SECONDARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ChipColors PRIMARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ChipColors SECONDARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ChipColors TITLE_PRIMARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ChipColors TITLE_SECONDARY_COLORS;
+  }
+
+  public class CircularProgressIndicator implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.CircularProgressIndicator? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.ProgressIndicatorColors getCircularProgressIndicatorColors();
+    method public androidx.wear.protolayout.TypeBuilders.StringProp? getContentDescription();
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp getEndAngle();
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp getProgress();
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp getStartAngle();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp getStrokeWidth();
+    method public boolean isOuterMarginApplied();
+  }
+
+  public static final class CircularProgressIndicator.Builder {
+    ctor public CircularProgressIndicator.Builder();
+    method public androidx.wear.protolayout.material.CircularProgressIndicator build();
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setCircularProgressIndicatorColors(androidx.wear.protolayout.material.ProgressIndicatorColors);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setContentDescription(androidx.wear.protolayout.TypeBuilders.StringProp);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setContentDescription(CharSequence);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setEndAngle(float);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setOuterMarginApplied(boolean);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setProgress(androidx.wear.protolayout.TypeBuilders.FloatProp);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setProgress(@FloatRange(from=0, to=1) float);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setStartAngle(float);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setStrokeWidth(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setStrokeWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  public class Colors {
+    ctor public Colors(@ColorInt int, @ColorInt int, @ColorInt int, @ColorInt int);
+    method @ColorInt public int getOnPrimary();
+    method @ColorInt public int getOnSurface();
+    method @ColorInt public int getPrimary();
+    method @ColorInt public int getSurface();
+    field public static final androidx.wear.protolayout.material.Colors DEFAULT;
+  }
+
+  public class CompactChip implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.CompactChip? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.ChipColors getChipColors();
+    method public androidx.wear.protolayout.ModifiersBuilders.Clickable getClickable();
+    method public androidx.wear.protolayout.TypeBuilders.StringProp? getContentDescription();
+    method public String? getIconContent();
+    method public String getText();
+    method public boolean hasText();
+  }
+
+  public static final class CompactChip.Builder {
+    ctor public CompactChip.Builder(android.content.Context, androidx.wear.protolayout.ModifiersBuilders.Clickable, androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    ctor public CompactChip.Builder(android.content.Context, String, androidx.wear.protolayout.ModifiersBuilders.Clickable, androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method public androidx.wear.protolayout.material.CompactChip build();
+    method public androidx.wear.protolayout.material.CompactChip.Builder setChipColors(androidx.wear.protolayout.material.ChipColors);
+    method public androidx.wear.protolayout.material.CompactChip.Builder setContentDescription(androidx.wear.protolayout.TypeBuilders.StringProp);
+    method public androidx.wear.protolayout.material.CompactChip.Builder setContentDescription(CharSequence);
+    method public androidx.wear.protolayout.material.CompactChip.Builder setIconContent(String);
+    method public androidx.wear.protolayout.material.CompactChip.Builder setTextContent(String);
+  }
+
+  public class ProgressIndicatorColors {
+    ctor public ProgressIndicatorColors(androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp);
+    ctor public ProgressIndicatorColors(@ColorInt int, @ColorInt int);
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getIndicatorColor();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getTrackColor();
+    method public static androidx.wear.protolayout.material.ProgressIndicatorColors progressIndicatorColors(androidx.wear.protolayout.material.Colors);
+  }
+
+  public class ProgressIndicatorDefaults {
+    field public static final androidx.wear.protolayout.material.ProgressIndicatorColors DEFAULT_COLORS;
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp DEFAULT_STROKE_WIDTH;
+    field public static final float GAP_END_ANGLE = 156.1f;
+    field public static final float GAP_START_ANGLE = -156.1f;
+  }
+
+  public class Text implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.Text? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getColor();
+    method public androidx.wear.protolayout.LayoutElementBuilders.FontStyle getFontStyle();
+    method public float getLineHeight();
+    method public int getMaxLines();
+    method public androidx.wear.protolayout.ModifiersBuilders.Modifiers getModifiers();
+    method public int getMultilineAlignment();
+    method public int getOverflow();
+    method public androidx.wear.protolayout.TypeBuilders.StringProp getText();
+    method public int getWeight();
+    method public boolean isItalic();
+    method public boolean isUnderline();
+  }
+
+  public static final class Text.Builder {
+    ctor public Text.Builder(android.content.Context, androidx.wear.protolayout.TypeBuilders.StringProp, androidx.wear.protolayout.TypeBuilders.StringLayoutConstraint);
+    ctor public Text.Builder(android.content.Context, String);
+    method public androidx.wear.protolayout.material.Text build();
+    method public androidx.wear.protolayout.material.Text.Builder setColor(androidx.wear.protolayout.ColorBuilders.ColorProp);
+    method public androidx.wear.protolayout.material.Text.Builder setItalic(boolean);
+    method public androidx.wear.protolayout.material.Text.Builder setMaxLines(@IntRange(from=1) int);
+    method public androidx.wear.protolayout.material.Text.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.Modifiers);
+    method public androidx.wear.protolayout.material.Text.Builder setMultilineAlignment(int);
+    method public androidx.wear.protolayout.material.Text.Builder setOverflow(int);
+    method public androidx.wear.protolayout.material.Text.Builder setScalable(boolean);
+    method public androidx.wear.protolayout.material.Text.Builder setTypography(int);
+    method public androidx.wear.protolayout.material.Text.Builder setUnderline(boolean);
+    method public androidx.wear.protolayout.material.Text.Builder setWeight(int);
+  }
+
+  public class TitleChip implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.TitleChip? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.ChipColors getChipColors();
+    method public androidx.wear.protolayout.ModifiersBuilders.Clickable getClickable();
+    method public androidx.wear.protolayout.TypeBuilders.StringProp? getContentDescription();
+    method public int getHorizontalAlignment();
+    method public String? getIconContent();
+    method public String getText();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension getWidth();
+  }
+
+  public static final class TitleChip.Builder {
+    ctor public TitleChip.Builder(android.content.Context, String, androidx.wear.protolayout.ModifiersBuilders.Clickable, androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method public androidx.wear.protolayout.material.TitleChip build();
+    method public androidx.wear.protolayout.material.TitleChip.Builder setChipColors(androidx.wear.protolayout.material.ChipColors);
+    method public androidx.wear.protolayout.material.TitleChip.Builder setContentDescription(androidx.wear.protolayout.TypeBuilders.StringProp);
+    method public androidx.wear.protolayout.material.TitleChip.Builder setContentDescription(CharSequence);
+    method public androidx.wear.protolayout.material.TitleChip.Builder setHorizontalAlignment(int);
+    method public androidx.wear.protolayout.material.TitleChip.Builder setIconContent(String);
+    method public androidx.wear.protolayout.material.TitleChip.Builder setWidth(androidx.wear.protolayout.DimensionBuilders.ContainerDimension);
+    method public androidx.wear.protolayout.material.TitleChip.Builder setWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  public class Typography {
+    field public static final int TYPOGRAPHY_BODY1 = 7; // 0x7
+    field public static final int TYPOGRAPHY_BODY2 = 8; // 0x8
+    field public static final int TYPOGRAPHY_BUTTON = 9; // 0x9
+    field public static final int TYPOGRAPHY_CAPTION1 = 10; // 0xa
+    field public static final int TYPOGRAPHY_CAPTION2 = 11; // 0xb
+    field public static final int TYPOGRAPHY_CAPTION3 = 12; // 0xc
+    field public static final int TYPOGRAPHY_DISPLAY1 = 1; // 0x1
+    field public static final int TYPOGRAPHY_DISPLAY2 = 2; // 0x2
+    field public static final int TYPOGRAPHY_DISPLAY3 = 3; // 0x3
+    field public static final int TYPOGRAPHY_TITLE1 = 4; // 0x4
+    field public static final int TYPOGRAPHY_TITLE2 = 5; // 0x5
+    field public static final int TYPOGRAPHY_TITLE3 = 6; // 0x6
+  }
+
+}
+
+package androidx.wear.protolayout.material.layouts {
+
+  public class EdgeContentLayout implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.layouts.EdgeContentLayout? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getContent();
+    method @Dimension(unit=androidx.annotation.Dimension.DP) public float getContentAndSecondaryLabelSpacing();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getEdgeContent();
+    method public float getEdgeContentThickness();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getPrimaryLabelTextContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getSecondaryLabelTextContent();
+    method public boolean isEdgeContentBehindAllOtherContent();
+    method public boolean isResponsiveContentInsetEnabled();
+  }
+
+  public static final class EdgeContentLayout.Builder {
+    ctor public EdgeContentLayout.Builder(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout build();
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setContentAndSecondaryLabelSpacing(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setEdgeContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setEdgeContentBehindAllOtherContent(boolean);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setEdgeContentThickness(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setPrimaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setResponsiveContentInsetEnabled(boolean);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setSecondaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+  }
+
+  public class LayoutDefaults {
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp DEFAULT_LARGE_VERTICAL_SPACER_HEIGHT;
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp DEFAULT_VERTICAL_SPACER_HEIGHT;
+    field public static final float EDGE_CONTENT_LAYOUT_PADDING_ABOVE_MAIN_CONTENT_DP = 6.0f;
+    field public static final float EDGE_CONTENT_LAYOUT_PADDING_BELOW_MAIN_CONTENT_DP = 8.0f;
+    field @Deprecated public static final int MULTI_BUTTON_MAX_NUMBER = 7; // 0x7
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp MULTI_SLOT_LAYOUT_HORIZONTAL_SPACER_WIDTH;
+  }
+
+  public static final class LayoutDefaults.MultiButtonLayoutDefaults {
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp BUTTON_SIZE_FOR_1_BUTTON;
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp BUTTON_SIZE_FOR_2_BUTTONS;
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp BUTTON_SIZE_FOR_3_PLUS_BUTTONS;
+    field public static final int MAX_BUTTONS = 7; // 0x7
+  }
+
+  public class MultiButtonLayout implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.layouts.MultiButtonLayout? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public java.util.List<androidx.wear.protolayout.LayoutElementBuilders.LayoutElement!> getButtonContents();
+    method public int getFiveButtonDistribution();
+    field public static final int FIVE_BUTTON_DISTRIBUTION_BOTTOM_HEAVY = 2; // 0x2
+    field public static final int FIVE_BUTTON_DISTRIBUTION_TOP_HEAVY = 1; // 0x1
+  }
+
+  public static final class MultiButtonLayout.Builder {
+    ctor public MultiButtonLayout.Builder();
+    method public androidx.wear.protolayout.material.layouts.MultiButtonLayout.Builder addButtonContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.MultiButtonLayout build();
+    method public androidx.wear.protolayout.material.layouts.MultiButtonLayout.Builder setFiveButtonDistribution(int);
+  }
+
+  public class MultiSlotLayout implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.layouts.MultiSlotLayout? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method @Dimension(unit=androidx.annotation.Dimension.DP) public float getHorizontalSpacerWidth();
+    method public java.util.List<androidx.wear.protolayout.LayoutElementBuilders.LayoutElement!> getSlotContents();
+  }
+
+  public static final class MultiSlotLayout.Builder {
+    ctor public MultiSlotLayout.Builder();
+    method public androidx.wear.protolayout.material.layouts.MultiSlotLayout.Builder addSlotContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.MultiSlotLayout build();
+    method public androidx.wear.protolayout.material.layouts.MultiSlotLayout.Builder setHorizontalSpacerWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  public class PrimaryLayout implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.layouts.PrimaryLayout? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getPrimaryChipContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getPrimaryLabelTextContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getSecondaryLabelTextContent();
+    method @Dimension(unit=androidx.annotation.Dimension.DP) public float getVerticalSpacerHeight();
+    method public boolean isResponsiveContentInsetEnabled();
+  }
+
+  public static final class PrimaryLayout.Builder {
+    ctor public PrimaryLayout.Builder(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout build();
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder setContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder setPrimaryChipContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder setPrimaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder setResponsiveContentInsetEnabled(boolean);
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder setSecondaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder setVerticalSpacerHeight(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+}
+
diff --git a/wear/protolayout/protolayout-material/api/res-1.2.0-beta01.txt b/wear/protolayout/protolayout-material/api/res-1.2.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wear/protolayout/protolayout-material/api/res-1.2.0-beta01.txt
diff --git a/wear/protolayout/protolayout-material/api/restricted_1.2.0-beta01.txt b/wear/protolayout/protolayout-material/api/restricted_1.2.0-beta01.txt
new file mode 100644
index 0000000..c51a973
--- /dev/null
+++ b/wear/protolayout/protolayout-material/api/restricted_1.2.0-beta01.txt
@@ -0,0 +1,337 @@
+// Signature format: 4.0
+package androidx.wear.protolayout.material {
+
+  public class Button implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.Button? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.ButtonColors getButtonColors();
+    method public androidx.wear.protolayout.ModifiersBuilders.Clickable getClickable();
+    method public androidx.wear.protolayout.TypeBuilders.StringProp? getContentDescription();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getCustomContent();
+    method public String? getIconContent();
+    method public String? getImageContent();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension getSize();
+    method public String? getTextContent();
+  }
+
+  public static final class Button.Builder {
+    ctor public Button.Builder(android.content.Context, androidx.wear.protolayout.ModifiersBuilders.Clickable);
+    method public androidx.wear.protolayout.material.Button build();
+    method public androidx.wear.protolayout.material.Button.Builder setButtonColors(androidx.wear.protolayout.material.ButtonColors);
+    method public androidx.wear.protolayout.material.Button.Builder setContentDescription(androidx.wear.protolayout.TypeBuilders.StringProp);
+    method public androidx.wear.protolayout.material.Button.Builder setContentDescription(CharSequence);
+    method public androidx.wear.protolayout.material.Button.Builder setCustomContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.Button.Builder setIconContent(String);
+    method public androidx.wear.protolayout.material.Button.Builder setIconContent(String, androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method public androidx.wear.protolayout.material.Button.Builder setImageContent(String);
+    method public androidx.wear.protolayout.material.Button.Builder setSize(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method public androidx.wear.protolayout.material.Button.Builder setSize(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method public androidx.wear.protolayout.material.Button.Builder setTextContent(String);
+    method public androidx.wear.protolayout.material.Button.Builder setTextContent(String, int);
+  }
+
+  public class ButtonColors {
+    ctor public ButtonColors(androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp);
+    ctor public ButtonColors(@ColorInt int, @ColorInt int);
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getBackgroundColor();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getContentColor();
+    method public static androidx.wear.protolayout.material.ButtonColors primaryButtonColors(androidx.wear.protolayout.material.Colors);
+    method public static androidx.wear.protolayout.material.ButtonColors secondaryButtonColors(androidx.wear.protolayout.material.Colors);
+  }
+
+  public class ButtonDefaults {
+    method public static androidx.wear.protolayout.DimensionBuilders.DpProp recommendedIconSize(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method public static androidx.wear.protolayout.DimensionBuilders.DpProp recommendedIconSize(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp DEFAULT_SIZE;
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp EXTRA_LARGE_SIZE;
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp LARGE_SIZE;
+    field public static final androidx.wear.protolayout.material.ButtonColors PRIMARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ButtonColors SECONDARY_COLORS;
+  }
+
+  public class Chip implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.Chip? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.ChipColors getChipColors();
+    method public androidx.wear.protolayout.ModifiersBuilders.Clickable getClickable();
+    method public androidx.wear.protolayout.TypeBuilders.StringProp? getContentDescription();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getCustomContent();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension getHeight();
+    method public int getHorizontalAlignment();
+    method public String? getIconContent();
+    method public String? getPrimaryLabelContent();
+    method public String? getSecondaryLabelContent();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension getWidth();
+  }
+
+  public static final class Chip.Builder {
+    ctor public Chip.Builder(android.content.Context, androidx.wear.protolayout.ModifiersBuilders.Clickable, androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method public androidx.wear.protolayout.material.Chip build();
+    method public androidx.wear.protolayout.material.Chip.Builder setChipColors(androidx.wear.protolayout.material.ChipColors);
+    method public androidx.wear.protolayout.material.Chip.Builder setContentDescription(androidx.wear.protolayout.TypeBuilders.StringProp);
+    method public androidx.wear.protolayout.material.Chip.Builder setContentDescription(CharSequence);
+    method public androidx.wear.protolayout.material.Chip.Builder setCustomContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.Chip.Builder setHorizontalAlignment(int);
+    method public androidx.wear.protolayout.material.Chip.Builder setIconContent(String);
+    method public androidx.wear.protolayout.material.Chip.Builder setPrimaryLabelContent(String);
+    method public androidx.wear.protolayout.material.Chip.Builder setSecondaryLabelContent(String);
+    method public androidx.wear.protolayout.material.Chip.Builder setWidth(androidx.wear.protolayout.DimensionBuilders.ContainerDimension);
+    method public androidx.wear.protolayout.material.Chip.Builder setWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  public class ChipColors {
+    ctor public ChipColors(androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp);
+    ctor public ChipColors(androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp);
+    ctor public ChipColors(@ColorInt int, @ColorInt int);
+    ctor public ChipColors(@ColorInt int, @ColorInt int, @ColorInt int, @ColorInt int);
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getBackgroundColor();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getContentColor();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getIconColor();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getSecondaryContentColor();
+    method public static androidx.wear.protolayout.material.ChipColors primaryChipColors(androidx.wear.protolayout.material.Colors);
+    method public static androidx.wear.protolayout.material.ChipColors secondaryChipColors(androidx.wear.protolayout.material.Colors);
+  }
+
+  public class ChipDefaults {
+    field public static final androidx.wear.protolayout.material.ChipColors COMPACT_PRIMARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ChipColors COMPACT_SECONDARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ChipColors PRIMARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ChipColors SECONDARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ChipColors TITLE_PRIMARY_COLORS;
+    field public static final androidx.wear.protolayout.material.ChipColors TITLE_SECONDARY_COLORS;
+  }
+
+  public class CircularProgressIndicator implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.CircularProgressIndicator? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.ProgressIndicatorColors getCircularProgressIndicatorColors();
+    method public androidx.wear.protolayout.TypeBuilders.StringProp? getContentDescription();
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp getEndAngle();
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp getProgress();
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp getStartAngle();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp getStrokeWidth();
+    method public boolean isOuterMarginApplied();
+  }
+
+  public static final class CircularProgressIndicator.Builder {
+    ctor public CircularProgressIndicator.Builder();
+    method public androidx.wear.protolayout.material.CircularProgressIndicator build();
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setCircularProgressIndicatorColors(androidx.wear.protolayout.material.ProgressIndicatorColors);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setContentDescription(androidx.wear.protolayout.TypeBuilders.StringProp);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setContentDescription(CharSequence);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setEndAngle(float);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setOuterMarginApplied(boolean);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setProgress(androidx.wear.protolayout.TypeBuilders.FloatProp);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setProgress(@FloatRange(from=0, to=1) float);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setStartAngle(float);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setStrokeWidth(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setStrokeWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  public class Colors {
+    ctor public Colors(@ColorInt int, @ColorInt int, @ColorInt int, @ColorInt int);
+    method @ColorInt public int getOnPrimary();
+    method @ColorInt public int getOnSurface();
+    method @ColorInt public int getPrimary();
+    method @ColorInt public int getSurface();
+    field public static final androidx.wear.protolayout.material.Colors DEFAULT;
+  }
+
+  public class CompactChip implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.CompactChip? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.ChipColors getChipColors();
+    method public androidx.wear.protolayout.ModifiersBuilders.Clickable getClickable();
+    method public androidx.wear.protolayout.TypeBuilders.StringProp? getContentDescription();
+    method public String? getIconContent();
+    method public String getText();
+    method public boolean hasText();
+  }
+
+  public static final class CompactChip.Builder {
+    ctor public CompactChip.Builder(android.content.Context, androidx.wear.protolayout.ModifiersBuilders.Clickable, androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    ctor public CompactChip.Builder(android.content.Context, String, androidx.wear.protolayout.ModifiersBuilders.Clickable, androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method public androidx.wear.protolayout.material.CompactChip build();
+    method public androidx.wear.protolayout.material.CompactChip.Builder setChipColors(androidx.wear.protolayout.material.ChipColors);
+    method public androidx.wear.protolayout.material.CompactChip.Builder setContentDescription(androidx.wear.protolayout.TypeBuilders.StringProp);
+    method public androidx.wear.protolayout.material.CompactChip.Builder setContentDescription(CharSequence);
+    method public androidx.wear.protolayout.material.CompactChip.Builder setIconContent(String);
+    method public androidx.wear.protolayout.material.CompactChip.Builder setTextContent(String);
+  }
+
+  public class ProgressIndicatorColors {
+    ctor public ProgressIndicatorColors(androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp);
+    ctor public ProgressIndicatorColors(@ColorInt int, @ColorInt int);
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getIndicatorColor();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getTrackColor();
+    method public static androidx.wear.protolayout.material.ProgressIndicatorColors progressIndicatorColors(androidx.wear.protolayout.material.Colors);
+  }
+
+  public class ProgressIndicatorDefaults {
+    field public static final androidx.wear.protolayout.material.ProgressIndicatorColors DEFAULT_COLORS;
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp DEFAULT_STROKE_WIDTH;
+    field public static final float GAP_END_ANGLE = 156.1f;
+    field public static final float GAP_START_ANGLE = -156.1f;
+  }
+
+  public class Text implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.Text? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getColor();
+    method public androidx.wear.protolayout.LayoutElementBuilders.FontStyle getFontStyle();
+    method public float getLineHeight();
+    method public int getMaxLines();
+    method public androidx.wear.protolayout.ModifiersBuilders.Modifiers getModifiers();
+    method public int getMultilineAlignment();
+    method public int getOverflow();
+    method public androidx.wear.protolayout.TypeBuilders.StringProp getText();
+    method public int getWeight();
+    method public boolean isItalic();
+    method public boolean isUnderline();
+  }
+
+  public static final class Text.Builder {
+    ctor public Text.Builder(android.content.Context, androidx.wear.protolayout.TypeBuilders.StringProp, androidx.wear.protolayout.TypeBuilders.StringLayoutConstraint);
+    ctor public Text.Builder(android.content.Context, String);
+    method public androidx.wear.protolayout.material.Text build();
+    method public androidx.wear.protolayout.material.Text.Builder setColor(androidx.wear.protolayout.ColorBuilders.ColorProp);
+    method public androidx.wear.protolayout.material.Text.Builder setItalic(boolean);
+    method public androidx.wear.protolayout.material.Text.Builder setMaxLines(@IntRange(from=1) int);
+    method public androidx.wear.protolayout.material.Text.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.Modifiers);
+    method public androidx.wear.protolayout.material.Text.Builder setMultilineAlignment(int);
+    method public androidx.wear.protolayout.material.Text.Builder setOverflow(int);
+    method public androidx.wear.protolayout.material.Text.Builder setScalable(boolean);
+    method public androidx.wear.protolayout.material.Text.Builder setTypography(int);
+    method public androidx.wear.protolayout.material.Text.Builder setUnderline(boolean);
+    method public androidx.wear.protolayout.material.Text.Builder setWeight(int);
+  }
+
+  public class TitleChip implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.TitleChip? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.ChipColors getChipColors();
+    method public androidx.wear.protolayout.ModifiersBuilders.Clickable getClickable();
+    method public androidx.wear.protolayout.TypeBuilders.StringProp? getContentDescription();
+    method public int getHorizontalAlignment();
+    method public String? getIconContent();
+    method public String getText();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension getWidth();
+  }
+
+  public static final class TitleChip.Builder {
+    ctor public TitleChip.Builder(android.content.Context, String, androidx.wear.protolayout.ModifiersBuilders.Clickable, androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method public androidx.wear.protolayout.material.TitleChip build();
+    method public androidx.wear.protolayout.material.TitleChip.Builder setChipColors(androidx.wear.protolayout.material.ChipColors);
+    method public androidx.wear.protolayout.material.TitleChip.Builder setContentDescription(androidx.wear.protolayout.TypeBuilders.StringProp);
+    method public androidx.wear.protolayout.material.TitleChip.Builder setContentDescription(CharSequence);
+    method public androidx.wear.protolayout.material.TitleChip.Builder setHorizontalAlignment(int);
+    method public androidx.wear.protolayout.material.TitleChip.Builder setIconContent(String);
+    method public androidx.wear.protolayout.material.TitleChip.Builder setWidth(androidx.wear.protolayout.DimensionBuilders.ContainerDimension);
+    method public androidx.wear.protolayout.material.TitleChip.Builder setWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  public class Typography {
+    field public static final int TYPOGRAPHY_BODY1 = 7; // 0x7
+    field public static final int TYPOGRAPHY_BODY2 = 8; // 0x8
+    field public static final int TYPOGRAPHY_BUTTON = 9; // 0x9
+    field public static final int TYPOGRAPHY_CAPTION1 = 10; // 0xa
+    field public static final int TYPOGRAPHY_CAPTION2 = 11; // 0xb
+    field public static final int TYPOGRAPHY_CAPTION3 = 12; // 0xc
+    field public static final int TYPOGRAPHY_DISPLAY1 = 1; // 0x1
+    field public static final int TYPOGRAPHY_DISPLAY2 = 2; // 0x2
+    field public static final int TYPOGRAPHY_DISPLAY3 = 3; // 0x3
+    field public static final int TYPOGRAPHY_TITLE1 = 4; // 0x4
+    field public static final int TYPOGRAPHY_TITLE2 = 5; // 0x5
+    field public static final int TYPOGRAPHY_TITLE3 = 6; // 0x6
+  }
+
+}
+
+package androidx.wear.protolayout.material.layouts {
+
+  public class EdgeContentLayout implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.layouts.EdgeContentLayout? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getContent();
+    method @Dimension(unit=androidx.annotation.Dimension.DP) public float getContentAndSecondaryLabelSpacing();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getEdgeContent();
+    method public float getEdgeContentThickness();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getPrimaryLabelTextContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getSecondaryLabelTextContent();
+    method public boolean isEdgeContentBehindAllOtherContent();
+    method public boolean isResponsiveContentInsetEnabled();
+  }
+
+  public static final class EdgeContentLayout.Builder {
+    ctor public EdgeContentLayout.Builder(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout build();
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setContentAndSecondaryLabelSpacing(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setEdgeContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setEdgeContentBehindAllOtherContent(boolean);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setEdgeContentThickness(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setPrimaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setResponsiveContentInsetEnabled(boolean);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setSecondaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+  }
+
+  public class LayoutDefaults {
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp DEFAULT_LARGE_VERTICAL_SPACER_HEIGHT;
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp DEFAULT_VERTICAL_SPACER_HEIGHT;
+    field public static final float EDGE_CONTENT_LAYOUT_PADDING_ABOVE_MAIN_CONTENT_DP = 6.0f;
+    field public static final float EDGE_CONTENT_LAYOUT_PADDING_BELOW_MAIN_CONTENT_DP = 8.0f;
+    field @Deprecated public static final int MULTI_BUTTON_MAX_NUMBER = 7; // 0x7
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp MULTI_SLOT_LAYOUT_HORIZONTAL_SPACER_WIDTH;
+  }
+
+  public static final class LayoutDefaults.MultiButtonLayoutDefaults {
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp BUTTON_SIZE_FOR_1_BUTTON;
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp BUTTON_SIZE_FOR_2_BUTTONS;
+    field public static final androidx.wear.protolayout.DimensionBuilders.DpProp BUTTON_SIZE_FOR_3_PLUS_BUTTONS;
+    field public static final int MAX_BUTTONS = 7; // 0x7
+  }
+
+  public class MultiButtonLayout implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.layouts.MultiButtonLayout? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public java.util.List<androidx.wear.protolayout.LayoutElementBuilders.LayoutElement!> getButtonContents();
+    method public int getFiveButtonDistribution();
+    field public static final int FIVE_BUTTON_DISTRIBUTION_BOTTOM_HEAVY = 2; // 0x2
+    field public static final int FIVE_BUTTON_DISTRIBUTION_TOP_HEAVY = 1; // 0x1
+  }
+
+  public static final class MultiButtonLayout.Builder {
+    ctor public MultiButtonLayout.Builder();
+    method public androidx.wear.protolayout.material.layouts.MultiButtonLayout.Builder addButtonContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.MultiButtonLayout build();
+    method public androidx.wear.protolayout.material.layouts.MultiButtonLayout.Builder setFiveButtonDistribution(int);
+  }
+
+  public class MultiSlotLayout implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.layouts.MultiSlotLayout? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method @Dimension(unit=androidx.annotation.Dimension.DP) public float getHorizontalSpacerWidth();
+    method public java.util.List<androidx.wear.protolayout.LayoutElementBuilders.LayoutElement!> getSlotContents();
+  }
+
+  public static final class MultiSlotLayout.Builder {
+    ctor public MultiSlotLayout.Builder();
+    method public androidx.wear.protolayout.material.layouts.MultiSlotLayout.Builder addSlotContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.MultiSlotLayout build();
+    method public androidx.wear.protolayout.material.layouts.MultiSlotLayout.Builder setHorizontalSpacerWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  public class PrimaryLayout implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public static androidx.wear.protolayout.material.layouts.PrimaryLayout? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getPrimaryChipContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getPrimaryLabelTextContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getSecondaryLabelTextContent();
+    method @Dimension(unit=androidx.annotation.Dimension.DP) public float getVerticalSpacerHeight();
+    method public boolean isResponsiveContentInsetEnabled();
+  }
+
+  public static final class PrimaryLayout.Builder {
+    ctor public PrimaryLayout.Builder(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout build();
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder setContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder setPrimaryChipContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder setPrimaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder setResponsiveContentInsetEnabled(boolean);
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder setSecondaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder setVerticalSpacerHeight(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+}
+
diff --git a/wear/protolayout/protolayout-material3/build.gradle b/wear/protolayout/protolayout-material3/build.gradle
index 829fab6..1e3a8a2 100644
--- a/wear/protolayout/protolayout-material3/build.gradle
+++ b/wear/protolayout/protolayout-material3/build.gradle
@@ -30,7 +30,7 @@
 
 dependencies {
     annotationProcessor(libs.nullaway)
-    // Add dependencies here
+    api(project(":wear:protolayout:protolayout"))
 }
 
 android {
diff --git a/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/tokens/ColorTokens.java b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/tokens/ColorTokens.java
new file mode 100644
index 0000000..b31de95
--- /dev/null
+++ b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/tokens/ColorTokens.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// VERSION: v0_64
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+package androidx.wear.protolayout.material3.tokens;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+
+/**
+ * System color palette provides colors for Material 3 on Wear OS. Only dark theme colors are
+ * provided as we always design on black.
+ */
+@RestrictTo(Scope.LIBRARY)
+public final class ColorTokens {
+  @ColorInt public static final int BACKGROUND = PaletteTokens.NEUTRAL0;
+  @ColorInt public static final int ERROR = PaletteTokens.ERROR80;
+  @ColorInt public static final int ERROR_CONTAINER = PaletteTokens.ERROR70;
+  @ColorInt public static final int ON_BACKGROUND = PaletteTokens.NEUTRAL100;
+  @ColorInt public static final int ON_ERROR = PaletteTokens.ERROR20;
+  @ColorInt public static final int ON_ERROR_CONTAINER = PaletteTokens.ERROR10;
+  @ColorInt public static final int ON_PRIMARY = PaletteTokens.PRIMARY10;
+  @ColorInt public static final int ON_PRIMARY_CONTAINER = PaletteTokens.PRIMARY90;
+  @ColorInt public static final int ON_SECONDARY = PaletteTokens.SECONDARY10;
+  @ColorInt public static final int ON_SECONDARY_CONTAINER = PaletteTokens.SECONDARY90;
+  @ColorInt public static final int ON_SURFACE = PaletteTokens.NEUTRAL95;
+  @ColorInt public static final int ON_SURFACE_VARIANT = PaletteTokens.NEUTRAL_VARIANT80;
+  @ColorInt public static final int ON_TERTIARY = PaletteTokens.TERTIARY10;
+  @ColorInt public static final int ON_TERTIARY_CONTAINER = PaletteTokens.TERTIARY90;
+  @ColorInt public static final int OUTLINE = PaletteTokens.NEUTRAL_VARIANT60;
+  @ColorInt public static final int OUTLINE_VARIANT = PaletteTokens.NEUTRAL_VARIANT40;
+  @ColorInt public static final int PRIMARY = PaletteTokens.PRIMARY90;
+  @ColorInt public static final int PRIMARY_CONTAINER = PaletteTokens.PRIMARY30;
+  @ColorInt public static final int PRIMARY_DIM = PaletteTokens.PRIMARY80;
+  @ColorInt public static final int SECONDARY = PaletteTokens.SECONDARY90;
+  @ColorInt public static final int SECONDARY_CONTAINER = PaletteTokens.SECONDARY30;
+  @ColorInt public static final int SECONDARY_DIM = PaletteTokens.SECONDARY80;
+  @ColorInt public static final int SURFACE_CONTAINER = PaletteTokens.NEUTRAL20;
+  @ColorInt public static final int SURFACE_CONTAINER_HIGH = PaletteTokens.NEUTRAL30;
+  @ColorInt public static final int SURFACE_CONTAINER_LOW = PaletteTokens.NEUTRAL15;
+  @ColorInt public static final int TERTIARY = PaletteTokens.TERTIARY90;
+  @ColorInt public static final int TERTIARY_CONTAINER = PaletteTokens.TERTIARY30;
+  @ColorInt public static final int TERTIARY_DIM = PaletteTokens.TERTIARY80;
+
+  private ColorTokens() {}
+}
diff --git a/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/tokens/PaletteTokens.java b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/tokens/PaletteTokens.java
new file mode 100644
index 0000000..ad55490f
--- /dev/null
+++ b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/tokens/PaletteTokens.java
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// VERSION: v0_64
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+package androidx.wear.protolayout.material3.tokens;
+
+import android.graphics.Color;
+import androidx.annotation.ColorInt;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+
+/** Reference color palette. */
+@RestrictTo(Scope.LIBRARY)
+public final class PaletteTokens {
+  @ColorInt public static final int ERROR0 = Color.rgb(/* red= */ 0, /* green= */ 0, /* blue= */ 0);
+
+  @ColorInt
+  public static final int ERROR10 = Color.rgb(/* red= */ 65, /* green= */ 14, /* blue= */ 11);
+
+  @ColorInt
+  public static final int ERROR100 = Color.rgb(/* red= */ 255, /* green= */ 255, /* blue= */ 255);
+
+  @ColorInt
+  public static final int ERROR20 = Color.rgb(/* red= */ 96, /* green= */ 20, /* blue= */ 16);
+
+  @ColorInt
+  public static final int ERROR30 = Color.rgb(/* red= */ 140, /* green= */ 29, /* blue= */ 24);
+
+  @ColorInt
+  public static final int ERROR40 = Color.rgb(/* red= */ 179, /* green= */ 38, /* blue= */ 30);
+
+  @ColorInt
+  public static final int ERROR5 = Color.rgb(/* red= */ 33, /* green= */ 7, /* blue= */ 6);
+
+  @ColorInt
+  public static final int ERROR50 = Color.rgb(/* red= */ 220, /* green= */ 54, /* blue= */ 46);
+
+  @ColorInt
+  public static final int ERROR60 = Color.rgb(/* red= */ 228, /* green= */ 105, /* blue= */ 98);
+
+  @ColorInt
+  public static final int ERROR65 = Color.rgb(/* red= */ 232, /* green= */ 126, /* blue= */ 120);
+
+  @ColorInt
+  public static final int ERROR70 = Color.rgb(/* red= */ 236, /* green= */ 146, /* blue= */ 142);
+
+  @ColorInt
+  public static final int ERROR80 = Color.rgb(/* red= */ 242, /* green= */ 184, /* blue= */ 181);
+
+  @ColorInt
+  public static final int ERROR85 = Color.rgb(/* red= */ 245, /* green= */ 203, /* blue= */ 200);
+
+  @ColorInt
+  public static final int ERROR90 = Color.rgb(/* red= */ 249, /* green= */ 222, /* blue= */ 220);
+
+  @ColorInt
+  public static final int ERROR95 = Color.rgb(/* red= */ 252, /* green= */ 238, /* blue= */ 238);
+
+  @ColorInt
+  public static final int NEUTRAL0 = Color.rgb(/* red= */ 0, /* green= */ 0, /* blue= */ 0);
+
+  @ColorInt
+  public static final int NEUTRAL10 = Color.rgb(/* red= */ 29, /* green= */ 26, /* blue= */ 38);
+
+  @ColorInt
+  public static final int NEUTRAL100 = Color.rgb(/* red= */ 255, /* green= */ 255, /* blue= */ 255);
+
+  @ColorInt
+  public static final int NEUTRAL15 = Color.rgb(/* red= */ 39, /* green= */ 36, /* blue= */ 48);
+
+  @ColorInt
+  public static final int NEUTRAL20 = Color.rgb(/* red= */ 51, /* green= */ 46, /* blue= */ 60);
+
+  @ColorInt
+  public static final int NEUTRAL30 = Color.rgb(/* red= */ 73, /* green= */ 68, /* blue= */ 83);
+
+  @ColorInt
+  public static final int NEUTRAL40 = Color.rgb(/* red= */ 97, /* green= */ 92, /* blue= */ 107);
+
+  @ColorInt
+  public static final int NEUTRAL50 = Color.rgb(/* red= */ 122, /* green= */ 116, /* blue= */ 132);
+
+  @ColorInt
+  public static final int NEUTRAL60 = Color.rgb(/* red= */ 148, /* green= */ 142, /* blue= */ 159);
+
+  @ColorInt
+  public static final int NEUTRAL70 = Color.rgb(/* red= */ 175, /* green= */ 168, /* blue= */ 185);
+
+  @ColorInt
+  public static final int NEUTRAL80 = Color.rgb(/* red= */ 203, /* green= */ 195, /* blue= */ 213);
+
+  @ColorInt
+  public static final int NEUTRAL90 = Color.rgb(/* red= */ 232, /* green= */ 223, /* blue= */ 242);
+
+  @ColorInt
+  public static final int NEUTRAL95 = Color.rgb(/* red= */ 246, /* green= */ 237, /* blue= */ 255);
+
+  @ColorInt
+  public static final int NEUTRAL_VARIANT0 = Color.rgb(/* red= */ 0, /* green= */ 0, /* blue= */ 0);
+
+  @ColorInt
+  public static final int NEUTRAL_VARIANT10 =
+      Color.rgb(/* red= */ 29, /* green= */ 26, /* blue= */ 35);
+
+  @ColorInt
+  public static final int NEUTRAL_VARIANT100 =
+      Color.rgb(/* red= */ 255, /* green= */ 255, /* blue= */ 255);
+
+  @ColorInt
+  public static final int NEUTRAL_VARIANT20 =
+      Color.rgb(/* red= */ 50, /* green= */ 47, /* blue= */ 56);
+
+  @ColorInt
+  public static final int NEUTRAL_VARIANT30 =
+      Color.rgb(/* red= */ 73, /* green= */ 69, /* blue= */ 79);
+
+  @ColorInt
+  public static final int NEUTRAL_VARIANT40 =
+      Color.rgb(/* red= */ 97, /* green= */ 93, /* blue= */ 103);
+
+  @ColorInt
+  public static final int NEUTRAL_VARIANT50 =
+      Color.rgb(/* red= */ 122, /* green= */ 117, /* blue= */ 128);
+
+  @ColorInt
+  public static final int NEUTRAL_VARIANT60 =
+      Color.rgb(/* red= */ 148, /* green= */ 143, /* blue= */ 154);
+
+  @ColorInt
+  public static final int NEUTRAL_VARIANT70 =
+      Color.rgb(/* red= */ 175, /* green= */ 169, /* blue= */ 181);
+
+  @ColorInt
+  public static final int NEUTRAL_VARIANT80 =
+      Color.rgb(/* red= */ 202, /* green= */ 196, /* blue= */ 208);
+
+  @ColorInt
+  public static final int NEUTRAL_VARIANT90 =
+      Color.rgb(/* red= */ 231, /* green= */ 224, /* blue= */ 236);
+
+  @ColorInt
+  public static final int NEUTRAL_VARIANT95 =
+      Color.rgb(/* red= */ 245, /* green= */ 238, /* blue= */ 251);
+
+  @ColorInt
+  public static final int PRIMARY0 = Color.rgb(/* red= */ 0, /* green= */ 0, /* blue= */ 0);
+
+  @ColorInt
+  public static final int PRIMARY10 = Color.rgb(/* red= */ 33, /* green= */ 15, /* blue= */ 72);
+
+  @ColorInt
+  public static final int PRIMARY100 = Color.rgb(/* red= */ 255, /* green= */ 255, /* blue= */ 255);
+
+  @ColorInt
+  public static final int PRIMARY20 = Color.rgb(/* red= */ 55, /* green= */ 38, /* blue= */ 94);
+
+  @ColorInt
+  public static final int PRIMARY30 = Color.rgb(/* red= */ 77, /* green= */ 61, /* blue= */ 118);
+
+  @ColorInt
+  public static final int PRIMARY40 = Color.rgb(/* red= */ 102, /* green= */ 85, /* blue= */ 144);
+
+  @ColorInt
+  public static final int PRIMARY50 = Color.rgb(/* red= */ 127, /* green= */ 109, /* blue= */ 170);
+
+  @ColorInt
+  public static final int PRIMARY60 = Color.rgb(/* red= */ 153, /* green= */ 135, /* blue= */ 198);
+
+  @ColorInt
+  public static final int PRIMARY70 = Color.rgb(/* red= */ 180, /* green= */ 161, /* blue= */ 226);
+
+  @ColorInt
+  public static final int PRIMARY80 = Color.rgb(/* red= */ 208, /* green= */ 188, /* blue= */ 255);
+
+  @ColorInt
+  public static final int PRIMARY90 = Color.rgb(/* red= */ 233, /* green= */ 221, /* blue= */ 255);
+
+  @ColorInt
+  public static final int PRIMARY95 = Color.rgb(/* red= */ 246, /* green= */ 237, /* blue= */ 255);
+
+  @ColorInt
+  public static final int SECONDARY0 = Color.rgb(/* red= */ 0, /* green= */ 0, /* blue= */ 0);
+
+  @ColorInt
+  public static final int SECONDARY10 = Color.rgb(/* red= */ 30, /* green= */ 24, /* blue= */ 46);
+
+  @ColorInt
+  public static final int SECONDARY100 =
+      Color.rgb(/* red= */ 255, /* green= */ 255, /* blue= */ 255);
+
+  @ColorInt
+  public static final int SECONDARY20 = Color.rgb(/* red= */ 51, /* green= */ 45, /* blue= */ 68);
+
+  @ColorInt
+  public static final int SECONDARY30 = Color.rgb(/* red= */ 74, /* green= */ 67, /* blue= */ 91);
+
+  @ColorInt
+  public static final int SECONDARY40 = Color.rgb(/* red= */ 98, /* green= */ 90, /* blue= */ 116);
+
+  @ColorInt
+  public static final int SECONDARY50 =
+      Color.rgb(/* red= */ 123, /* green= */ 115, /* blue= */ 141);
+
+  @ColorInt
+  public static final int SECONDARY60 =
+      Color.rgb(/* red= */ 150, /* green= */ 140, /* blue= */ 168);
+
+  @ColorInt
+  public static final int SECONDARY70 =
+      Color.rgb(/* red= */ 177, /* green= */ 167, /* blue= */ 195);
+
+  @ColorInt
+  public static final int SECONDARY80 =
+      Color.rgb(/* red= */ 204, /* green= */ 194, /* blue= */ 223);
+
+  @ColorInt
+  public static final int SECONDARY90 =
+      Color.rgb(/* red= */ 233, /* green= */ 222, /* blue= */ 252);
+
+  @ColorInt
+  public static final int SECONDARY95 =
+      Color.rgb(/* red= */ 246, /* green= */ 237, /* blue= */ 255);
+
+  @ColorInt
+  public static final int TERTIARY0 = Color.rgb(/* red= */ 0, /* green= */ 0, /* blue= */ 0);
+
+  @ColorInt
+  public static final int TERTIARY10 = Color.rgb(/* red= */ 46, /* green= */ 21, /* blue= */ 0);
+
+  @ColorInt
+  public static final int TERTIARY100 =
+      Color.rgb(/* red= */ 255, /* green= */ 255, /* blue= */ 255);
+
+  @ColorInt
+  public static final int TERTIARY20 = Color.rgb(/* red= */ 76, /* green= */ 39, /* blue= */ 0);
+
+  @ColorInt
+  public static final int TERTIARY30 = Color.rgb(/* red= */ 108, /* green= */ 58, /* blue= */ 3);
+
+  @ColorInt
+  public static final int TERTIARY40 = Color.rgb(/* red= */ 136, /* green= */ 81, /* blue= */ 27);
+
+  @ColorInt
+  public static final int TERTIARY50 = Color.rgb(/* red= */ 165, /* green= */ 105, /* blue= */ 49);
+
+  @ColorInt
+  public static final int TERTIARY60 = Color.rgb(/* red= */ 195, /* green= */ 130, /* blue= */ 72);
+
+  @ColorInt
+  public static final int TERTIARY70 = Color.rgb(/* red= */ 226, /* green= */ 156, /* blue= */ 95);
+
+  @ColorInt
+  public static final int TERTIARY80 = Color.rgb(/* red= */ 255, /* green= */ 183, /* blue= */ 122);
+
+  @ColorInt
+  public static final int TERTIARY90 = Color.rgb(/* red= */ 255, /* green= */ 220, /* blue= */ 194);
+
+  @ColorInt
+  public static final int TERTIARY95 = Color.rgb(/* red= */ 255, /* green= */ 238, /* blue= */ 226);
+
+  private PaletteTokens() {}
+}
diff --git a/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/tokens/ShapeTokens.java b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/tokens/ShapeTokens.java
new file mode 100644
index 0000000..d64da97
--- /dev/null
+++ b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/tokens/ShapeTokens.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// VERSION: v0_64
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+package androidx.wear.protolayout.material3.tokens;
+
+import static androidx.wear.protolayout.DimensionBuilders.dp;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.ModifiersBuilders.Corner;
+
+/** The Material 3 shape system on Wear OS. */
+@RestrictTo(Scope.LIBRARY)
+public final class ShapeTokens {
+
+  @NonNull public static final Corner CORNER_EXTRA_LARGE = roundedCornerShape(36.0f);
+
+  @NonNull public static final Corner CORNER_EXTRA_SMALL = roundedCornerShape(4.0f);
+
+  // Full corner can be achieved by setting a big radius value, which will be clamped by
+  // min(halfWidth, halfHeight).
+  @NonNull public static final Corner CORNER_FULL = roundedCornerShape(99999.0f);
+
+  @NonNull public static final Corner CORNER_LARGE = roundedCornerShape(26.0f);
+
+  @NonNull public static final Corner CORNER_MEDIUM = roundedCornerShape(18.0f);
+
+  @NonNull public static final Corner CORNER_NONE = roundedCornerShape(0.0f);
+
+  @NonNull public static final Corner CORNER_SMALL = roundedCornerShape(8.0f);
+
+  @NonNull
+  private static Corner roundedCornerShape(float sizeDp) {
+    return new Corner.Builder().setRadius(dp(sizeDp)).build();
+  }
+
+  private ShapeTokens() {}
+}
diff --git a/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/tokens/TextStyle.java b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/tokens/TextStyle.java
new file mode 100644
index 0000000..22a3d19
--- /dev/null
+++ b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/tokens/TextStyle.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.protolayout.material3.tokens;
+
+import static androidx.annotation.Dimension.SP;
+import static androidx.wear.protolayout.DimensionBuilders.em;
+import static androidx.wear.protolayout.DimensionBuilders.sp;
+
+import androidx.annotation.Dimension;
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.DimensionBuilders.EmProp;
+import androidx.wear.protolayout.DimensionBuilders.SpProp;
+import androidx.wear.protolayout.LayoutElementBuilders.FontSetting;
+import java.util.ArrayList;
+import java.util.List;
+
+/** Text styling configuration. */
+@RestrictTo(Scope.LIBRARY)
+public class TextStyle {
+  /** Font family, such as "Roboto". */
+  @NonNull public final String fontFamily;
+
+  /** The size of the font, in scaled pixels. */
+  @NonNull public final SpProp size;
+
+  /** The explicit height between lines of text. */
+  @NonNull public final SpProp lineHeight;
+
+  /**
+   * The text letter spacing. Positive numbers increase the space between letters while negative
+   * numbers tighten the space.
+   */
+  @NonNull public final EmProp letterSpacing;
+
+  /** List of {@link FontSetting} option for font, such as weight, width. */
+  @NonNull public final List<FontSetting> fontSettings;
+
+  public TextStyle(
+      @NonNull String fontFamily,
+      @Dimension(unit = SP) float size,
+      @Dimension(unit = SP) float lineHeight,
+      @Dimension(unit = SP) float letterSpacing,
+      @NonNull List<FontSetting> fontSettings) {
+    this.fontFamily = fontFamily;
+    this.size = sp(size);
+    this.lineHeight = sp(lineHeight);
+    this.letterSpacing = letterSpacingSpToEm(letterSpacing, size);
+    this.fontSettings = new ArrayList<>(fontSettings);
+  }
+
+  private static EmProp letterSpacingSpToEm(
+      @Dimension(unit = SP) float letterSpacing, @Dimension(unit = SP) float fontSize) {
+    // When the font size and the font tracking are specified in same unit,
+    // letter spacing in em = tracking value / font size
+    return em(letterSpacing / fontSize);
+  }
+}
diff --git a/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/tokens/TypeScaleTokens.java b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/tokens/TypeScaleTokens.java
new file mode 100644
index 0000000..69f763f
--- /dev/null
+++ b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/tokens/TypeScaleTokens.java
@@ -0,0 +1,356 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// VERSION: v0_64
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+package androidx.wear.protolayout.material3.tokens;
+
+import static androidx.annotation.Dimension.SP;
+
+import androidx.annotation.Dimension;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.LayoutElementBuilders.FontSetting;
+
+/** A list of text style values in Material3 for supporting product needs. */
+@RestrictTo(Scope.LIBRARY)
+public final class TypeScaleTokens {
+
+  public static final String ARC_MEDIUM_FONT_FAMILY = TypefaceTokens.BRAND;
+
+  @Dimension(unit = SP)
+  public static final float ARC_MEDIUM_LINE_HEIGHT = 18.0f;
+
+  @Dimension(unit = SP)
+  public static final float ARC_MEDIUM_SIZE = 15.0f;
+
+  @Dimension(unit = SP)
+  public static final float ARC_MEDIUM_TRACKING = 0.4f;
+
+  public static final FontSetting ARC_MEDIUM_WEIGHT = FontSetting.weight(600);
+
+  public static final FontSetting ARC_MEDIUM_WEIGHT_PROMINENT = FontSetting.weight(800);
+
+  public static final FontSetting ARC_MEDIUM_WIDTH = FontSetting.width(100.0f);
+
+  public static final String ARC_SMALL_FONT_FAMILY = TypefaceTokens.BRAND;
+
+  @Dimension(unit = SP)
+  public static final float ARC_SMALL_LINE_HEIGHT = 16.0f;
+
+  @Dimension(unit = SP)
+  public static final float ARC_SMALL_SIZE = 14.0f;
+
+  @Dimension(unit = SP)
+  public static final float ARC_SMALL_TRACKING = 0.4f;
+
+  public static final FontSetting ARC_SMALL_WEIGHT = FontSetting.weight(560);
+
+  public static final FontSetting ARC_SMALL_WEIGHT_PROMINENT = FontSetting.weight(760);
+
+  public static final FontSetting ARC_SMALL_WIDTH = FontSetting.width(100.0f);
+
+  public static final String BODY_EXTRA_SMALL_FONT_FAMILY = TypefaceTokens.BRAND;
+
+  @Dimension(unit = SP)
+  public static final float BODY_EXTRA_SMALL_LINE_HEIGHT = 12.0f;
+
+  @Dimension(unit = SP)
+  public static final float BODY_EXTRA_SMALL_SIZE = 10.0f;
+
+  @Dimension(unit = SP)
+  public static final float BODY_EXTRA_SMALL_TRACKING = 0.2f;
+
+  public static final FontSetting BODY_EXTRA_SMALL_WEIGHT = FontSetting.weight(500);
+
+  public static final FontSetting BODY_EXTRA_SMALL_WEIGHT_PROMINENT = FontSetting.weight(700);
+
+  public static final FontSetting BODY_EXTRA_SMALL_WIDTH = FontSetting.width(104.0f);
+
+  public static final String BODY_LARGE_FONT_FAMILY = TypefaceTokens.BRAND;
+
+  @Dimension(unit = SP)
+  public static final float BODY_LARGE_LINE_HEIGHT = 18.0f;
+
+  @Dimension(unit = SP)
+  public static final float BODY_LARGE_SIZE = 16.0f;
+
+  @Dimension(unit = SP)
+  public static final float BODY_LARGE_TRACKING = 0.4f;
+
+  public static final FontSetting BODY_LARGE_WEIGHT = FontSetting.weight(450);
+
+  public static final FontSetting BODY_LARGE_WEIGHT_PROMINENT = FontSetting.weight(650);
+
+  public static final FontSetting BODY_LARGE_WIDTH = FontSetting.width(110.0f);
+
+  public static final String BODY_MEDIUM_FONT_FAMILY = TypefaceTokens.BRAND;
+
+  @Dimension(unit = SP)
+  public static final float BODY_MEDIUM_LINE_HEIGHT = 16.0f;
+
+  @Dimension(unit = SP)
+  public static final float BODY_MEDIUM_SIZE = 14.0f;
+
+  @Dimension(unit = SP)
+  public static final float BODY_MEDIUM_TRACKING = 0.4f;
+
+  public static final FontSetting BODY_MEDIUM_WEIGHT = FontSetting.weight(450);
+
+  public static final FontSetting BODY_MEDIUM_WEIGHT_PROMINENT = FontSetting.weight(650);
+
+  public static final FontSetting BODY_MEDIUM_WIDTH = FontSetting.width(110.0f);
+
+  public static final String BODY_SMALL_FONT_FAMILY = TypefaceTokens.BRAND;
+
+  @Dimension(unit = SP)
+  public static final float BODY_SMALL_LINE_HEIGHT = 14.0f;
+
+  @Dimension(unit = SP)
+  public static final float BODY_SMALL_SIZE = 12.0f;
+
+  @Dimension(unit = SP)
+  public static final float BODY_SMALL_TRACKING = 0.4f;
+
+  public static final FontSetting BODY_SMALL_WEIGHT = FontSetting.weight(500);
+
+  public static final FontSetting BODY_SMALL_WEIGHT_PROMINENT = FontSetting.weight(700);
+
+  public static final FontSetting BODY_SMALL_WIDTH = FontSetting.width(110.0f);
+
+  public static final String DISPLAY_LARGE_FONT_FAMILY = TypefaceTokens.BRAND;
+
+  @Dimension(unit = SP)
+  public static final float DISPLAY_LARGE_LINE_HEIGHT = 44.0f;
+
+  @Dimension(unit = SP)
+  public static final float DISPLAY_LARGE_SIZE = 40.0f;
+
+  @Dimension(unit = SP)
+  public static final float DISPLAY_LARGE_TRACKING = 0.2f;
+
+  public static final FontSetting DISPLAY_LARGE_WEIGHT = FontSetting.weight(500);
+
+  public static final FontSetting DISPLAY_LARGE_WIDTH = FontSetting.width(110.0f);
+
+  public static final String DISPLAY_MEDIUM_FONT_FAMILY = TypefaceTokens.BRAND;
+
+  @Dimension(unit = SP)
+  public static final float DISPLAY_MEDIUM_LINE_HEIGHT = 36.0f;
+
+  @Dimension(unit = SP)
+  public static final float DISPLAY_MEDIUM_SIZE = 30.0f;
+
+  @Dimension(unit = SP)
+  public static final float DISPLAY_MEDIUM_TRACKING = 0.2f;
+
+  public static final FontSetting DISPLAY_MEDIUM_WEIGHT = FontSetting.weight(520);
+
+  public static final FontSetting DISPLAY_MEDIUM_WIDTH = FontSetting.width(110.0f);
+
+  public static final String DISPLAY_SMALL_FONT_FAMILY = TypefaceTokens.BRAND;
+
+  @Dimension(unit = SP)
+  public static final float DISPLAY_SMALL_LINE_HEIGHT = 26.0f;
+
+  @Dimension(unit = SP)
+  public static final float DISPLAY_SMALL_SIZE = 24.0f;
+
+  @Dimension(unit = SP)
+  public static final float DISPLAY_SMALL_TRACKING = 0.2f;
+
+  public static final FontSetting DISPLAY_SMALL_WEIGHT = FontSetting.weight(550);
+
+  public static final FontSetting DISPLAY_SMALL_WIDTH = FontSetting.width(110.0f);
+
+  public static final String LABEL_LARGE_FONT_FAMILY = TypefaceTokens.BRAND;
+
+  @Dimension(unit = SP)
+  public static final float LABEL_LARGE_LINE_HEIGHT = 22.0f;
+
+  @Dimension(unit = SP)
+  public static final float LABEL_LARGE_SIZE = 20.0f;
+
+  @Dimension(unit = SP)
+  public static final float LABEL_LARGE_TRACKING = 0.4f;
+
+  public static final FontSetting LABEL_LARGE_WEIGHT = FontSetting.weight(500);
+
+  public static final FontSetting LABEL_LARGE_WIDTH = FontSetting.width(110.0f);
+
+  public static final String LABEL_MEDIUM_FONT_FAMILY = TypefaceTokens.BRAND;
+
+  @Dimension(unit = SP)
+  public static final float LABEL_MEDIUM_LINE_HEIGHT = 16.0f;
+
+  @Dimension(unit = SP)
+  public static final float LABEL_MEDIUM_SIZE = 15.0f;
+
+  @Dimension(unit = SP)
+  public static final float LABEL_MEDIUM_TRACKING = 0.4f;
+
+  public static final FontSetting LABEL_MEDIUM_WEIGHT = FontSetting.weight(500);
+
+  public static final FontSetting LABEL_MEDIUM_WIDTH = FontSetting.width(110.0f);
+
+  public static final String LABEL_SMALL_FONT_FAMILY = TypefaceTokens.BRAND;
+
+  @Dimension(unit = SP)
+  public static final float LABEL_SMALL_LINE_HEIGHT = 16.0f;
+
+  @Dimension(unit = SP)
+  public static final float LABEL_SMALL_SIZE = 13.0f;
+
+  @Dimension(unit = SP)
+  public static final float LABEL_SMALL_TRACKING = 0.4f;
+
+  public static final FontSetting LABEL_SMALL_WEIGHT = FontSetting.weight(500);
+
+  public static final FontSetting LABEL_SMALL_WIDTH = FontSetting.width(110.0f);
+
+  public static final String NUMERAL_EXTRA_LARGE_FONT_FAMILY = TypefaceTokens.BRAND;
+
+  @Dimension(unit = SP)
+  public static final float NUMERAL_EXTRA_LARGE_LINE_HEIGHT = 60.0f;
+
+  @Dimension(unit = SP)
+  public static final float NUMERAL_EXTRA_LARGE_SIZE = 60.0f;
+
+  @Dimension(unit = SP)
+  public static final float NUMERAL_EXTRA_LARGE_TRACKING = 0.0f;
+
+  public static final FontSetting NUMERAL_EXTRA_LARGE_WEIGHT = FontSetting.weight(560);
+
+  public static final FontSetting NUMERAL_EXTRA_LARGE_WEIGHT_PROMINENT = FontSetting.weight(760);
+
+  public static final FontSetting NUMERAL_EXTRA_LARGE_WIDTH = FontSetting.width(110.0f);
+
+  public static final String NUMERAL_EXTRA_SMALL_FONT_FAMILY = TypefaceTokens.BRAND;
+
+  @Dimension(unit = SP)
+  public static final float NUMERAL_EXTRA_SMALL_LINE_HEIGHT = 24.0f;
+
+  @Dimension(unit = SP)
+  public static final float NUMERAL_EXTRA_SMALL_SIZE = 24.0f;
+
+  @Dimension(unit = SP)
+  public static final float NUMERAL_EXTRA_SMALL_TRACKING = 0.0f;
+
+  public static final FontSetting NUMERAL_EXTRA_SMALL_WEIGHT = FontSetting.weight(550);
+
+  public static final FontSetting NUMERAL_EXTRA_SMALL_WEIGHT_PROMINENT = FontSetting.weight(750);
+
+  public static final FontSetting NUMERAL_EXTRA_SMALL_WIDTH = FontSetting.width(100.0f);
+
+  public static final String NUMERAL_LARGE_FONT_FAMILY = TypefaceTokens.BRAND;
+
+  @Dimension(unit = SP)
+  public static final float NUMERAL_LARGE_LINE_HEIGHT = 50.0f;
+
+  @Dimension(unit = SP)
+  public static final float NUMERAL_LARGE_SIZE = 50.0f;
+
+  @Dimension(unit = SP)
+  public static final float NUMERAL_LARGE_TRACKING = 1.0f;
+
+  public static final FontSetting NUMERAL_LARGE_WEIGHT = FontSetting.weight(580);
+
+  public static final FontSetting NUMERAL_LARGE_WEIGHT_PROMINENT = FontSetting.weight(780);
+
+  public static final FontSetting NUMERAL_LARGE_WIDTH = FontSetting.width(110.0f);
+
+  public static final String NUMERAL_MEDIUM_FONT_FAMILY = TypefaceTokens.BRAND;
+
+  @Dimension(unit = SP)
+  public static final float NUMERAL_MEDIUM_LINE_HEIGHT = 40.0f;
+
+  @Dimension(unit = SP)
+  public static final float NUMERAL_MEDIUM_SIZE = 40.0f;
+
+  @Dimension(unit = SP)
+  public static final float NUMERAL_MEDIUM_TRACKING = 0.0f;
+
+  public static final FontSetting NUMERAL_MEDIUM_WEIGHT = FontSetting.weight(580);
+
+  public static final FontSetting NUMERAL_MEDIUM_WEIGHT_PROMINENT = FontSetting.weight(780);
+
+  public static final FontSetting NUMERAL_MEDIUM_WIDTH = FontSetting.width(100.0f);
+
+  public static final String NUMERAL_SMALL_FONT_FAMILY = TypefaceTokens.BRAND;
+
+  @Dimension(unit = SP)
+  public static final float NUMERAL_SMALL_LINE_HEIGHT = 30.0f;
+
+  @Dimension(unit = SP)
+  public static final float NUMERAL_SMALL_SIZE = 30.0f;
+
+  @Dimension(unit = SP)
+  public static final float NUMERAL_SMALL_TRACKING = 1.0f;
+
+  public static final FontSetting NUMERAL_SMALL_WEIGHT = FontSetting.weight(550);
+
+  public static final FontSetting NUMERAL_SMALL_WEIGHT_PROMINENT = FontSetting.weight(750);
+
+  public static final FontSetting NUMERAL_SMALL_WIDTH = FontSetting.width(100.0f);
+
+  public static final String TITLE_LARGE_FONT_FAMILY = TypefaceTokens.BRAND;
+
+  @Dimension(unit = SP)
+  public static final float TITLE_LARGE_LINE_HEIGHT = 22.0f;
+
+  @Dimension(unit = SP)
+  public static final float TITLE_LARGE_SIZE = 20.0f;
+
+  @Dimension(unit = SP)
+  public static final float TITLE_LARGE_TRACKING = 0.2f;
+
+  public static final FontSetting TITLE_LARGE_WEIGHT = FontSetting.weight(500);
+
+  public static final FontSetting TITLE_LARGE_WIDTH = FontSetting.width(110.0f);
+
+  public static final String TITLE_MEDIUM_FONT_FAMILY = TypefaceTokens.BRAND;
+
+  @Dimension(unit = SP)
+  public static final float TITLE_MEDIUM_LINE_HEIGHT = 18.0f;
+
+  @Dimension(unit = SP)
+  public static final float TITLE_MEDIUM_SIZE = 16.0f;
+
+  @Dimension(unit = SP)
+  public static final float TITLE_MEDIUM_TRACKING = 0.4f;
+
+  public static final FontSetting TITLE_MEDIUM_WEIGHT = FontSetting.weight(500);
+
+  public static final FontSetting TITLE_MEDIUM_WIDTH = FontSetting.width(110.0f);
+
+  public static final String TITLE_SMALL_FONT_FAMILY = TypefaceTokens.BRAND;
+
+  @Dimension(unit = SP)
+  public static final float TITLE_SMALL_LINE_HEIGHT = 16.0f;
+
+  @Dimension(unit = SP)
+  public static final float TITLE_SMALL_SIZE = 14.0f;
+
+  @Dimension(unit = SP)
+  public static final float TITLE_SMALL_TRACKING = 0.4f;
+
+  public static final FontSetting TITLE_SMALL_WEIGHT = FontSetting.weight(500);
+
+  public static final FontSetting TITLE_SMALL_WIDTH = FontSetting.width(110.0f);
+
+  private TypeScaleTokens() {}
+}
diff --git a/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/tokens/TypefaceTokens.java b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/tokens/TypefaceTokens.java
new file mode 100644
index 0000000..7b60504
--- /dev/null
+++ b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/tokens/TypefaceTokens.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// VERSION: v0_64
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+package androidx.wear.protolayout.material3.tokens;
+
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+
+/** Material 3 fonts & weights. */
+@RestrictTo(Scope.LIBRARY)
+public final class TypefaceTokens {
+
+  public static final String PLAIN = "roboto-flex";
+
+  public static final float WEIGHT_BOLD = 700.0f;
+
+  public static final float WEIGHT_MEDIUM_1 = 500.0f;
+
+  public static final float WEIGHT_REGULAR = 400.0f;
+
+  public static final String BRAND = PLAIN;
+
+  private TypefaceTokens() {}
+}
diff --git a/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/tokens/TypographyTokens.java b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/tokens/TypographyTokens.java
new file mode 100644
index 0000000..168e593
--- /dev/null
+++ b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/tokens/TypographyTokens.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// VERSION: v0_64
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+package androidx.wear.protolayout.material3.tokens;
+
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+
+/** A range of contrasting text styles in Material3 for supporting product needs. */
+@RestrictTo(Scope.LIBRARY)
+public final class TypographyTokens {
+
+  /**
+   * ArcMedium is for arc headers and titles. Arc is for text along a curved path on the screen,
+   * reserved for short header text strings at the very top or bottom of the screen like page
+   * titles.
+   */
+  public static final TextStyle ARC_MEDIUM =
+      new TextStyle(
+          /* fontFamily= */ TypeScaleTokens.ARC_MEDIUM_FONT_FAMILY,
+          /* size= */ TypeScaleTokens.ARC_MEDIUM_SIZE,
+          /* lineHeight= */ TypeScaleTokens.ARC_MEDIUM_LINE_HEIGHT,
+          /* letterSpacing= */ TypeScaleTokens.ARC_MEDIUM_TRACKING,
+          /* fontSettings= */ VariableFontSettingsTokens.ARC_MEDIUM_VARIATION_SETTINGS);
+
+  /**
+   * ArcSmall is for limited arc strings of text. Arc is for text along a curved path on the screen,
+   * reserved for short curved text strings at the bottom of the screen.
+   */
+  public static final TextStyle ARC_SMALL =
+      new TextStyle(
+          /* fontFamily= */ TypeScaleTokens.ARC_SMALL_FONT_FAMILY,
+          /* size= */ TypeScaleTokens.ARC_SMALL_SIZE,
+          /* lineHeight= */ TypeScaleTokens.ARC_SMALL_LINE_HEIGHT,
+          /* letterSpacing= */ TypeScaleTokens.ARC_SMALL_TRACKING,
+          /* fontSettings= */ VariableFontSettingsTokens.ARC_SMALL_VARIATION_SETTINGS);
+
+  /**
+   * BodyExtraSmall is the smallest body. Body texts are typically used for long-form writing as it
+   * works well for small text sizes. For longer sections of text, a serif or sans serif typeface is
+   * recommended.
+   */
+  public static final TextStyle BODY_EXTRA_SMALL =
+      new TextStyle(
+          /* fontFamily= */ TypeScaleTokens.BODY_EXTRA_SMALL_FONT_FAMILY,
+          /* size= */ TypeScaleTokens.BODY_EXTRA_SMALL_SIZE,
+          /* lineHeight= */ TypeScaleTokens.BODY_EXTRA_SMALL_LINE_HEIGHT,
+          /* letterSpacing= */ TypeScaleTokens.BODY_EXTRA_SMALL_TRACKING,
+          /* fontSettings= */ VariableFontSettingsTokens.BODY_EXTRA_SMALL_VARIATION_SETTINGS);
+
+  /**
+   * BodyLarge is the largest body. Body texts are typically used for long-form writing as it works
+   * well for small text sizes. For longer sections of text, a serif or sans serif typeface is
+   * recommended.
+   */
+  public static final TextStyle BODY_LARGE =
+      new TextStyle(
+          /* fontFamily= */ TypeScaleTokens.BODY_LARGE_FONT_FAMILY,
+          /* size= */ TypeScaleTokens.BODY_LARGE_SIZE,
+          /* lineHeight= */ TypeScaleTokens.BODY_LARGE_LINE_HEIGHT,
+          /* letterSpacing= */ TypeScaleTokens.BODY_LARGE_TRACKING,
+          /* fontSettings= */ VariableFontSettingsTokens.BODY_LARGE_VARIATION_SETTINGS);
+
+  /**
+   * BodyMedium is second largest body. Body texts are typically used for long-form writing as it
+   * works well for small text sizes. For longer sections of text, a serif or sans serif typeface is
+   * recommended.
+   */
+  public static final TextStyle BODY_MEDIUM =
+      new TextStyle(
+          /* fontFamily= */ TypeScaleTokens.BODY_MEDIUM_FONT_FAMILY,
+          /* size= */ TypeScaleTokens.BODY_MEDIUM_SIZE,
+          /* lineHeight= */ TypeScaleTokens.BODY_MEDIUM_LINE_HEIGHT,
+          /* letterSpacing= */ TypeScaleTokens.BODY_MEDIUM_TRACKING,
+          /* fontSettings= */ VariableFontSettingsTokens.BODY_MEDIUM_VARIATION_SETTINGS);
+
+  /**
+   * BodySmall is third largest body. Body texts are typically used for long-form writing as it
+   * works well for small text sizes. For longer sections of text, a serif or sans serif typeface is
+   * recommended.
+   */
+  public static final TextStyle BODY_SMALL =
+      new TextStyle(
+          /* fontFamily= */ TypeScaleTokens.BODY_SMALL_FONT_FAMILY,
+          /* size= */ TypeScaleTokens.BODY_SMALL_SIZE,
+          /* lineHeight= */ TypeScaleTokens.BODY_SMALL_LINE_HEIGHT,
+          /* letterSpacing= */ TypeScaleTokens.BODY_SMALL_TRACKING,
+          /* fontSettings= */ VariableFontSettingsTokens.BODY_SMALL_VARIATION_SETTINGS);
+
+  /**
+   * DisplayLarge is the largest headline. Displays are the largest text on the screen, reserved for
+   * short, important text.
+   */
+  public static final TextStyle DISPLAY_LARGE =
+      new TextStyle(
+          /* fontFamily= */ TypeScaleTokens.DISPLAY_LARGE_FONT_FAMILY,
+          /* size= */ TypeScaleTokens.DISPLAY_LARGE_SIZE,
+          /* lineHeight= */ TypeScaleTokens.DISPLAY_LARGE_LINE_HEIGHT,
+          /* letterSpacing= */ TypeScaleTokens.DISPLAY_LARGE_TRACKING,
+          /* fontSettings= */ VariableFontSettingsTokens.DISPLAY_LARGE_VARIATION_SETTINGS);
+
+  /**
+   * DisplayMedium is the second largest headline. Displays are the largest text on the screen,
+   * reserved for short, important text.
+   */
+  public static final TextStyle DISPLAY_MEDIUM =
+      new TextStyle(
+          /* fontFamily= */ TypeScaleTokens.DISPLAY_MEDIUM_FONT_FAMILY,
+          /* size= */ TypeScaleTokens.DISPLAY_MEDIUM_SIZE,
+          /* lineHeight= */ TypeScaleTokens.DISPLAY_MEDIUM_LINE_HEIGHT,
+          /* letterSpacing= */ TypeScaleTokens.DISPLAY_MEDIUM_TRACKING,
+          /* fontSettings= */ VariableFontSettingsTokens.DISPLAY_MEDIUM_VARIATION_SETTINGS);
+
+  /**
+   * DisplaySmall is the smallest headline. Displays are the largest text on the screen, reserved
+   * for short, important text.
+   */
+  public static final TextStyle DISPLAY_SMALL =
+      new TextStyle(
+          /* fontFamily= */ TypeScaleTokens.DISPLAY_SMALL_FONT_FAMILY,
+          /* size= */ TypeScaleTokens.DISPLAY_SMALL_SIZE,
+          /* lineHeight= */ TypeScaleTokens.DISPLAY_SMALL_LINE_HEIGHT,
+          /* letterSpacing= */ TypeScaleTokens.DISPLAY_SMALL_TRACKING,
+          /* fontSettings= */ VariableFontSettingsTokens.DISPLAY_SMALL_VARIATION_SETTINGS);
+
+  /**
+   * LabelLarge is the largest label. They are used for displaying prominent texts like label on
+   * title buttons.
+   */
+  public static final TextStyle LABEL_LARGE =
+      new TextStyle(
+          /* fontFamily= */ TypeScaleTokens.LABEL_LARGE_FONT_FAMILY,
+          /* size= */ TypeScaleTokens.LABEL_LARGE_SIZE,
+          /* lineHeight= */ TypeScaleTokens.LABEL_LARGE_LINE_HEIGHT,
+          /* letterSpacing= */ TypeScaleTokens.LABEL_LARGE_TRACKING,
+          /* fontSettings= */ VariableFontSettingsTokens.LABEL_LARGE_VARIATION_SETTINGS);
+
+  /**
+   * LabelMedium is the medium label. They are used for displaying texts like primary label on
+   * buttons.
+   */
+  public static final TextStyle LABEL_MEDIUM =
+      new TextStyle(
+          /* fontFamily= */ TypeScaleTokens.LABEL_MEDIUM_FONT_FAMILY,
+          /* size= */ TypeScaleTokens.LABEL_MEDIUM_SIZE,
+          /* lineHeight= */ TypeScaleTokens.LABEL_MEDIUM_LINE_HEIGHT,
+          /* letterSpacing= */ TypeScaleTokens.LABEL_MEDIUM_TRACKING,
+          /* fontSettings= */ VariableFontSettingsTokens.LABEL_MEDIUM_VARIATION_SETTINGS);
+
+  /**
+   * LabelSmall is the small label. They are used for displaying texts like secondary label on
+   * buttons, labels on compact buttons.
+   */
+  public static final TextStyle LABEL_SMALL =
+      new TextStyle(
+          /* fontFamily= */ TypeScaleTokens.LABEL_SMALL_FONT_FAMILY,
+          /* size= */ TypeScaleTokens.LABEL_SMALL_SIZE,
+          /* lineHeight= */ TypeScaleTokens.LABEL_SMALL_LINE_HEIGHT,
+          /* letterSpacing= */ TypeScaleTokens.LABEL_SMALL_TRACKING,
+          /* fontSettings= */ VariableFontSettingsTokens.LABEL_SMALL_VARIATION_SETTINGS);
+
+  /**
+   * NumeralsExtraLarge is the largest role for digits. Numerals use tabular spacing by default.
+   * They highlight and express glanceable numbers that are limited to a two or three characters
+   * only, where no localization is required like the charging screen.
+   */
+  public static final TextStyle NUMERAL_EXTRA_LARGE =
+      new TextStyle(
+          /* fontFamily= */ TypeScaleTokens.NUMERAL_EXTRA_LARGE_FONT_FAMILY,
+          /* size= */ TypeScaleTokens.NUMERAL_EXTRA_LARGE_SIZE,
+          /* lineHeight= */ TypeScaleTokens.NUMERAL_EXTRA_LARGE_LINE_HEIGHT,
+          /* letterSpacing= */ TypeScaleTokens.NUMERAL_EXTRA_LARGE_TRACKING,
+          /* fontSettings= */ VariableFontSettingsTokens.NUMERAL_EXTRA_LARGE_VARIATION_SETTINGS);
+
+  /**
+   * NumeralsExtraSmall is the smallest role for digits. Numerals use tabular spacing by default.
+   * They are for numbers that need to accommodate longer strings of digits, where no localization
+   * is required like in-workout metrics.
+   */
+  public static final TextStyle NUMERAL_EXTRA_SMALL =
+      new TextStyle(
+          /* fontFamily= */ TypeScaleTokens.NUMERAL_EXTRA_SMALL_FONT_FAMILY,
+          /* size= */ TypeScaleTokens.NUMERAL_EXTRA_SMALL_SIZE,
+          /* lineHeight= */ TypeScaleTokens.NUMERAL_EXTRA_SMALL_LINE_HEIGHT,
+          /* letterSpacing= */ TypeScaleTokens.NUMERAL_EXTRA_SMALL_TRACKING,
+          /* fontSettings= */ VariableFontSettingsTokens.NUMERAL_EXTRA_SMALL_VARIATION_SETTINGS);
+
+  /**
+   * NumeralsLarge is the second largest role for digits. Numerals use tabular spacing by default.
+   * They are large sized number strings that are limited to big displays of time, where no
+   * localization is required like a timer countdown.
+   */
+  public static final TextStyle NUMERAL_LARGE =
+      new TextStyle(
+          /* fontFamily= */ TypeScaleTokens.NUMERAL_LARGE_FONT_FAMILY,
+          /* size= */ TypeScaleTokens.NUMERAL_LARGE_SIZE,
+          /* lineHeight= */ TypeScaleTokens.NUMERAL_LARGE_LINE_HEIGHT,
+          /* letterSpacing= */ TypeScaleTokens.NUMERAL_LARGE_TRACKING,
+          /* fontSettings= */ VariableFontSettingsTokens.NUMERAL_LARGE_VARIATION_SETTINGS);
+
+  /**
+   * NumeralsMedium is the third largest role for digits. Numerals use tabular spacing by default.
+   * They are medium sized numbers that are limited to short strings of digits, where no
+   * localization is required like a steps count.
+   */
+  public static final TextStyle NUMERAL_MEDIUM =
+      new TextStyle(
+          /* fontFamily= */ TypeScaleTokens.NUMERAL_MEDIUM_FONT_FAMILY,
+          /* size= */ TypeScaleTokens.NUMERAL_MEDIUM_SIZE,
+          /* lineHeight= */ TypeScaleTokens.NUMERAL_MEDIUM_LINE_HEIGHT,
+          /* letterSpacing= */ TypeScaleTokens.NUMERAL_MEDIUM_TRACKING,
+          /* fontSettings= */ VariableFontSettingsTokens.NUMERAL_MEDIUM_VARIATION_SETTINGS);
+
+  /**
+   * NumeralsSmall is the fourth largest role for digits. Numerals use tabular spacing by default.
+   * They are for numbers that need emphasis at a smaller scale, where no localization is required
+   * like date and time pickers.
+   */
+  public static final TextStyle NUMERAL_SMALL =
+      new TextStyle(
+          /* fontFamily= */ TypeScaleTokens.NUMERAL_SMALL_FONT_FAMILY,
+          /* size= */ TypeScaleTokens.NUMERAL_SMALL_SIZE,
+          /* lineHeight= */ TypeScaleTokens.NUMERAL_SMALL_LINE_HEIGHT,
+          /* letterSpacing= */ TypeScaleTokens.NUMERAL_SMALL_TRACKING,
+          /* fontSettings= */ VariableFontSettingsTokens.NUMERAL_SMALL_VARIATION_SETTINGS);
+
+  /**
+   * TitleLarge is the largest title. Titles are smaller than Displays. They are typically reserved
+   * for medium-emphasis text that is shorter in length.
+   */
+  public static final TextStyle TITLE_LARGE =
+      new TextStyle(
+          /* fontFamily= */ TypeScaleTokens.TITLE_LARGE_FONT_FAMILY,
+          /* size= */ TypeScaleTokens.TITLE_LARGE_SIZE,
+          /* lineHeight= */ TypeScaleTokens.TITLE_LARGE_LINE_HEIGHT,
+          /* letterSpacing= */ TypeScaleTokens.TITLE_LARGE_TRACKING,
+          /* fontSettings= */ VariableFontSettingsTokens.TITLE_LARGE_VARIATION_SETTINGS);
+
+  /**
+   * TitleMedium is the medium title. Titles are smaller than Displays. They are typically reserved
+   * for medium-emphasis text that is shorter in length.
+   */
+  public static final TextStyle TITLE_MEDIUM =
+      new TextStyle(
+          /* fontFamily= */ TypeScaleTokens.TITLE_MEDIUM_FONT_FAMILY,
+          /* size= */ TypeScaleTokens.TITLE_MEDIUM_SIZE,
+          /* lineHeight= */ TypeScaleTokens.TITLE_MEDIUM_LINE_HEIGHT,
+          /* letterSpacing= */ TypeScaleTokens.TITLE_MEDIUM_TRACKING,
+          /* fontSettings= */ VariableFontSettingsTokens.TITLE_MEDIUM_VARIATION_SETTINGS);
+
+  /**
+   * TitleSmall is the smallest title. Titles are smaller than Displays. They are typically reserved
+   * for medium-emphasis text that is shorter in length.
+   */
+  public static final TextStyle TITLE_SMALL =
+      new TextStyle(
+          /* fontFamily= */ TypeScaleTokens.TITLE_SMALL_FONT_FAMILY,
+          /* size= */ TypeScaleTokens.TITLE_SMALL_SIZE,
+          /* lineHeight= */ TypeScaleTokens.TITLE_SMALL_LINE_HEIGHT,
+          /* letterSpacing= */ TypeScaleTokens.TITLE_SMALL_TRACKING,
+          /* fontSettings= */ VariableFontSettingsTokens.TITLE_SMALL_VARIATION_SETTINGS);
+
+  private TypographyTokens() {}
+}
diff --git a/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/tokens/VariableFontSettingsTokens.java b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/tokens/VariableFontSettingsTokens.java
new file mode 100644
index 0000000..37efe70
--- /dev/null
+++ b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/tokens/VariableFontSettingsTokens.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// VERSION: v0_64
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+package androidx.wear.protolayout.material3.tokens;
+
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.LayoutElementBuilders.FontSetting;
+import java.util.List;
+
+/** A list of text style values in Material3 for supporting product needs. */
+@RestrictTo(Scope.LIBRARY)
+@SuppressWarnings("JdkImmutableCollections")
+public final class VariableFontSettingsTokens {
+
+  public static final List<FontSetting> ARC_MEDIUM_VARIATION_SETTINGS =
+      List.of(TypeScaleTokens.ARC_MEDIUM_WEIGHT, TypeScaleTokens.ARC_MEDIUM_WIDTH);
+
+  public static final List<FontSetting> ARC_SMALL_VARIATION_SETTINGS =
+      List.of(TypeScaleTokens.ARC_SMALL_WEIGHT, TypeScaleTokens.ARC_SMALL_WIDTH);
+
+  public static final List<FontSetting> BODY_EXTRA_SMALL_VARIATION_SETTINGS =
+      List.of(TypeScaleTokens.BODY_EXTRA_SMALL_WEIGHT, TypeScaleTokens.BODY_EXTRA_SMALL_WIDTH);
+
+  public static final List<FontSetting> BODY_LARGE_VARIATION_SETTINGS =
+      List.of(TypeScaleTokens.BODY_LARGE_WEIGHT, TypeScaleTokens.BODY_LARGE_WIDTH);
+
+  public static final List<FontSetting> BODY_MEDIUM_VARIATION_SETTINGS =
+      List.of(TypeScaleTokens.BODY_MEDIUM_WEIGHT, TypeScaleTokens.BODY_MEDIUM_WIDTH);
+
+  public static final List<FontSetting> BODY_SMALL_VARIATION_SETTINGS =
+      List.of(TypeScaleTokens.BODY_SMALL_WEIGHT, TypeScaleTokens.BODY_SMALL_WIDTH);
+
+  public static final List<FontSetting> DISPLAY_LARGE_VARIATION_SETTINGS =
+      List.of(TypeScaleTokens.DISPLAY_LARGE_WEIGHT, TypeScaleTokens.DISPLAY_LARGE_WIDTH);
+
+  public static final List<FontSetting> DISPLAY_MEDIUM_VARIATION_SETTINGS =
+      List.of(TypeScaleTokens.DISPLAY_MEDIUM_WEIGHT, TypeScaleTokens.DISPLAY_MEDIUM_WIDTH);
+
+  public static final List<FontSetting> DISPLAY_SMALL_VARIATION_SETTINGS =
+      List.of(TypeScaleTokens.DISPLAY_SMALL_WEIGHT, TypeScaleTokens.DISPLAY_SMALL_WIDTH);
+
+  public static final List<FontSetting> LABEL_LARGE_VARIATION_SETTINGS =
+      List.of(TypeScaleTokens.LABEL_LARGE_WEIGHT, TypeScaleTokens.LABEL_LARGE_WIDTH);
+
+  public static final List<FontSetting> LABEL_MEDIUM_VARIATION_SETTINGS =
+      List.of(TypeScaleTokens.LABEL_MEDIUM_WEIGHT, TypeScaleTokens.LABEL_MEDIUM_WIDTH);
+
+  public static final List<FontSetting> LABEL_SMALL_VARIATION_SETTINGS =
+      List.of(TypeScaleTokens.LABEL_SMALL_WEIGHT, TypeScaleTokens.LABEL_SMALL_WIDTH);
+
+  public static final List<FontSetting> NUMERAL_EXTRA_LARGE_VARIATION_SETTINGS =
+      List.of(
+          FontSetting.tabularNum(),
+          TypeScaleTokens.NUMERAL_EXTRA_LARGE_WEIGHT,
+          TypeScaleTokens.NUMERAL_EXTRA_LARGE_WIDTH);
+
+  public static final List<FontSetting> NUMERAL_EXTRA_SMALL_VARIATION_SETTINGS =
+      List.of(
+          FontSetting.tabularNum(),
+          TypeScaleTokens.NUMERAL_EXTRA_SMALL_WEIGHT,
+          TypeScaleTokens.NUMERAL_EXTRA_SMALL_WIDTH);
+
+  public static final List<FontSetting> NUMERAL_LARGE_VARIATION_SETTINGS =
+      List.of(
+          FontSetting.tabularNum(),
+          TypeScaleTokens.NUMERAL_LARGE_WEIGHT,
+          TypeScaleTokens.NUMERAL_LARGE_WIDTH);
+
+  public static final List<FontSetting> NUMERAL_MEDIUM_VARIATION_SETTINGS =
+      List.of(
+          FontSetting.tabularNum(),
+          TypeScaleTokens.NUMERAL_MEDIUM_WEIGHT,
+          TypeScaleTokens.NUMERAL_MEDIUM_WIDTH);
+
+  public static final List<FontSetting> NUMERAL_SMALL_VARIATION_SETTINGS =
+      List.of(
+          FontSetting.tabularNum(),
+          TypeScaleTokens.NUMERAL_SMALL_WEIGHT,
+          TypeScaleTokens.NUMERAL_SMALL_WIDTH);
+
+  public static final List<FontSetting> TITLE_LARGE_VARIATION_SETTINGS =
+      List.of(TypeScaleTokens.TITLE_LARGE_WEIGHT, TypeScaleTokens.TITLE_LARGE_WIDTH);
+
+  public static final List<FontSetting> TITLE_MEDIUM_VARIATION_SETTINGS =
+      List.of(TypeScaleTokens.TITLE_MEDIUM_WEIGHT, TypeScaleTokens.TITLE_MEDIUM_WIDTH);
+
+  public static final List<FontSetting> TITLE_SMALL_VARIATION_SETTINGS =
+      List.of(TypeScaleTokens.TITLE_SMALL_WEIGHT, TypeScaleTokens.TITLE_SMALL_WIDTH);
+
+  private VariableFontSettingsTokens() {}
+}
diff --git a/wear/protolayout/protolayout-renderer/api/1.2.0-beta01.txt b/wear/protolayout/protolayout-renderer/api/1.2.0-beta01.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/wear/protolayout/protolayout-renderer/api/1.2.0-beta01.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/wear/protolayout/protolayout-renderer/api/res-1.2.0-beta01.txt b/wear/protolayout/protolayout-renderer/api/res-1.2.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wear/protolayout/protolayout-renderer/api/res-1.2.0-beta01.txt
diff --git a/wear/protolayout/protolayout-renderer/api/restricted_1.2.0-beta01.txt b/wear/protolayout/protolayout-renderer/api/restricted_1.2.0-beta01.txt
new file mode 100644
index 0000000..6933c93
--- /dev/null
+++ b/wear/protolayout/protolayout-renderer/api/restricted_1.2.0-beta01.txt
@@ -0,0 +1,53 @@
+// Signature format: 4.0
+package androidx.wear.protolayout.renderer.common {
+
+  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public interface LoggingUtils {
+    method public boolean canLogD(String);
+    method public void logD(String, String);
+    method @com.google.errorprone.annotations.FormatMethod public void logD(String, @com.google.errorprone.annotations.FormatString String, java.lang.Object!...);
+  }
+
+  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public class LoggingUtilsImpl implements androidx.wear.protolayout.renderer.common.LoggingUtils {
+    ctor public LoggingUtilsImpl(android.content.ComponentName);
+    method public boolean canLogD(String);
+    method public void logD(String, String);
+    method @com.google.errorprone.annotations.FormatMethod public void logD(String, @com.google.errorprone.annotations.FormatString String, java.lang.Object!...);
+  }
+
+}
+
+package androidx.wear.protolayout.renderer.impl {
+
+  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public class ProtoLayoutViewInstance implements java.lang.AutoCloseable {
+    ctor public ProtoLayoutViewInstance(androidx.wear.protolayout.renderer.impl.ProtoLayoutViewInstance.Config);
+    method public void close() throws java.lang.Exception;
+    method @UiThread public void detach(android.view.ViewGroup);
+    method public void invalidateCache();
+    method @UiThread public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> renderAndAttach(androidx.wear.protolayout.proto.LayoutElementProto.Layout, androidx.wear.protolayout.proto.ResourceProto.Resources, android.view.ViewGroup);
+  }
+
+  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final class ProtoLayoutViewInstance.Config {
+    method public com.google.common.util.concurrent.ListeningExecutorService getBgExecutorService();
+    method public String getClickableIdExtra();
+    method public androidx.wear.protolayout.renderer.impl.ProtoLayoutViewInstance.LoadActionListener getLoadActionListener();
+    method public androidx.wear.protolayout.renderer.common.LoggingUtils? getLoggingUtils();
+    method public java.util.Map<androidx.wear.protolayout.expression.pipeline.PlatformDataProvider!,java.util.Set<androidx.wear.protolayout.expression.PlatformDataKey<? extends java.lang.Object!>!>!> getPlatformDataProviders();
+    method public androidx.wear.protolayout.expression.pipeline.StateStore? getStateStore();
+    method public android.content.Context getUiContext();
+    method public com.google.common.util.concurrent.ListeningExecutorService getUiExecutorService();
+  }
+
+  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final class ProtoLayoutViewInstance.Config.Builder {
+    ctor public ProtoLayoutViewInstance.Config.Builder(android.content.Context, com.google.common.util.concurrent.ListeningExecutorService, com.google.common.util.concurrent.ListeningExecutorService, String);
+    method public androidx.wear.protolayout.renderer.impl.ProtoLayoutViewInstance.Config.Builder addPlatformDataProvider(androidx.wear.protolayout.expression.pipeline.PlatformDataProvider, androidx.wear.protolayout.expression.PlatformDataKey<? extends java.lang.Object!>!...);
+    method public androidx.wear.protolayout.renderer.impl.ProtoLayoutViewInstance.Config build();
+    method public androidx.wear.protolayout.renderer.impl.ProtoLayoutViewInstance.Config.Builder setLoadActionListener(androidx.wear.protolayout.renderer.impl.ProtoLayoutViewInstance.LoadActionListener);
+    method public androidx.wear.protolayout.renderer.impl.ProtoLayoutViewInstance.Config.Builder setStateStore(androidx.wear.protolayout.expression.pipeline.StateStore);
+  }
+
+  public static interface ProtoLayoutViewInstance.LoadActionListener {
+    method public void onClick(androidx.wear.protolayout.proto.StateProto.State);
+  }
+
+}
+
diff --git a/wear/protolayout/protolayout-renderer/api/restricted_current.ignore b/wear/protolayout/protolayout-renderer/api/restricted_current.ignore
new file mode 100644
index 0000000..bdde8a3
--- /dev/null
+++ b/wear/protolayout/protolayout-renderer/api/restricted_current.ignore
@@ -0,0 +1,5 @@
+// Baseline format: 1.0
+InvalidNullConversion: androidx.wear.protolayout.renderer.impl.ProtoLayoutViewInstance.Config#getPlatformDataProviders():
+    Attempted to remove nullability from java.lang.Object (was NONNULL) in method androidx.wear.protolayout.renderer.impl.ProtoLayoutViewInstance.Config.getPlatformDataProviders()
+InvalidNullConversion: androidx.wear.protolayout.renderer.impl.ProtoLayoutViewInstance.Config.Builder#addPlatformDataProvider(androidx.wear.protolayout.expression.pipeline.PlatformDataProvider, androidx.wear.protolayout.expression.PlatformDataKey<?>...) parameter #1:
+    Attempted to remove nullability from java.lang.Object (was NONNULL) in parameter arg2 in androidx.wear.protolayout.renderer.impl.ProtoLayoutViewInstance.Config.Builder.addPlatformDataProvider(androidx.wear.protolayout.expression.pipeline.PlatformDataProvider arg1, androidx.wear.protolayout.expression.PlatformDataKey<?>... arg2)
diff --git a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/ProtoLayoutTheme.java b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/ProtoLayoutTheme.java
index a06bd4e..0361d51 100644
--- a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/ProtoLayoutTheme.java
+++ b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/ProtoLayoutTheme.java
@@ -28,6 +28,12 @@
 /** Theme customization for ProtoLayout texts, which includes Font types and variants. */
 @RestrictTo(Scope.LIBRARY)
 public interface ProtoLayoutTheme {
+    // These map to family names from androidx.wear.protolayout.LayoutElementBuilders.FontStyle
+    String FONT_NAME_DEFAULT = "default";
+    String FONT_NAME_ROBOTO = "roboto";
+    String FONT_NAME_ROBOTO_FLEX = "roboto-flex";
+    String FONT_NAME_LEGACY_VARIANT_TITLE = "protolayout-title";
+    String FONT_NAME_LEGACY_VARIANT_BODY = "protolayout-body";
 
     /** Holder for different weights of the same font variant. */
     interface FontSet {
@@ -43,13 +49,22 @@
     }
 
     /**
-     * Gets the FontSet for a given font variant.
+     * Returns the {@link FontSet} for the first font family name that is supported. If none are
+     * supported, defaults to the system font.
      *
-     * @param fontVariant the numeric value of the proto enum {@link
-     *     androidx.wear.protolayout.proto.LayoutElementProto.FontVariant}.
+     * <p>It's theme's responsibility to define which font family is supported by returning the
+     * corresponding {@link FontSet}. The default one should be system font and always supported.
+     * The Roboto Flex variable font from {@link
+     * androidx.wear.protolayout.LayoutElementBuilders.FontStyle#ROBOTO_FLEX_FONT} and
+     * standard Roboto font from {@link
+     * androidx.wear.protolayout.LayoutElementBuilders.FontStyle#ROBOTO_FONT} should be
+     * supported on renderers supporting versions 1.4 and above.
+     *
+     * @param preferredFontFamilies the ordered list of String values representing the preferred
+     *     font families that should be used.
      */
     @NonNull
-    FontSet getFontSet(int fontVariant);
+    FontSet getFontSet(@NonNull String... preferredFontFamilies);
 
     /** Gets an Android Theme object styled with TextAppearance attributes. */
     @NonNull
@@ -63,9 +78,9 @@
     int getFallbackTextAppearanceResId();
 
     /**
-     * Gets a drawable resource Id for a custom ripple. The resource with this id should be
-     * present in the Android Theme returned by {@link ProtoLayoutTheme#getTheme()}. If no custom
-     * ripple is set, this method should return zero.
+     * Gets a drawable resource Id for a custom ripple. The resource with this id should be present
+     * in the Android Theme returned by {@link ProtoLayoutTheme#getTheme()}. If no custom ripple is
+     * set, this method should return zero.
      */
     @DrawableRes
     int getRippleResId();
diff --git a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/ProtoLayoutInflater.java b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/ProtoLayoutInflater.java
index 3c41231..3be0537 100644
--- a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/ProtoLayoutInflater.java
+++ b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/ProtoLayoutInflater.java
@@ -33,6 +33,7 @@
 import static java.lang.Math.max;
 import static java.lang.Math.min;
 import static java.lang.Math.round;
+import static java.nio.charset.StandardCharsets.US_ASCII;
 
 import android.annotation.SuppressLint;
 import android.content.Context;
@@ -133,7 +134,10 @@
 import androidx.wear.protolayout.proto.LayoutElementProto.Column;
 import androidx.wear.protolayout.proto.LayoutElementProto.ContentScaleMode;
 import androidx.wear.protolayout.proto.LayoutElementProto.ExtensionLayoutElement;
+import androidx.wear.protolayout.proto.LayoutElementProto.FontFeatureSetting;
+import androidx.wear.protolayout.proto.LayoutElementProto.FontSetting;
 import androidx.wear.protolayout.proto.LayoutElementProto.FontStyle;
+import androidx.wear.protolayout.proto.LayoutElementProto.FontVariationSetting;
 import androidx.wear.protolayout.proto.LayoutElementProto.Image;
 import androidx.wear.protolayout.proto.LayoutElementProto.Layout;
 import androidx.wear.protolayout.proto.LayoutElementProto.LayoutElement;
@@ -198,15 +202,18 @@
 import androidx.wear.widget.ArcLayout;
 import androidx.wear.widget.CurvedTextView;
 
+import com.google.common.collect.ImmutableSet;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.SettableFuture;
 
+import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Optional;
+import java.util.StringJoiner;
 import java.util.concurrent.CancellationException;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
@@ -307,13 +314,19 @@
 
     @Nullable private final LoggingUtils mLoggingUtils;
     @NonNull private final InflaterStatsLogger mInflaterStatsLogger;
-
     @Nullable final Executor mLoadActionExecutor;
     final LoadActionListener mLoadActionListener;
     final boolean mAnimationEnabled;
 
     private boolean mApplyFontVariantBodyAsDefault = false;
 
+    @VisibleForTesting static final String WEIGHT_AXIS_TAG = "wght";
+    @VisibleForTesting static final String WIDTH_AXIS_TAG = "wdth";
+    @VisibleForTesting static final String TABULAR_OPTION_TAG = "tnum";
+
+    private static final ImmutableSet<String> SUPPORTED_FONT_SETTING_TAGS =
+            ImmutableSet.of(WEIGHT_AXIS_TAG, WIDTH_AXIS_TAG, TABULAR_OPTION_TAG);
+
     /**
      * Listener for clicks on Clickable objects that have an Action to (re)load the contents of a
      * layout.
@@ -1158,6 +1171,8 @@
      * bold bit set to render properly.
      */
     private static boolean isBold(FontStyle fontStyle) {
+        // Even though we have weight axis too, this concept of bold and bold flag in Typeface is
+        // different, so we only look at the FontWeight enum API here.
         // Although this method could be a simple equality check against FONT_WEIGHT_BOLD, we list
         // all current cases here so that this will become a compile time error as soon as a new
         // FontWeight value is added to the schema. If this fails to build, then this means that an
@@ -1178,8 +1193,30 @@
     }
 
     private Typeface fontStyleToTypeface(FontStyle fontStyle) {
-        FontSet fonts = mProtoLayoutTheme.getFontSet(fontStyle.getVariant().getValue().getNumber());
+        String[] preferredFontFamilies = new String[fontStyle.getPreferredFontFamiliesCount() + 1];
+        if (fontStyle.getPreferredFontFamiliesCount() > 0) {
+            fontStyle.getPreferredFontFamiliesList().toArray(preferredFontFamilies);
+        }
 
+        // Add value from the FontVariant as fallback to work with providers using legacy
+        // FONT_VARIANT API or with older system API.
+        String fontVariantName;
+        switch (fontStyle.getVariant().getValue()) {
+            case FONT_VARIANT_TITLE:
+                fontVariantName = ProtoLayoutTheme.FONT_NAME_LEGACY_VARIANT_TITLE;
+                break;
+            case UNRECOGNIZED:
+            case FONT_VARIANT_BODY:
+            default:
+                // fall through as this is default
+                fontVariantName = ProtoLayoutTheme.FONT_NAME_LEGACY_VARIANT_BODY;
+                break;
+        }
+        preferredFontFamilies[preferredFontFamilies.length - 1] = fontVariantName;
+
+        FontSet fonts = mProtoLayoutTheme.getFontSet(preferredFontFamilies);
+
+        // Only use FontWeight enum API. Weight axis is already covered by FontVariationSetting.
         switch (fontStyle.getWeight().getValue()) {
             case FONT_WEIGHT_BOLD:
                 return fonts.getBoldFont();
@@ -1239,6 +1276,9 @@
         // Need to supply typefaceStyle when creating the typeface (will select specialist
         // bold/italic typefaces), *and* when setting the typeface (will set synthetic bold/italic
         // flags in Paint if they're not supported by the given typeface).
+        // This is fine to do even for variable fonts with weight axis, as if their weight axis is
+        // larger than 700 and BOLD flag is on, it should be "bolded" two times - one for Typeface
+        // selection, one for axis value.
         textView.setTypeface(createTypeface(style), fontStyleToTypefaceStyle(style));
 
         if (fontStyleHasSize(style)) {
@@ -1307,6 +1347,57 @@
         } else {
             textView.setTextColor(TEXT_COLOR_DEFAULT);
         }
+
+        if (style.getSettingsCount() > 0) {
+            applyFontSetting(style, textView);
+        }
+    }
+
+    private void applyFontSetting(@NonNull FontStyle style, @NonNull TextView textView) {
+        StringJoiner variationSettings = new StringJoiner(",");
+        StringJoiner featureSettings = new StringJoiner(",");
+
+        for (FontSetting setting : style.getSettingsList()) {
+            String tag = "";
+
+            switch (setting.getInnerCase()) {
+                case VARIATION:
+                    FontVariationSetting variation = setting.getVariation();
+                    tag = toTagString(variation.getAxisTag());
+
+                    if (SUPPORTED_FONT_SETTING_TAGS.contains(tag)) {
+                        variationSettings.add("'" + tag + "' " + variation.getValue());
+                    } else {
+                        // Skip not supported tags.
+                        Log.d(TAG, "FontVariation axes tag " + tag + " is not supported.");
+                    }
+
+                    break;
+                case FEATURE:
+                    FontFeatureSetting feature = setting.getFeature();
+                    tag = toTagString(feature.getTag());
+
+                    if (SUPPORTED_FONT_SETTING_TAGS.contains(tag)) {
+                        featureSettings.add("'" + tag + "'");
+                    } else {
+                        // Skip not supported tags.
+                        Log.d(TAG, "FontFeature tag " + tag + " is not supported.");
+                    }
+
+                    break;
+                case INNER_NOT_SET:
+                    break;
+            }
+        }
+
+        textView.setFontVariationSettings(variationSettings.toString());
+        textView.setFontFeatureSettings(featureSettings.toString());
+    }
+
+    /** Given the integer representation of 4 characters ASCII code, returns the String of it. */
+    @NonNull
+    private static String toTagString(int tagCode) {
+        return new String(ByteBuffer.allocate(4).putInt(tagCode).array(), US_ASCII);
     }
 
     private void applyFontStyle(FontStyle style, CurvedTextView textView) {
diff --git a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/ProtoLayoutThemeImpl.java b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/ProtoLayoutThemeImpl.java
index b540781..92494b2 100644
--- a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/ProtoLayoutThemeImpl.java
+++ b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/ProtoLayoutThemeImpl.java
@@ -18,6 +18,8 @@
 
 import static androidx.core.util.Preconditions.checkNotNull;
 
+import static java.util.Arrays.stream;
+
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
@@ -31,10 +33,11 @@
 import androidx.annotation.StyleRes;
 import androidx.annotation.StyleableRes;
 import androidx.collection.ArrayMap;
-import androidx.wear.protolayout.proto.LayoutElementProto.FontVariant;
 import androidx.wear.protolayout.renderer.ProtoLayoutTheme;
 import androidx.wear.protolayout.renderer.R;
 
+import com.google.common.collect.ImmutableSet;
+
 import java.util.Map;
 
 /** Theme customization for ProtoLayout texts, which includes Font types and variants. */
@@ -106,7 +109,7 @@
         return new ProtoLayoutThemeImpl(context.getResources(), R.style.ProtoLayoutBaseTheme);
     }
 
-    private final Map<Integer, FontSet> mVariantToFontSet = new ArrayMap<>();
+    private final Map<String, FontSet> mFontFamilyToFontSet = new ArrayMap<>();
     private final Theme mTheme;
     @AttrRes private final int mFallbackTextAppearanceAttrId;
 
@@ -139,32 +142,79 @@
 
         TypedArray a = mTheme.obtainStyledAttributes(R.styleable.ProtoLayoutTheme);
 
-        mVariantToFontSet.put(
-                FontVariant.FONT_VARIANT_TITLE_VALUE,
+        int defaultBodyFontResourceId =
+                a.getResourceId(R.styleable.ProtoLayoutTheme_protoLayoutBodyFont, -1);
+
+        // Font families. Default to body font in case theme doesn't have set attribute.
+        mFontFamilyToFontSet.put(
+                FONT_NAME_DEFAULT,
+                new FontSetImpl(
+                        mTheme,
+                        a.getResourceId(
+                                R.styleable.ProtoLayoutTheme_protoLayoutDefaultSystemFont,
+                                defaultBodyFontResourceId)));
+        mFontFamilyToFontSet.put(
+                FONT_NAME_ROBOTO,
+                new FontSetImpl(
+                        mTheme,
+                        a.getResourceId(
+                                R.styleable.ProtoLayoutTheme_protoLayoutRobotoFont,
+                                defaultBodyFontResourceId)));
+        mFontFamilyToFontSet.put(
+                FONT_NAME_ROBOTO_FLEX,
+                new FontSetImpl(
+                        mTheme,
+                        a.getResourceId(
+                                R.styleable.ProtoLayoutTheme_protoLayoutRobotoFlexFont,
+                                defaultBodyFontResourceId)));
+
+        // Legacy variants
+        mFontFamilyToFontSet.put(
+                FONT_NAME_LEGACY_VARIANT_TITLE,
                 new FontSetImpl(
                         mTheme,
                         a.getResourceId(R.styleable.ProtoLayoutTheme_protoLayoutTitleFont, -1)));
-
-        mVariantToFontSet.put(
-                FontVariant.FONT_VARIANT_BODY_VALUE,
-                new FontSetImpl(
-                        mTheme,
-                        a.getResourceId(R.styleable.ProtoLayoutTheme_protoLayoutBodyFont, -1)));
+        mFontFamilyToFontSet.put(
+                FONT_NAME_LEGACY_VARIANT_BODY, new FontSetImpl(mTheme, defaultBodyFontResourceId));
 
         a.recycle();
     }
 
+    private static final ImmutableSet<String> SUPPORTED_FONT_FAMILIES =
+            ImmutableSet.of(
+                    FONT_NAME_DEFAULT,
+                    FONT_NAME_ROBOTO,
+                    // TODO(b/348207120): Enable Roboto Flex font.
+                    // FONT_NAME_ROBOTO_FLEX,
+                    FONT_NAME_LEGACY_VARIANT_TITLE,
+                    FONT_NAME_LEGACY_VARIANT_BODY);
+
     /**
-     * Gets the FontSet for a given font variant.
+     * Returns the {@link FontSet} for the first font family name that is supported. If none are
+     * supported, defaults to the system font.
      *
-     * @param fontVariant the numeric value of the proto enum {@link FontVariant}.
+     * <p>It's theme's responsibility to define which font families are supported by returning the
+     * corresponding {@link FontSet}. The default one should be system font and always supported.
+     * The Roboto Flex variable font from {@link
+     * androidx.wear.protolayout.LayoutElementBuilders.FontStyle#ROBOTO_FLEX_FONT} and
+     * standard Roboto font from {@link
+     * androidx.wear.protolayout.LayoutElementBuilders.FontStyle#ROBOTO_FONT} should be
+     * supported on renderers supporting versions 1.4 and above.
+     *
+     * @param preferredFontFamilies the prioritized list of String values representing the preferred
+     *     font families that should be used.
      */
-    @Override
     @NonNull
-    public FontSet getFontSet(int fontVariant) {
-        FontSet defaultFontSet =
-                checkNotNull(mVariantToFontSet.get(FontVariant.FONT_VARIANT_BODY_VALUE));
-        return mVariantToFontSet.getOrDefault(fontVariant, defaultFontSet);
+    @Override
+    public FontSet getFontSet(@NonNull String... preferredFontFamilies) {
+        String acceptedFontFamily =
+                stream(preferredFontFamilies)
+                        .filter(SUPPORTED_FONT_FAMILIES::contains)
+                        .findFirst()
+                        .orElse(FONT_NAME_DEFAULT);
+        // Default font name would always be available.
+        FontSet defaultFontSet = checkNotNull(mFontFamilyToFontSet.get(FONT_NAME_DEFAULT));
+        return mFontFamilyToFontSet.getOrDefault(acceptedFontFamily, defaultFontSet);
     }
 
     /** Gets an Android Theme object styled with TextAppearance attributes. */
diff --git a/wear/protolayout/protolayout-renderer/src/main/res/values/attrs.xml b/wear/protolayout/protolayout-renderer/src/main/res/values/attrs.xml
index 021d774..58d4e9b 100644
--- a/wear/protolayout/protolayout-renderer/src/main/res/values/attrs.xml
+++ b/wear/protolayout/protolayout-renderer/src/main/res/values/attrs.xml
@@ -91,5 +91,8 @@
     <attr name="protoLayoutFallbackTextAppearance" format="reference" />
     <attr name="protoLayoutTitleFont" format="reference" />
     <attr name="protoLayoutBodyFont" format="reference" />
+    <attr name="protoLayoutDefaultSystemFont" format="reference" />
+    <attr name="protoLayoutRobotoFont" format="reference" />
+    <attr name="protoLayoutRobotoFlexFont" format="reference" />
   </declare-styleable>
 </resources>
diff --git a/wear/protolayout/protolayout-renderer/src/main/res/values/styles.xml b/wear/protolayout/protolayout-renderer/src/main/res/values/styles.xml
index 53bf66c..320e47a 100644
--- a/wear/protolayout/protolayout-renderer/src/main/res/values/styles.xml
+++ b/wear/protolayout/protolayout-renderer/src/main/res/values/styles.xml
@@ -12,9 +12,19 @@
     <item name="protoLayoutBoldFont">sans-serif</item>
   </style>
 
+  <style name="ProtoLayoutRobotoFont">
+    <item name="protoLayoutNormalFont">Roboto-Regular.ttf</item>
+    <item name="protoLayoutMediumFont">Roboto-Medium.ttf</item>
+    <item name="protoLayoutBoldFont">Roboto-Regular.ttf</item>
+  </style>
+
   <style name="ProtoLayoutBaseTheme">
     <item name="protoLayoutFallbackTextAppearance">@style/ProtoLayoutFallbackTextAppearance</item>
     <item name="protoLayoutTitleFont">@style/ProtoLayoutBaseFont</item>
     <item name="protoLayoutBodyFont">@style/ProtoLayoutBaseFont</item>
+    <item name="protoLayoutDefaultSystemFont">@style/ProtoLayoutBaseFont</item>
+    <item name="protoLayoutRobotoFont">@style/ProtoLayoutRobotoFont</item>
+<!--  TODO(b/348207120): Enable Roboto Flex font.  -->
+    <item name="protoLayoutRobotoFlexFont">@style/ProtoLayoutRobotoFont</item>
   </style>
 </resources>
diff --git a/wear/protolayout/protolayout-renderer/src/test/java/androidx/wear/protolayout/renderer/inflater/ProtoLayoutInflaterTest.java b/wear/protolayout/protolayout-renderer/src/test/java/androidx/wear/protolayout/renderer/inflater/ProtoLayoutInflaterTest.java
index 3979e64..7123baf 100644
--- a/wear/protolayout/protolayout-renderer/src/test/java/androidx/wear/protolayout/renderer/inflater/ProtoLayoutInflaterTest.java
+++ b/wear/protolayout/protolayout-renderer/src/test/java/androidx/wear/protolayout/renderer/inflater/ProtoLayoutInflaterTest.java
@@ -154,6 +154,8 @@
 import androidx.wear.protolayout.proto.LayoutElementProto.ColorFilter;
 import androidx.wear.protolayout.proto.LayoutElementProto.Column;
 import androidx.wear.protolayout.proto.LayoutElementProto.ExtensionLayoutElement;
+import androidx.wear.protolayout.proto.LayoutElementProto.FontFeatureSetting;
+import androidx.wear.protolayout.proto.LayoutElementProto.FontSetting;
 import androidx.wear.protolayout.proto.LayoutElementProto.FontStyle;
 import androidx.wear.protolayout.proto.LayoutElementProto.Image;
 import androidx.wear.protolayout.proto.LayoutElementProto.Layout;
@@ -233,6 +235,7 @@
 import org.robolectric.shadows.ShadowSystemClock;
 
 import java.io.IOException;
+import java.nio.ByteBuffer;
 import java.time.Duration;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -3095,6 +3098,40 @@
         expect.that(textView2.getMaxLines()).isEqualTo(3);
     }
 
+    // Typeface gets shadowed, so FontVariationSetting won't be set in TextView, as shadow returns
+    // null for supported axes.
+    @Test
+    public void inflate_textView_fontFeatureSetting() {
+        String textContents = "Text that is very large so it will go to many lines";
+        FontSetting.Builder randomSetting = FontSetting.newBuilder()
+                .setFeature(
+                        FontFeatureSetting.newBuilder()
+                                .setTag(ByteBuffer.wrap("rndm".getBytes(UTF_8)).getInt()));
+        FontSetting.Builder tnumSetting = FontSetting.newBuilder()
+                .setFeature(
+                        FontFeatureSetting.newBuilder()
+                                .setTag(ByteBuffer.wrap("tnum".getBytes(UTF_8)).getInt()));
+        Text.Builder text1 =
+                Text.newBuilder()
+                        .setLineHeight(sp(16))
+                        .setText(string(textContents))
+                        .setFontStyle(
+                                FontStyle.newBuilder()
+                                        .addSize(sp(16))
+                                        .addSettings(tnumSetting)
+                                        .addSettings(randomSetting));
+        Layout layout = fingerprintedLayout(LayoutElement.newBuilder().setText(text1).build());
+
+        // Initial layout.
+        Renderer renderer = renderer(layout);
+        ViewGroup inflatedViewParent = renderer.inflate();
+        TextView textView = (TextView) inflatedViewParent.getChildAt(0);
+
+        shadowOf(Looper.getMainLooper()).idle();
+
+        expect.that(textView.getFontFeatureSettings()).isEqualTo("'tnum'");
+    }
+
     private static Box.Builder buildFixedSizeBoxWIthText(Text.Builder content) {
         return Box.newBuilder()
                 .setWidth(ContainerDimension.newBuilder().setLinearDimension(dp(100)))
diff --git a/wear/protolayout/protolayout/api/1.2.0-beta01.txt b/wear/protolayout/protolayout/api/1.2.0-beta01.txt
new file mode 100644
index 0000000..721be43
--- /dev/null
+++ b/wear/protolayout/protolayout/api/1.2.0-beta01.txt
@@ -0,0 +1,1429 @@
+// Signature format: 4.0
+package androidx.wear.protolayout {
+
+  public final class ActionBuilders {
+    method public static androidx.wear.protolayout.ActionBuilders.AndroidBooleanExtra booleanExtra(boolean);
+    method public static androidx.wear.protolayout.ActionBuilders.AndroidDoubleExtra doubleExtra(double);
+    method public static androidx.wear.protolayout.ActionBuilders.AndroidIntExtra intExtra(int);
+    method public static androidx.wear.protolayout.ActionBuilders.LaunchAction launchAction(android.content.ComponentName);
+    method public static androidx.wear.protolayout.ActionBuilders.LaunchAction launchAction(android.content.ComponentName, java.util.Map<java.lang.String!,androidx.wear.protolayout.ActionBuilders.AndroidExtra!>);
+    method public static androidx.wear.protolayout.ActionBuilders.AndroidLongExtra longExtra(long);
+    method public static androidx.wear.protolayout.ActionBuilders.AndroidStringExtra stringExtra(String);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static interface ActionBuilders.Action {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ActionBuilders.AndroidActivity {
+    method public String getClassName();
+    method public java.util.Map<java.lang.String!,androidx.wear.protolayout.ActionBuilders.AndroidExtra!> getKeyToExtraMapping();
+    method public String getPackageName();
+  }
+
+  public static final class ActionBuilders.AndroidActivity.Builder {
+    ctor public ActionBuilders.AndroidActivity.Builder();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ActionBuilders.AndroidActivity.Builder addKeyToExtraMapping(String, androidx.wear.protolayout.ActionBuilders.AndroidExtra);
+    method public androidx.wear.protolayout.ActionBuilders.AndroidActivity build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ActionBuilders.AndroidActivity.Builder setClassName(String);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ActionBuilders.AndroidActivity.Builder setPackageName(String);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ActionBuilders.AndroidBooleanExtra implements androidx.wear.protolayout.ActionBuilders.AndroidExtra {
+    method public boolean getValue();
+  }
+
+  public static final class ActionBuilders.AndroidBooleanExtra.Builder {
+    ctor public ActionBuilders.AndroidBooleanExtra.Builder();
+    method public androidx.wear.protolayout.ActionBuilders.AndroidBooleanExtra build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ActionBuilders.AndroidBooleanExtra.Builder setValue(boolean);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ActionBuilders.AndroidDoubleExtra implements androidx.wear.protolayout.ActionBuilders.AndroidExtra {
+    method public double getValue();
+  }
+
+  public static final class ActionBuilders.AndroidDoubleExtra.Builder {
+    ctor public ActionBuilders.AndroidDoubleExtra.Builder();
+    method public androidx.wear.protolayout.ActionBuilders.AndroidDoubleExtra build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ActionBuilders.AndroidDoubleExtra.Builder setValue(double);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static interface ActionBuilders.AndroidExtra {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ActionBuilders.AndroidIntExtra implements androidx.wear.protolayout.ActionBuilders.AndroidExtra {
+    method public int getValue();
+  }
+
+  public static final class ActionBuilders.AndroidIntExtra.Builder {
+    ctor public ActionBuilders.AndroidIntExtra.Builder();
+    method public androidx.wear.protolayout.ActionBuilders.AndroidIntExtra build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ActionBuilders.AndroidIntExtra.Builder setValue(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ActionBuilders.AndroidLongExtra implements androidx.wear.protolayout.ActionBuilders.AndroidExtra {
+    method public long getValue();
+  }
+
+  public static final class ActionBuilders.AndroidLongExtra.Builder {
+    ctor public ActionBuilders.AndroidLongExtra.Builder();
+    method public androidx.wear.protolayout.ActionBuilders.AndroidLongExtra build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ActionBuilders.AndroidLongExtra.Builder setValue(long);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ActionBuilders.AndroidStringExtra implements androidx.wear.protolayout.ActionBuilders.AndroidExtra {
+    method public String getValue();
+  }
+
+  public static final class ActionBuilders.AndroidStringExtra.Builder {
+    ctor public ActionBuilders.AndroidStringExtra.Builder();
+    method public androidx.wear.protolayout.ActionBuilders.AndroidStringExtra build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ActionBuilders.AndroidStringExtra.Builder setValue(String);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ActionBuilders.LaunchAction implements androidx.wear.protolayout.ActionBuilders.Action {
+    method public androidx.wear.protolayout.ActionBuilders.AndroidActivity? getAndroidActivity();
+  }
+
+  public static final class ActionBuilders.LaunchAction.Builder {
+    ctor public ActionBuilders.LaunchAction.Builder();
+    method public androidx.wear.protolayout.ActionBuilders.LaunchAction build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ActionBuilders.LaunchAction.Builder setAndroidActivity(androidx.wear.protolayout.ActionBuilders.AndroidActivity);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ActionBuilders.LoadAction implements androidx.wear.protolayout.ActionBuilders.Action {
+    method public androidx.wear.protolayout.StateBuilders.State? getRequestState();
+  }
+
+  public static final class ActionBuilders.LoadAction.Builder {
+    ctor public ActionBuilders.LoadAction.Builder();
+    method public androidx.wear.protolayout.ActionBuilders.LoadAction build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ActionBuilders.LoadAction.Builder setRequestState(androidx.wear.protolayout.StateBuilders.State);
+  }
+
+  public final class ColorBuilders {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static androidx.wear.protolayout.ColorBuilders.ColorProp argb(@ColorInt int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public static interface ColorBuilders.Brush {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ColorBuilders.ColorProp {
+    method @ColorInt public int getArgb();
+    method public androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor? getDynamicValue();
+  }
+
+  public static final class ColorBuilders.ColorProp.Builder {
+    ctor @Deprecated public ColorBuilders.ColorProp.Builder();
+    ctor public ColorBuilders.ColorProp.Builder(@ColorInt int);
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ColorBuilders.ColorProp.Builder setArgb(@ColorInt int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ColorBuilders.ColorProp.Builder setDynamicValue(androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public static final class ColorBuilders.ColorStop {
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getColor();
+    method public androidx.wear.protolayout.TypeBuilders.FloatProp? getOffset();
+  }
+
+  public static final class ColorBuilders.ColorStop.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public ColorBuilders.ColorStop.Builder(androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.TypeBuilders.FloatProp);
+    method public androidx.wear.protolayout.ColorBuilders.ColorStop build();
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public static final class ColorBuilders.SweepGradient implements androidx.wear.protolayout.ColorBuilders.Brush {
+    method public java.util.List<androidx.wear.protolayout.ColorBuilders.ColorStop!> getColorStops();
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp getEndAngle();
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp getStartAngle();
+  }
+
+  public static final class ColorBuilders.SweepGradient.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) @java.lang.SafeVarargs public ColorBuilders.SweepGradient.Builder(androidx.wear.protolayout.ColorBuilders.ColorProp!...);
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) @java.lang.SafeVarargs public ColorBuilders.SweepGradient.Builder(androidx.wear.protolayout.ColorBuilders.ColorStop!...);
+    method public androidx.wear.protolayout.ColorBuilders.SweepGradient build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.ColorBuilders.SweepGradient.Builder setEndAngle(androidx.wear.protolayout.DimensionBuilders.DegreesProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.ColorBuilders.SweepGradient.Builder setStartAngle(androidx.wear.protolayout.DimensionBuilders.DegreesProp);
+  }
+
+  public final class DeviceParametersBuilders {
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int DEVICE_PLATFORM_UNDEFINED = 0; // 0x0
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int DEVICE_PLATFORM_WEAR_OS = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int SCREEN_SHAPE_RECT = 2; // 0x2
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int SCREEN_SHAPE_ROUND = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int SCREEN_SHAPE_UNDEFINED = 0; // 0x0
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class DeviceParametersBuilders.Capabilities {
+    method public long getMinimumFreshnessLimitMillis();
+  }
+
+  public static final class DeviceParametersBuilders.Capabilities.Builder {
+    ctor public DeviceParametersBuilders.Capabilities.Builder();
+    method public androidx.wear.protolayout.DeviceParametersBuilders.Capabilities build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DeviceParametersBuilders.Capabilities.Builder setMinimumFreshnessLimitMillis(long);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class DeviceParametersBuilders.DeviceParameters {
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental public androidx.wear.protolayout.DeviceParametersBuilders.Capabilities? getCapabilities();
+    method public int getDevicePlatform();
+    method @FloatRange(from=0.0, fromInclusive=false, toInclusive=false) public float getFontScale();
+    method public androidx.wear.protolayout.expression.VersionBuilders.VersionInfo getRendererSchemaVersion();
+    method @FloatRange(from=0.0, fromInclusive=false, toInclusive=false) public float getScreenDensity();
+    method @Dimension(unit=androidx.annotation.Dimension.DP) public int getScreenHeightDp();
+    method public int getScreenShape();
+    method @Dimension(unit=androidx.annotation.Dimension.DP) public int getScreenWidthDp();
+  }
+
+  public static final class DeviceParametersBuilders.DeviceParameters.Builder {
+    ctor public DeviceParametersBuilders.DeviceParameters.Builder();
+    method public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters build();
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setCapabilities(androidx.wear.protolayout.DeviceParametersBuilders.Capabilities);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setDevicePlatform(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setFontScale(@FloatRange(from=0.0, fromInclusive=false, toInclusive=false) float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setRendererSchemaVersion(androidx.wear.protolayout.expression.VersionBuilders.VersionInfo);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setScreenDensity(@FloatRange(from=0.0, fromInclusive=false, toInclusive=false) float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setScreenHeightDp(@Dimension(unit=androidx.annotation.Dimension.DP) int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setScreenShape(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setScreenWidthDp(@Dimension(unit=androidx.annotation.Dimension.DP) int);
+  }
+
+  public final class DimensionBuilders {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static androidx.wear.protolayout.DimensionBuilders.DegreesProp degrees(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static androidx.wear.protolayout.DimensionBuilders.DpProp dp(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static androidx.wear.protolayout.DimensionBuilders.EmProp em(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static androidx.wear.protolayout.DimensionBuilders.EmProp em(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static androidx.wear.protolayout.DimensionBuilders.ExpandedDimensionProp expand();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static androidx.wear.protolayout.DimensionBuilders.SpProp sp(@Dimension(unit=androidx.annotation.Dimension.SP) float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public static androidx.wear.protolayout.DimensionBuilders.ExpandedDimensionProp weight(@FloatRange(from=0.0) float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static androidx.wear.protolayout.DimensionBuilders.WrappedDimensionProp wrap();
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class DimensionBuilders.AngularLayoutConstraint {
+    method public int getAngularAlignment();
+    method @Dimension(unit=androidx.annotation.Dimension.DP) public float getValue();
+  }
+
+  public static final class DimensionBuilders.AngularLayoutConstraint.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public DimensionBuilders.AngularLayoutConstraint.Builder(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method public androidx.wear.protolayout.DimensionBuilders.AngularLayoutConstraint build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DimensionBuilders.AngularLayoutConstraint.Builder setAngularAlignment(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static final class DimensionBuilders.BoundingBoxRatio implements androidx.wear.protolayout.DimensionBuilders.PivotDimension {
+    method public androidx.wear.protolayout.TypeBuilders.FloatProp getRatio();
+  }
+
+  public static final class DimensionBuilders.BoundingBoxRatio.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public DimensionBuilders.BoundingBoxRatio.Builder(androidx.wear.protolayout.TypeBuilders.FloatProp);
+    method public androidx.wear.protolayout.DimensionBuilders.BoundingBoxRatio build();
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static interface DimensionBuilders.ContainerDimension {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class DimensionBuilders.DegreesProp {
+    method public androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat? getDynamicValue();
+    method public float getValue();
+  }
+
+  public static final class DimensionBuilders.DegreesProp.Builder {
+    ctor @Deprecated public DimensionBuilders.DegreesProp.Builder();
+    ctor public DimensionBuilders.DegreesProp.Builder(float);
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DimensionBuilders.DegreesProp.Builder setDynamicValue(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DimensionBuilders.DegreesProp.Builder setValue(float);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class DimensionBuilders.DpProp implements androidx.wear.protolayout.DimensionBuilders.ContainerDimension androidx.wear.protolayout.DimensionBuilders.ExtensionDimension androidx.wear.protolayout.DimensionBuilders.ImageDimension androidx.wear.protolayout.DimensionBuilders.PivotDimension androidx.wear.protolayout.DimensionBuilders.SpacerDimension {
+    method public androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat? getDynamicValue();
+    method @Dimension(unit=androidx.annotation.Dimension.DP) public float getValue();
+  }
+
+  public static final class DimensionBuilders.DpProp.Builder {
+    ctor @Deprecated public DimensionBuilders.DpProp.Builder();
+    ctor public DimensionBuilders.DpProp.Builder(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DimensionBuilders.DpProp.Builder setDynamicValue(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DimensionBuilders.DpProp.Builder setValue(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class DimensionBuilders.EmProp {
+    method public float getValue();
+  }
+
+  public static final class DimensionBuilders.EmProp.Builder {
+    ctor public DimensionBuilders.EmProp.Builder();
+    method public androidx.wear.protolayout.DimensionBuilders.EmProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DimensionBuilders.EmProp.Builder setValue(float);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class DimensionBuilders.ExpandedDimensionProp implements androidx.wear.protolayout.DimensionBuilders.ContainerDimension androidx.wear.protolayout.DimensionBuilders.ImageDimension androidx.wear.protolayout.DimensionBuilders.SpacerDimension {
+    method public androidx.wear.protolayout.TypeBuilders.FloatProp? getLayoutWeight();
+  }
+
+  public static final class DimensionBuilders.ExpandedDimensionProp.Builder {
+    ctor public DimensionBuilders.ExpandedDimensionProp.Builder();
+    method public androidx.wear.protolayout.DimensionBuilders.ExpandedDimensionProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DimensionBuilders.ExpandedDimensionProp.Builder setLayoutWeight(androidx.wear.protolayout.TypeBuilders.FloatProp);
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ExperimentalProtoLayoutExtensionApi @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static interface DimensionBuilders.ExtensionDimension {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class DimensionBuilders.HorizontalLayoutConstraint {
+    method public int getHorizontalAlignment();
+    method @Dimension(unit=androidx.annotation.Dimension.DP) public float getValue();
+  }
+
+  public static final class DimensionBuilders.HorizontalLayoutConstraint.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public DimensionBuilders.HorizontalLayoutConstraint.Builder(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method public androidx.wear.protolayout.DimensionBuilders.HorizontalLayoutConstraint build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DimensionBuilders.HorizontalLayoutConstraint.Builder setHorizontalAlignment(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static interface DimensionBuilders.ImageDimension {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static interface DimensionBuilders.PivotDimension {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class DimensionBuilders.ProportionalDimensionProp implements androidx.wear.protolayout.DimensionBuilders.ImageDimension {
+    method @IntRange(from=0) public int getAspectRatioHeight();
+    method @IntRange(from=0) public int getAspectRatioWidth();
+  }
+
+  public static final class DimensionBuilders.ProportionalDimensionProp.Builder {
+    ctor public DimensionBuilders.ProportionalDimensionProp.Builder();
+    method public androidx.wear.protolayout.DimensionBuilders.ProportionalDimensionProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DimensionBuilders.ProportionalDimensionProp.Builder setAspectRatioHeight(@IntRange(from=0) int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DimensionBuilders.ProportionalDimensionProp.Builder setAspectRatioWidth(@IntRange(from=0) int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class DimensionBuilders.SpProp {
+    method @Dimension(unit=androidx.annotation.Dimension.SP) public float getValue();
+  }
+
+  public static final class DimensionBuilders.SpProp.Builder {
+    ctor public DimensionBuilders.SpProp.Builder();
+    method public androidx.wear.protolayout.DimensionBuilders.SpProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DimensionBuilders.SpProp.Builder setValue(@Dimension(unit=androidx.annotation.Dimension.SP) float);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static interface DimensionBuilders.SpacerDimension {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class DimensionBuilders.VerticalLayoutConstraint {
+    method @Dimension(unit=androidx.annotation.Dimension.DP) public float getValue();
+    method public int getVerticalAlignment();
+  }
+
+  public static final class DimensionBuilders.VerticalLayoutConstraint.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public DimensionBuilders.VerticalLayoutConstraint.Builder(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method public androidx.wear.protolayout.DimensionBuilders.VerticalLayoutConstraint build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DimensionBuilders.VerticalLayoutConstraint.Builder setVerticalAlignment(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class DimensionBuilders.WrappedDimensionProp implements androidx.wear.protolayout.DimensionBuilders.ContainerDimension {
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp? getMinimumSize();
+  }
+
+  public static final class DimensionBuilders.WrappedDimensionProp.Builder {
+    ctor public DimensionBuilders.WrappedDimensionProp.Builder();
+    method public androidx.wear.protolayout.DimensionBuilders.WrappedDimensionProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DimensionBuilders.WrappedDimensionProp.Builder setMinimumSize(androidx.wear.protolayout.DimensionBuilders.DpProp);
+  }
+
+  public final class LayoutElementBuilders {
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int ANGULAR_ALIGNMENT_CENTER = 2; // 0x2
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int ANGULAR_ALIGNMENT_END = 3; // 0x3
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int ANGULAR_ALIGNMENT_START = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int ANGULAR_ALIGNMENT_UNDEFINED = 0; // 0x0
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int ARC_ANCHOR_CENTER = 2; // 0x2
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int ARC_ANCHOR_END = 3; // 0x3
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int ARC_ANCHOR_START = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int ARC_ANCHOR_UNDEFINED = 0; // 0x0
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int CONTENT_SCALE_MODE_CROP = 2; // 0x2
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int CONTENT_SCALE_MODE_FILL_BOUNDS = 3; // 0x3
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int CONTENT_SCALE_MODE_FIT = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int CONTENT_SCALE_MODE_UNDEFINED = 0; // 0x0
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int FONT_VARIANT_BODY = 2; // 0x2
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int FONT_VARIANT_TITLE = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int FONT_VARIANT_UNDEFINED = 0; // 0x0
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int FONT_WEIGHT_BOLD = 700; // 0x2bc
+    field @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int FONT_WEIGHT_MEDIUM = 500; // 0x1f4
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int FONT_WEIGHT_NORMAL = 400; // 0x190
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int FONT_WEIGHT_UNDEFINED = 0; // 0x0
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int HORIZONTAL_ALIGN_CENTER = 2; // 0x2
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int HORIZONTAL_ALIGN_END = 5; // 0x5
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int HORIZONTAL_ALIGN_LEFT = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int HORIZONTAL_ALIGN_RIGHT = 3; // 0x3
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int HORIZONTAL_ALIGN_START = 4; // 0x4
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int HORIZONTAL_ALIGN_UNDEFINED = 0; // 0x0
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int SPAN_VERTICAL_ALIGN_BOTTOM = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int SPAN_VERTICAL_ALIGN_TEXT_BASELINE = 2; // 0x2
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int SPAN_VERTICAL_ALIGN_UNDEFINED = 0; // 0x0
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int STROKE_CAP_BUTT = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int STROKE_CAP_ROUND = 2; // 0x2
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int STROKE_CAP_SQUARE = 3; // 0x3
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int STROKE_CAP_UNDEFINED = 0; // 0x0
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int TEXT_ALIGN_CENTER = 2; // 0x2
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int TEXT_ALIGN_END = 3; // 0x3
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int TEXT_ALIGN_START = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int TEXT_ALIGN_UNDEFINED = 0; // 0x0
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public static final int TEXT_OVERFLOW_ELLIPSIZE = 4; // 0x4
+    field @Deprecated @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int TEXT_OVERFLOW_ELLIPSIZE_END = 2; // 0x2
+    field @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int TEXT_OVERFLOW_MARQUEE = 3; // 0x3
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int TEXT_OVERFLOW_TRUNCATE = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int TEXT_OVERFLOW_UNDEFINED = 0; // 0x0
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int VERTICAL_ALIGN_BOTTOM = 3; // 0x3
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int VERTICAL_ALIGN_CENTER = 2; // 0x2
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int VERTICAL_ALIGN_TOP = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int VERTICAL_ALIGN_UNDEFINED = 0; // 0x0
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.Arc implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp? getAnchorAngle();
+    method public androidx.wear.protolayout.LayoutElementBuilders.ArcAnchorTypeProp? getAnchorType();
+    method public androidx.wear.protolayout.LayoutElementBuilders.ArcDirectionProp? getArcDirection();
+    method public java.util.List<androidx.wear.protolayout.LayoutElementBuilders.ArcLayoutElement!> getContents();
+    method public androidx.wear.protolayout.ModifiersBuilders.Modifiers? getModifiers();
+    method public androidx.wear.protolayout.LayoutElementBuilders.VerticalAlignmentProp? getVerticalAlign();
+  }
+
+  public static final class LayoutElementBuilders.Arc.Builder {
+    ctor public LayoutElementBuilders.Arc.Builder();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Arc.Builder addContent(androidx.wear.protolayout.LayoutElementBuilders.ArcLayoutElement);
+    method public androidx.wear.protolayout.LayoutElementBuilders.Arc build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Arc.Builder setAnchorAngle(androidx.wear.protolayout.DimensionBuilders.DegreesProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Arc.Builder setAnchorType(androidx.wear.protolayout.LayoutElementBuilders.ArcAnchorTypeProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Arc.Builder setAnchorType(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.LayoutElementBuilders.Arc.Builder setArcDirection(androidx.wear.protolayout.LayoutElementBuilders.ArcDirectionProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.LayoutElementBuilders.Arc.Builder setArcDirection(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Arc.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.Modifiers);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Arc.Builder setVerticalAlign(androidx.wear.protolayout.LayoutElementBuilders.VerticalAlignmentProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Arc.Builder setVerticalAlign(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.ArcAdapter implements androidx.wear.protolayout.LayoutElementBuilders.ArcLayoutElement {
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getContent();
+    method public androidx.wear.protolayout.TypeBuilders.BoolProp? getRotateContents();
+  }
+
+  public static final class LayoutElementBuilders.ArcAdapter.Builder {
+    ctor public LayoutElementBuilders.ArcAdapter.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.ArcAdapter build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ArcAdapter.Builder setContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ArcAdapter.Builder setRotateContents(androidx.wear.protolayout.TypeBuilders.BoolProp);
+    method public androidx.wear.protolayout.LayoutElementBuilders.ArcAdapter.Builder setRotateContents(boolean);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.ArcAnchorTypeProp {
+    method public int getValue();
+  }
+
+  public static final class LayoutElementBuilders.ArcAnchorTypeProp.Builder {
+    ctor public LayoutElementBuilders.ArcAnchorTypeProp.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.ArcAnchorTypeProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ArcAnchorTypeProp.Builder setValue(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public static final class LayoutElementBuilders.ArcDirectionProp {
+    method public int getValue();
+  }
+
+  public static final class LayoutElementBuilders.ArcDirectionProp.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public LayoutElementBuilders.ArcDirectionProp.Builder(int);
+    method public androidx.wear.protolayout.LayoutElementBuilders.ArcDirectionProp build();
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static interface LayoutElementBuilders.ArcLayoutElement {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.ArcLine implements androidx.wear.protolayout.LayoutElementBuilders.ArcLayoutElement {
+    method public androidx.wear.protolayout.LayoutElementBuilders.ArcDirectionProp? getArcDirection();
+    method public androidx.wear.protolayout.ColorBuilders.Brush? getBrush();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp? getColor();
+    method public androidx.wear.protolayout.DimensionBuilders.AngularLayoutConstraint? getLayoutConstraintsForDynamicLength();
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp? getLength();
+    method public androidx.wear.protolayout.ModifiersBuilders.ArcModifiers? getModifiers();
+    method public androidx.wear.protolayout.LayoutElementBuilders.StrokeCapProp? getStrokeCap();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp? getThickness();
+  }
+
+  public static final class LayoutElementBuilders.ArcLine.Builder {
+    ctor public LayoutElementBuilders.ArcLine.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.ArcLine build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.LayoutElementBuilders.ArcLine.Builder setArcDirection(androidx.wear.protolayout.LayoutElementBuilders.ArcDirectionProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.LayoutElementBuilders.ArcLine.Builder setArcDirection(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.LayoutElementBuilders.ArcLine.Builder setBrush(androidx.wear.protolayout.ColorBuilders.Brush);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ArcLine.Builder setColor(androidx.wear.protolayout.ColorBuilders.ColorProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.ArcLine.Builder setLayoutConstraintsForDynamicLength(androidx.wear.protolayout.DimensionBuilders.AngularLayoutConstraint);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ArcLine.Builder setLength(androidx.wear.protolayout.DimensionBuilders.DegreesProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ArcLine.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.ArcModifiers);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.ArcLine.Builder setStrokeCap(androidx.wear.protolayout.LayoutElementBuilders.StrokeCapProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.ArcLine.Builder setStrokeCap(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ArcLine.Builder setThickness(androidx.wear.protolayout.DimensionBuilders.DpProp);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.ArcSpacer implements androidx.wear.protolayout.LayoutElementBuilders.ArcLayoutElement {
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp? getLength();
+    method public androidx.wear.protolayout.ModifiersBuilders.ArcModifiers? getModifiers();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp? getThickness();
+  }
+
+  public static final class LayoutElementBuilders.ArcSpacer.Builder {
+    ctor public LayoutElementBuilders.ArcSpacer.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.ArcSpacer build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ArcSpacer.Builder setLength(androidx.wear.protolayout.DimensionBuilders.DegreesProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ArcSpacer.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.ArcModifiers);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ArcSpacer.Builder setThickness(androidx.wear.protolayout.DimensionBuilders.DpProp);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.ArcText implements androidx.wear.protolayout.LayoutElementBuilders.ArcLayoutElement {
+    method public androidx.wear.protolayout.LayoutElementBuilders.ArcDirectionProp? getArcDirection();
+    method public androidx.wear.protolayout.LayoutElementBuilders.FontStyle? getFontStyle();
+    method public androidx.wear.protolayout.ModifiersBuilders.ArcModifiers? getModifiers();
+    method public androidx.wear.protolayout.TypeBuilders.StringProp? getText();
+  }
+
+  public static final class LayoutElementBuilders.ArcText.Builder {
+    ctor public LayoutElementBuilders.ArcText.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.ArcText build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.LayoutElementBuilders.ArcText.Builder setArcDirection(androidx.wear.protolayout.LayoutElementBuilders.ArcDirectionProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.LayoutElementBuilders.ArcText.Builder setArcDirection(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ArcText.Builder setFontStyle(androidx.wear.protolayout.LayoutElementBuilders.FontStyle);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ArcText.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.ArcModifiers);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ArcText.Builder setText(androidx.wear.protolayout.TypeBuilders.StringProp);
+    method public androidx.wear.protolayout.LayoutElementBuilders.ArcText.Builder setText(String);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.Box implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public java.util.List<androidx.wear.protolayout.LayoutElementBuilders.LayoutElement!> getContents();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension? getHeight();
+    method public androidx.wear.protolayout.LayoutElementBuilders.HorizontalAlignmentProp? getHorizontalAlignment();
+    method public androidx.wear.protolayout.ModifiersBuilders.Modifiers? getModifiers();
+    method public androidx.wear.protolayout.LayoutElementBuilders.VerticalAlignmentProp? getVerticalAlignment();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension? getWidth();
+  }
+
+  public static final class LayoutElementBuilders.Box.Builder {
+    ctor public LayoutElementBuilders.Box.Builder();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Box.Builder addContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.LayoutElementBuilders.Box build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Box.Builder setHeight(androidx.wear.protolayout.DimensionBuilders.ContainerDimension);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Box.Builder setHorizontalAlignment(androidx.wear.protolayout.LayoutElementBuilders.HorizontalAlignmentProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Box.Builder setHorizontalAlignment(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Box.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.Modifiers);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Box.Builder setVerticalAlignment(androidx.wear.protolayout.LayoutElementBuilders.VerticalAlignmentProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Box.Builder setVerticalAlignment(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Box.Builder setWidth(androidx.wear.protolayout.DimensionBuilders.ContainerDimension);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.ColorFilter {
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp? getTint();
+  }
+
+  public static final class LayoutElementBuilders.ColorFilter.Builder {
+    ctor public LayoutElementBuilders.ColorFilter.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.ColorFilter build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ColorFilter.Builder setTint(androidx.wear.protolayout.ColorBuilders.ColorProp);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.Column implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public java.util.List<androidx.wear.protolayout.LayoutElementBuilders.LayoutElement!> getContents();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension? getHeight();
+    method public androidx.wear.protolayout.LayoutElementBuilders.HorizontalAlignmentProp? getHorizontalAlignment();
+    method public androidx.wear.protolayout.ModifiersBuilders.Modifiers? getModifiers();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension? getWidth();
+  }
+
+  public static final class LayoutElementBuilders.Column.Builder {
+    ctor public LayoutElementBuilders.Column.Builder();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Column.Builder addContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.LayoutElementBuilders.Column build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Column.Builder setHeight(androidx.wear.protolayout.DimensionBuilders.ContainerDimension);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Column.Builder setHorizontalAlignment(androidx.wear.protolayout.LayoutElementBuilders.HorizontalAlignmentProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Column.Builder setHorizontalAlignment(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Column.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.Modifiers);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Column.Builder setWidth(androidx.wear.protolayout.DimensionBuilders.ContainerDimension);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.ContentScaleModeProp {
+    method public int getValue();
+  }
+
+  public static final class LayoutElementBuilders.ContentScaleModeProp.Builder {
+    ctor public LayoutElementBuilders.ContentScaleModeProp.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.ContentScaleModeProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ContentScaleModeProp.Builder setValue(int);
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ExperimentalProtoLayoutExtensionApi @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class LayoutElementBuilders.ExtensionLayoutElement implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public String getExtensionId();
+    method public androidx.wear.protolayout.DimensionBuilders.ExtensionDimension? getHeight();
+    method public byte[] getPayload();
+    method public androidx.wear.protolayout.DimensionBuilders.ExtensionDimension? getWidth();
+  }
+
+  public static final class LayoutElementBuilders.ExtensionLayoutElement.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public LayoutElementBuilders.ExtensionLayoutElement.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.ExtensionLayoutElement build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.ExtensionLayoutElement.Builder setExtensionId(String);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.ExtensionLayoutElement.Builder setHeight(androidx.wear.protolayout.DimensionBuilders.ExtensionDimension);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.ExtensionLayoutElement.Builder setPayload(byte[]);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.ExtensionLayoutElement.Builder setWidth(androidx.wear.protolayout.DimensionBuilders.ExtensionDimension);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static interface LayoutElementBuilders.FontSetting {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static androidx.wear.protolayout.LayoutElementBuilders.FontSetting tabularNum();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static androidx.wear.protolayout.LayoutElementBuilders.FontSetting weight(@IntRange(from=1, to=1000) int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static androidx.wear.protolayout.LayoutElementBuilders.FontSetting width(@FloatRange(from=25, to=200) float);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.FontStyle {
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp? getColor();
+    method public androidx.wear.protolayout.TypeBuilders.BoolProp? getItalic();
+    method public androidx.wear.protolayout.DimensionBuilders.EmProp? getLetterSpacing();
+    method public java.util.List<java.lang.String!> getPreferredFontFamilies();
+    method public java.util.List<androidx.wear.protolayout.LayoutElementBuilders.FontSetting!> getSettings();
+    method public androidx.wear.protolayout.DimensionBuilders.SpProp? getSize();
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental public java.util.List<androidx.wear.protolayout.DimensionBuilders.SpProp!> getSizes();
+    method public androidx.wear.protolayout.TypeBuilders.BoolProp? getUnderline();
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental public androidx.wear.protolayout.LayoutElementBuilders.FontVariantProp? getVariant();
+    method public androidx.wear.protolayout.LayoutElementBuilders.FontWeightProp? getWeight();
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static final String ROBOTO_FLEX_FONT = "roboto-flex";
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static final String ROBOTO_FONT = "roboto";
+  }
+
+  public static final class LayoutElementBuilders.FontStyle.Builder {
+    ctor public LayoutElementBuilders.FontStyle.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.FontStyle build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder setColor(androidx.wear.protolayout.ColorBuilders.ColorProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder setItalic(androidx.wear.protolayout.TypeBuilders.BoolProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder setItalic(boolean);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder setLetterSpacing(androidx.wear.protolayout.DimensionBuilders.EmProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder setPreferredFontFamilies(String, java.lang.String!...);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder setSettings(androidx.wear.protolayout.LayoutElementBuilders.FontSetting!...);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder setSize(androidx.wear.protolayout.DimensionBuilders.SpProp);
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder setSizes(@Dimension(unit=androidx.annotation.Dimension.SP) @IntRange(from=1) int...);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder setUnderline(androidx.wear.protolayout.TypeBuilders.BoolProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder setUnderline(boolean);
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder setVariant(androidx.wear.protolayout.LayoutElementBuilders.FontVariantProp);
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder setVariant(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder setWeight(androidx.wear.protolayout.LayoutElementBuilders.FontWeightProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder setWeight(int);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.FontStyles {
+    method @Deprecated public static androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder body1(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder body2(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder button(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder caption1(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder caption2(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder display1(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder display2(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder display3(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder title1(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder title2(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder title3(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.FontVariantProp {
+    method public int getValue();
+  }
+
+  public static final class LayoutElementBuilders.FontVariantProp.Builder {
+    ctor public LayoutElementBuilders.FontVariantProp.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.FontVariantProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.FontVariantProp.Builder setValue(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.FontWeightProp {
+    method public int getValue();
+  }
+
+  public static final class LayoutElementBuilders.FontWeightProp.Builder {
+    ctor public LayoutElementBuilders.FontWeightProp.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.FontWeightProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.FontWeightProp.Builder setValue(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.HorizontalAlignmentProp {
+    method public int getValue();
+  }
+
+  public static final class LayoutElementBuilders.HorizontalAlignmentProp.Builder {
+    ctor public LayoutElementBuilders.HorizontalAlignmentProp.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.HorizontalAlignmentProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.HorizontalAlignmentProp.Builder setValue(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.Image implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public androidx.wear.protolayout.LayoutElementBuilders.ColorFilter? getColorFilter();
+    method public androidx.wear.protolayout.LayoutElementBuilders.ContentScaleModeProp? getContentScaleMode();
+    method public androidx.wear.protolayout.DimensionBuilders.ImageDimension? getHeight();
+    method public androidx.wear.protolayout.ModifiersBuilders.Modifiers? getModifiers();
+    method public androidx.wear.protolayout.TypeBuilders.StringProp? getResourceId();
+    method public androidx.wear.protolayout.DimensionBuilders.ImageDimension? getWidth();
+  }
+
+  public static final class LayoutElementBuilders.Image.Builder {
+    ctor public LayoutElementBuilders.Image.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.Image build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Image.Builder setColorFilter(androidx.wear.protolayout.LayoutElementBuilders.ColorFilter);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Image.Builder setContentScaleMode(androidx.wear.protolayout.LayoutElementBuilders.ContentScaleModeProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Image.Builder setContentScaleMode(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Image.Builder setHeight(androidx.wear.protolayout.DimensionBuilders.ImageDimension);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Image.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.Modifiers);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Image.Builder setResourceId(androidx.wear.protolayout.TypeBuilders.StringProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Image.Builder setResourceId(String);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Image.Builder setWidth(androidx.wear.protolayout.DimensionBuilders.ImageDimension);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.Layout {
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental public static androidx.wear.protolayout.LayoutElementBuilders.Layout? fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.LayoutElementBuilders.Layout fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getRoot();
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental public byte[] toByteArray();
+  }
+
+  public static final class LayoutElementBuilders.Layout.Builder {
+    ctor public LayoutElementBuilders.Layout.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.Layout build();
+    method public androidx.wear.protolayout.LayoutElementBuilders.Layout.Builder setRoot(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static interface LayoutElementBuilders.LayoutElement {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.Row implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public java.util.List<androidx.wear.protolayout.LayoutElementBuilders.LayoutElement!> getContents();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension? getHeight();
+    method public androidx.wear.protolayout.ModifiersBuilders.Modifiers? getModifiers();
+    method public androidx.wear.protolayout.LayoutElementBuilders.VerticalAlignmentProp? getVerticalAlignment();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension? getWidth();
+  }
+
+  public static final class LayoutElementBuilders.Row.Builder {
+    ctor public LayoutElementBuilders.Row.Builder();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Row.Builder addContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.LayoutElementBuilders.Row build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Row.Builder setHeight(androidx.wear.protolayout.DimensionBuilders.ContainerDimension);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Row.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.Modifiers);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Row.Builder setVerticalAlignment(androidx.wear.protolayout.LayoutElementBuilders.VerticalAlignmentProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Row.Builder setVerticalAlignment(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Row.Builder setWidth(androidx.wear.protolayout.DimensionBuilders.ContainerDimension);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.Spacer implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public androidx.wear.protolayout.DimensionBuilders.SpacerDimension? getHeight();
+    method public androidx.wear.protolayout.DimensionBuilders.VerticalLayoutConstraint? getLayoutConstraintsForDynamicHeight();
+    method public androidx.wear.protolayout.DimensionBuilders.HorizontalLayoutConstraint? getLayoutConstraintsForDynamicWidth();
+    method public androidx.wear.protolayout.ModifiersBuilders.Modifiers? getModifiers();
+    method public androidx.wear.protolayout.DimensionBuilders.SpacerDimension? getWidth();
+  }
+
+  public static final class LayoutElementBuilders.Spacer.Builder {
+    ctor public LayoutElementBuilders.Spacer.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.Spacer build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Spacer.Builder setHeight(androidx.wear.protolayout.DimensionBuilders.SpacerDimension);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.Spacer.Builder setLayoutConstraintsForDynamicHeight(androidx.wear.protolayout.DimensionBuilders.VerticalLayoutConstraint);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.Spacer.Builder setLayoutConstraintsForDynamicWidth(androidx.wear.protolayout.DimensionBuilders.HorizontalLayoutConstraint);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Spacer.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.Modifiers);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Spacer.Builder setWidth(androidx.wear.protolayout.DimensionBuilders.SpacerDimension);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static interface LayoutElementBuilders.Span {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.SpanImage implements androidx.wear.protolayout.LayoutElementBuilders.Span {
+    method public androidx.wear.protolayout.LayoutElementBuilders.SpanVerticalAlignmentProp? getAlignment();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp? getHeight();
+    method public androidx.wear.protolayout.ModifiersBuilders.SpanModifiers? getModifiers();
+    method public androidx.wear.protolayout.TypeBuilders.StringProp? getResourceId();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp? getWidth();
+  }
+
+  public static final class LayoutElementBuilders.SpanImage.Builder {
+    ctor public LayoutElementBuilders.SpanImage.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.SpanImage build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.SpanImage.Builder setAlignment(androidx.wear.protolayout.LayoutElementBuilders.SpanVerticalAlignmentProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.SpanImage.Builder setAlignment(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.SpanImage.Builder setHeight(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.SpanImage.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.SpanModifiers);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.SpanImage.Builder setResourceId(androidx.wear.protolayout.TypeBuilders.StringProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.SpanImage.Builder setResourceId(String);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.SpanImage.Builder setWidth(androidx.wear.protolayout.DimensionBuilders.DpProp);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.SpanText implements androidx.wear.protolayout.LayoutElementBuilders.Span {
+    method public androidx.wear.protolayout.LayoutElementBuilders.FontStyle? getFontStyle();
+    method public androidx.wear.protolayout.ModifiersBuilders.SpanModifiers? getModifiers();
+    method public androidx.wear.protolayout.TypeBuilders.StringProp? getText();
+  }
+
+  public static final class LayoutElementBuilders.SpanText.Builder {
+    ctor public LayoutElementBuilders.SpanText.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.SpanText build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.SpanText.Builder setFontStyle(androidx.wear.protolayout.LayoutElementBuilders.FontStyle);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.SpanText.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.SpanModifiers);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.SpanText.Builder setText(androidx.wear.protolayout.TypeBuilders.StringProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.SpanText.Builder setText(String);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.SpanVerticalAlignmentProp {
+    method public int getValue();
+  }
+
+  public static final class LayoutElementBuilders.SpanVerticalAlignmentProp.Builder {
+    ctor public LayoutElementBuilders.SpanVerticalAlignmentProp.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.SpanVerticalAlignmentProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.SpanVerticalAlignmentProp.Builder setValue(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.Spannable implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public androidx.wear.protolayout.DimensionBuilders.SpProp? getLineHeight();
+    method @SuppressCompatibility @IntRange(from=0xffffffff) @androidx.wear.protolayout.expression.ProtoLayoutExperimental public int getMarqueeIterations();
+    method public androidx.wear.protolayout.TypeBuilders.Int32Prop? getMaxLines();
+    method public androidx.wear.protolayout.ModifiersBuilders.Modifiers? getModifiers();
+    method public androidx.wear.protolayout.LayoutElementBuilders.HorizontalAlignmentProp? getMultilineAlignment();
+    method public androidx.wear.protolayout.LayoutElementBuilders.TextOverflowProp? getOverflow();
+    method public java.util.List<androidx.wear.protolayout.LayoutElementBuilders.Span!> getSpans();
+  }
+
+  public static final class LayoutElementBuilders.Spannable.Builder {
+    ctor public LayoutElementBuilders.Spannable.Builder();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Spannable.Builder addSpan(androidx.wear.protolayout.LayoutElementBuilders.Span);
+    method public androidx.wear.protolayout.LayoutElementBuilders.Spannable build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Spannable.Builder setLineHeight(androidx.wear.protolayout.DimensionBuilders.SpProp);
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.Spannable.Builder setMarqueeIterations(@IntRange(from=0xffffffff) int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Spannable.Builder setMaxLines(androidx.wear.protolayout.TypeBuilders.Int32Prop);
+    method public androidx.wear.protolayout.LayoutElementBuilders.Spannable.Builder setMaxLines(@IntRange(from=1) int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Spannable.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.Modifiers);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Spannable.Builder setMultilineAlignment(androidx.wear.protolayout.LayoutElementBuilders.HorizontalAlignmentProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Spannable.Builder setMultilineAlignment(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Spannable.Builder setOverflow(androidx.wear.protolayout.LayoutElementBuilders.TextOverflowProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Spannable.Builder setOverflow(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class LayoutElementBuilders.StrokeCapProp {
+    method public androidx.wear.protolayout.ModifiersBuilders.Shadow? getShadow();
+    method public int getValue();
+  }
+
+  public static final class LayoutElementBuilders.StrokeCapProp.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public LayoutElementBuilders.StrokeCapProp.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.StrokeCapProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.LayoutElementBuilders.StrokeCapProp.Builder setShadow(androidx.wear.protolayout.ModifiersBuilders.Shadow);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.StrokeCapProp.Builder setValue(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.Text implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public androidx.wear.protolayout.LayoutElementBuilders.FontStyle? getFontStyle();
+    method public androidx.wear.protolayout.TypeBuilders.StringLayoutConstraint? getLayoutConstraintsForDynamicText();
+    method public androidx.wear.protolayout.DimensionBuilders.SpProp? getLineHeight();
+    method @SuppressCompatibility @IntRange(from=0xffffffff) @androidx.wear.protolayout.expression.ProtoLayoutExperimental public int getMarqueeIterations();
+    method public androidx.wear.protolayout.TypeBuilders.Int32Prop? getMaxLines();
+    method public androidx.wear.protolayout.ModifiersBuilders.Modifiers? getModifiers();
+    method public androidx.wear.protolayout.LayoutElementBuilders.TextAlignmentProp? getMultilineAlignment();
+    method public androidx.wear.protolayout.LayoutElementBuilders.TextOverflowProp? getOverflow();
+    method public androidx.wear.protolayout.TypeBuilders.StringProp? getText();
+  }
+
+  public static final class LayoutElementBuilders.Text.Builder {
+    ctor public LayoutElementBuilders.Text.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.Text build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Text.Builder setFontStyle(androidx.wear.protolayout.LayoutElementBuilders.FontStyle);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.Text.Builder setLayoutConstraintsForDynamicText(androidx.wear.protolayout.TypeBuilders.StringLayoutConstraint);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Text.Builder setLineHeight(androidx.wear.protolayout.DimensionBuilders.SpProp);
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.Text.Builder setMarqueeIterations(@IntRange(from=0xffffffff) int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Text.Builder setMaxLines(androidx.wear.protolayout.TypeBuilders.Int32Prop);
+    method public androidx.wear.protolayout.LayoutElementBuilders.Text.Builder setMaxLines(@IntRange(from=1) int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Text.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.Modifiers);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Text.Builder setMultilineAlignment(androidx.wear.protolayout.LayoutElementBuilders.TextAlignmentProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Text.Builder setMultilineAlignment(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Text.Builder setOverflow(androidx.wear.protolayout.LayoutElementBuilders.TextOverflowProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Text.Builder setOverflow(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Text.Builder setText(androidx.wear.protolayout.TypeBuilders.StringProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Text.Builder setText(String);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.TextAlignmentProp {
+    method public int getValue();
+  }
+
+  public static final class LayoutElementBuilders.TextAlignmentProp.Builder {
+    ctor public LayoutElementBuilders.TextAlignmentProp.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.TextAlignmentProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.TextAlignmentProp.Builder setValue(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.TextOverflowProp {
+    method public int getValue();
+  }
+
+  public static final class LayoutElementBuilders.TextOverflowProp.Builder {
+    ctor public LayoutElementBuilders.TextOverflowProp.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.TextOverflowProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.TextOverflowProp.Builder setValue(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.VerticalAlignmentProp {
+    method public int getValue();
+  }
+
+  public static final class LayoutElementBuilders.VerticalAlignmentProp.Builder {
+    ctor public LayoutElementBuilders.VerticalAlignmentProp.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.VerticalAlignmentProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.VerticalAlignmentProp.Builder setValue(int);
+  }
+
+  public final class ModifiersBuilders {
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int SEMANTICS_ROLE_BUTTON = 2; // 0x2
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int SEMANTICS_ROLE_CHECKBOX = 3; // 0x3
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int SEMANTICS_ROLE_IMAGE = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int SEMANTICS_ROLE_NONE = 0; // 0x0
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int SEMANTICS_ROLE_RADIOBUTTON = 5; // 0x5
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int SEMANTICS_ROLE_SWITCH = 4; // 0x4
+    field @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int SLIDE_DIRECTION_BOTTOM_TO_TOP = 4; // 0x4
+    field @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int SLIDE_DIRECTION_LEFT_TO_RIGHT = 1; // 0x1
+    field @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int SLIDE_DIRECTION_RIGHT_TO_LEFT = 2; // 0x2
+    field @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int SLIDE_DIRECTION_TOP_TO_BOTTOM = 3; // 0x3
+    field @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int SLIDE_DIRECTION_UNDEFINED = 0; // 0x0
+    field @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int SLIDE_PARENT_SNAP_TO_INSIDE = 1; // 0x1
+    field @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int SLIDE_PARENT_SNAP_TO_OUTSIDE = 2; // 0x2
+    field @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int SLIDE_PARENT_SNAP_UNDEFINED = 0; // 0x0
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class ModifiersBuilders.AnimatedVisibility {
+    method public androidx.wear.protolayout.ModifiersBuilders.EnterTransition? getEnterTransition();
+    method public androidx.wear.protolayout.ModifiersBuilders.ExitTransition? getExitTransition();
+  }
+
+  public static final class ModifiersBuilders.AnimatedVisibility.Builder {
+    ctor public ModifiersBuilders.AnimatedVisibility.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.AnimatedVisibility build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.AnimatedVisibility.Builder setEnterTransition(androidx.wear.protolayout.ModifiersBuilders.EnterTransition);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.AnimatedVisibility.Builder setExitTransition(androidx.wear.protolayout.ModifiersBuilders.ExitTransition);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ModifiersBuilders.ArcModifiers {
+    method public androidx.wear.protolayout.ModifiersBuilders.Clickable? getClickable();
+    method public androidx.wear.protolayout.TypeBuilders.FloatProp? getOpacity();
+    method public androidx.wear.protolayout.ModifiersBuilders.Semantics? getSemantics();
+  }
+
+  public static final class ModifiersBuilders.ArcModifiers.Builder {
+    ctor public ModifiersBuilders.ArcModifiers.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.ArcModifiers build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.ArcModifiers.Builder setClickable(androidx.wear.protolayout.ModifiersBuilders.Clickable);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.ArcModifiers.Builder setOpacity(androidx.wear.protolayout.TypeBuilders.FloatProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.ArcModifiers.Builder setSemantics(androidx.wear.protolayout.ModifiersBuilders.Semantics);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ModifiersBuilders.Background {
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp? getColor();
+    method public androidx.wear.protolayout.ModifiersBuilders.Corner? getCorner();
+  }
+
+  public static final class ModifiersBuilders.Background.Builder {
+    ctor public ModifiersBuilders.Background.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.Background build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Background.Builder setColor(androidx.wear.protolayout.ColorBuilders.ColorProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Background.Builder setCorner(androidx.wear.protolayout.ModifiersBuilders.Corner);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ModifiersBuilders.Border {
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp? getColor();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp? getWidth();
+  }
+
+  public static final class ModifiersBuilders.Border.Builder {
+    ctor public ModifiersBuilders.Border.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.Border build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Border.Builder setColor(androidx.wear.protolayout.ColorBuilders.ColorProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Border.Builder setWidth(androidx.wear.protolayout.DimensionBuilders.DpProp);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ModifiersBuilders.Clickable {
+    method public String getId();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp getMinimumClickableHeight();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp getMinimumClickableWidth();
+    method public androidx.wear.protolayout.ActionBuilders.Action? getOnClick();
+    method public boolean isVisualFeedbackEnabled();
+  }
+
+  public static final class ModifiersBuilders.Clickable.Builder {
+    ctor public ModifiersBuilders.Clickable.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.Clickable build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Clickable.Builder setId(String);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.ModifiersBuilders.Clickable.Builder setMinimumClickableHeight(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.ModifiersBuilders.Clickable.Builder setMinimumClickableWidth(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Clickable.Builder setOnClick(androidx.wear.protolayout.ActionBuilders.Action);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Clickable.Builder setVisualFeedbackEnabled(boolean);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ModifiersBuilders.Corner {
+    method public androidx.wear.protolayout.ModifiersBuilders.CornerRadius getBottomLeftRadius();
+    method public androidx.wear.protolayout.ModifiersBuilders.CornerRadius getBottomRightRadius();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp? getRadius();
+    method public androidx.wear.protolayout.ModifiersBuilders.CornerRadius getTopLeftRadius();
+    method public androidx.wear.protolayout.ModifiersBuilders.CornerRadius getTopRightRadius();
+  }
+
+  public static final class ModifiersBuilders.Corner.Builder {
+    ctor public ModifiersBuilders.Corner.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.Corner build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Corner.Builder setBottomLeftRadius(androidx.wear.protolayout.DimensionBuilders.DpProp, androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Corner.Builder setBottomLeftRadius(androidx.wear.protolayout.ModifiersBuilders.CornerRadius);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Corner.Builder setBottomRightRadius(androidx.wear.protolayout.DimensionBuilders.DpProp, androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Corner.Builder setBottomRightRadius(androidx.wear.protolayout.ModifiersBuilders.CornerRadius);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Corner.Builder setRadius(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Corner.Builder setTopLeftRadius(androidx.wear.protolayout.DimensionBuilders.DpProp, androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Corner.Builder setTopLeftRadius(androidx.wear.protolayout.ModifiersBuilders.CornerRadius);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Corner.Builder setTopRightRadius(androidx.wear.protolayout.DimensionBuilders.DpProp, androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Corner.Builder setTopRightRadius(androidx.wear.protolayout.ModifiersBuilders.CornerRadius);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static final class ModifiersBuilders.CornerRadius {
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp getX();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp getY();
+  }
+
+  public static final class ModifiersBuilders.CornerRadius.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public ModifiersBuilders.CornerRadius.Builder(androidx.wear.protolayout.DimensionBuilders.DpProp, androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method public androidx.wear.protolayout.ModifiersBuilders.CornerRadius build();
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental public static final class ModifiersBuilders.DefaultContentTransitions {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.ModifiersBuilders.EnterTransition fadeIn();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.ModifiersBuilders.EnterTransition fadeInSlideIn(@SuppressCompatibility int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.ModifiersBuilders.ExitTransition fadeOut();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.ModifiersBuilders.ExitTransition fadeOutSlideOut(@SuppressCompatibility int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.ModifiersBuilders.EnterTransition slideIn(@SuppressCompatibility int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.ModifiersBuilders.ExitTransition slideOut(@SuppressCompatibility int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ModifiersBuilders.ElementMetadata {
+    method public byte[] getTagData();
+  }
+
+  public static final class ModifiersBuilders.ElementMetadata.Builder {
+    ctor public ModifiersBuilders.ElementMetadata.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.ElementMetadata build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.ElementMetadata.Builder setTagData(byte[]);
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class ModifiersBuilders.EnterTransition {
+    method public androidx.wear.protolayout.ModifiersBuilders.FadeInTransition? getFadeIn();
+    method public androidx.wear.protolayout.ModifiersBuilders.SlideInTransition? getSlideIn();
+  }
+
+  public static final class ModifiersBuilders.EnterTransition.Builder {
+    ctor public ModifiersBuilders.EnterTransition.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.EnterTransition build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.EnterTransition.Builder setFadeIn(androidx.wear.protolayout.ModifiersBuilders.FadeInTransition);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.EnterTransition.Builder setSlideIn(androidx.wear.protolayout.ModifiersBuilders.SlideInTransition);
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class ModifiersBuilders.ExitTransition {
+    method public androidx.wear.protolayout.ModifiersBuilders.FadeOutTransition? getFadeOut();
+    method public androidx.wear.protolayout.ModifiersBuilders.SlideOutTransition? getSlideOut();
+  }
+
+  public static final class ModifiersBuilders.ExitTransition.Builder {
+    ctor public ModifiersBuilders.ExitTransition.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.ExitTransition build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.ExitTransition.Builder setFadeOut(androidx.wear.protolayout.ModifiersBuilders.FadeOutTransition);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.ExitTransition.Builder setSlideOut(androidx.wear.protolayout.ModifiersBuilders.SlideOutTransition);
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class ModifiersBuilders.FadeInTransition {
+    method public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec? getAnimationSpec();
+    method @FloatRange(from=0.0, to=1.0) public float getInitialAlpha();
+  }
+
+  public static final class ModifiersBuilders.FadeInTransition.Builder {
+    ctor public ModifiersBuilders.FadeInTransition.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.FadeInTransition build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.FadeInTransition.Builder setAnimationSpec(androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.FadeInTransition.Builder setInitialAlpha(@FloatRange(from=0.0, to=1.0) float);
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class ModifiersBuilders.FadeOutTransition {
+    method public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec? getAnimationSpec();
+    method @FloatRange(from=0.0, to=1.0) public float getTargetAlpha();
+  }
+
+  public static final class ModifiersBuilders.FadeOutTransition.Builder {
+    ctor public ModifiersBuilders.FadeOutTransition.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.FadeOutTransition build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.FadeOutTransition.Builder setAnimationSpec(androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
+    method public androidx.wear.protolayout.ModifiersBuilders.FadeOutTransition.Builder setTargetAlpha(@FloatRange(from=0.0, to=1.0) float);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ModifiersBuilders.Modifiers {
+    method public androidx.wear.protolayout.ModifiersBuilders.Background? getBackground();
+    method public androidx.wear.protolayout.ModifiersBuilders.Border? getBorder();
+    method public androidx.wear.protolayout.ModifiersBuilders.Clickable? getClickable();
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental public androidx.wear.protolayout.ModifiersBuilders.AnimatedVisibility? getContentUpdateAnimation();
+    method public androidx.wear.protolayout.ModifiersBuilders.ElementMetadata? getMetadata();
+    method public androidx.wear.protolayout.TypeBuilders.FloatProp? getOpacity();
+    method public androidx.wear.protolayout.ModifiersBuilders.Padding? getPadding();
+    method public androidx.wear.protolayout.ModifiersBuilders.Semantics? getSemantics();
+    method public androidx.wear.protolayout.ModifiersBuilders.Transformation? getTransformation();
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental public androidx.wear.protolayout.TypeBuilders.BoolProp isVisible();
+  }
+
+  public static final class ModifiersBuilders.Modifiers.Builder {
+    ctor public ModifiersBuilders.Modifiers.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.Modifiers build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Modifiers.Builder setBackground(androidx.wear.protolayout.ModifiersBuilders.Background);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Modifiers.Builder setBorder(androidx.wear.protolayout.ModifiersBuilders.Border);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Modifiers.Builder setClickable(androidx.wear.protolayout.ModifiersBuilders.Clickable);
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.Modifiers.Builder setContentUpdateAnimation(androidx.wear.protolayout.ModifiersBuilders.AnimatedVisibility);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Modifiers.Builder setMetadata(androidx.wear.protolayout.ModifiersBuilders.ElementMetadata);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Modifiers.Builder setOpacity(androidx.wear.protolayout.TypeBuilders.FloatProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Modifiers.Builder setPadding(androidx.wear.protolayout.ModifiersBuilders.Padding);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Modifiers.Builder setSemantics(androidx.wear.protolayout.ModifiersBuilders.Semantics);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Modifiers.Builder setTransformation(androidx.wear.protolayout.ModifiersBuilders.Transformation);
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.ModifiersBuilders.Modifiers.Builder setVisible(androidx.wear.protolayout.TypeBuilders.BoolProp);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ModifiersBuilders.Padding {
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp? getBottom();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp? getEnd();
+    method public androidx.wear.protolayout.TypeBuilders.BoolProp? getRtlAware();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp? getStart();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp? getTop();
+  }
+
+  public static final class ModifiersBuilders.Padding.Builder {
+    ctor public ModifiersBuilders.Padding.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.Padding build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Padding.Builder setAll(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Padding.Builder setBottom(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Padding.Builder setEnd(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Padding.Builder setRtlAware(androidx.wear.protolayout.TypeBuilders.BoolProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Padding.Builder setRtlAware(boolean);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Padding.Builder setStart(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Padding.Builder setTop(androidx.wear.protolayout.DimensionBuilders.DpProp);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ModifiersBuilders.Semantics {
+    method public androidx.wear.protolayout.TypeBuilders.StringProp? getContentDescription();
+    method public int getRole();
+    method public androidx.wear.protolayout.TypeBuilders.StringProp? getStateDescription();
+  }
+
+  public static final class ModifiersBuilders.Semantics.Builder {
+    ctor public ModifiersBuilders.Semantics.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.Semantics build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Semantics.Builder setContentDescription(androidx.wear.protolayout.TypeBuilders.StringProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Semantics.Builder setContentDescription(String);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.Semantics.Builder setRole(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.Semantics.Builder setStateDescription(androidx.wear.protolayout.TypeBuilders.StringProp);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public static final class ModifiersBuilders.Shadow {
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp getBlurRadius();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getColor();
+  }
+
+  public static final class ModifiersBuilders.Shadow.Builder {
+    ctor public ModifiersBuilders.Shadow.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.Shadow build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.ModifiersBuilders.Shadow.Builder setBlurRadius(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.ModifiersBuilders.Shadow.Builder setColor(androidx.wear.protolayout.ColorBuilders.ColorProp);
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static interface ModifiersBuilders.SlideBound {
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class ModifiersBuilders.SlideInTransition {
+    method public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec? getAnimationSpec();
+    method @SuppressCompatibility public int getDirection();
+    method public androidx.wear.protolayout.ModifiersBuilders.SlideBound? getInitialSlideBound();
+  }
+
+  public static final class ModifiersBuilders.SlideInTransition.Builder {
+    ctor public ModifiersBuilders.SlideInTransition.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.SlideInTransition build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.SlideInTransition.Builder setAnimationSpec(androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.SlideInTransition.Builder setDirection(@SuppressCompatibility int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.SlideInTransition.Builder setInitialSlideBound(androidx.wear.protolayout.ModifiersBuilders.SlideBound);
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class ModifiersBuilders.SlideOutTransition {
+    method public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec? getAnimationSpec();
+    method @SuppressCompatibility public int getDirection();
+    method public androidx.wear.protolayout.ModifiersBuilders.SlideBound? getTargetSlideBound();
+  }
+
+  public static final class ModifiersBuilders.SlideOutTransition.Builder {
+    ctor public ModifiersBuilders.SlideOutTransition.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.SlideOutTransition build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.SlideOutTransition.Builder setAnimationSpec(androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.SlideOutTransition.Builder setDirection(@SuppressCompatibility int);
+    method public androidx.wear.protolayout.ModifiersBuilders.SlideOutTransition.Builder setTargetSlideBound(androidx.wear.protolayout.ModifiersBuilders.SlideBound);
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class ModifiersBuilders.SlideParentBound implements androidx.wear.protolayout.ModifiersBuilders.SlideBound {
+    method @SuppressCompatibility public int getSnapTo();
+  }
+
+  public static final class ModifiersBuilders.SlideParentBound.Builder {
+    ctor public ModifiersBuilders.SlideParentBound.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.SlideParentBound build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.SlideParentBound.Builder setSnapTo(@SuppressCompatibility int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ModifiersBuilders.SpanModifiers {
+    method public androidx.wear.protolayout.ModifiersBuilders.Clickable? getClickable();
+  }
+
+  public static final class ModifiersBuilders.SpanModifiers.Builder {
+    ctor public ModifiersBuilders.SpanModifiers.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.SpanModifiers build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.SpanModifiers.Builder setClickable(androidx.wear.protolayout.ModifiersBuilders.Clickable);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static final class ModifiersBuilders.Transformation {
+    method public androidx.wear.protolayout.DimensionBuilders.PivotDimension getPivotX();
+    method public androidx.wear.protolayout.DimensionBuilders.PivotDimension getPivotY();
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp getRotation();
+    method public androidx.wear.protolayout.TypeBuilders.FloatProp getScaleX();
+    method public androidx.wear.protolayout.TypeBuilders.FloatProp getScaleY();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp getTranslationX();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp getTranslationY();
+  }
+
+  public static final class ModifiersBuilders.Transformation.Builder {
+    ctor public ModifiersBuilders.Transformation.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.Transformation build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Transformation.Builder setPivotX(androidx.wear.protolayout.DimensionBuilders.PivotDimension);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Transformation.Builder setPivotY(androidx.wear.protolayout.DimensionBuilders.PivotDimension);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Transformation.Builder setRotation(androidx.wear.protolayout.DimensionBuilders.DegreesProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Transformation.Builder setScaleX(androidx.wear.protolayout.TypeBuilders.FloatProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Transformation.Builder setScaleY(androidx.wear.protolayout.TypeBuilders.FloatProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Transformation.Builder setTranslationX(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Transformation.Builder setTranslationY(androidx.wear.protolayout.DimensionBuilders.DpProp);
+  }
+
+  public final class ResourceBuilders {
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int ANIMATED_IMAGE_FORMAT_AVD = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int ANIMATED_IMAGE_FORMAT_UNDEFINED = 0; // 0x0
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int IMAGE_FORMAT_ARGB_8888 = 2; // 0x2
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int IMAGE_FORMAT_RGB_565 = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int IMAGE_FORMAT_UNDEFINED = 0; // 0x0
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class ResourceBuilders.AndroidAnimatedImageResourceByResId {
+    method public int getAnimatedImageFormat();
+    method @DrawableRes public int getResourceId();
+    method public androidx.wear.protolayout.TriggerBuilders.Trigger? getStartTrigger();
+  }
+
+  public static final class ResourceBuilders.AndroidAnimatedImageResourceByResId.Builder {
+    ctor public ResourceBuilders.AndroidAnimatedImageResourceByResId.Builder();
+    method public androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId.Builder setAnimatedImageFormat(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId.Builder setResourceId(@DrawableRes int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId.Builder setStartTrigger(androidx.wear.protolayout.TriggerBuilders.Trigger);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ResourceBuilders.AndroidImageResourceByResId {
+    method @DrawableRes public int getResourceId();
+  }
+
+  public static final class ResourceBuilders.AndroidImageResourceByResId.Builder {
+    ctor public ResourceBuilders.AndroidImageResourceByResId.Builder();
+    method public androidx.wear.protolayout.ResourceBuilders.AndroidImageResourceByResId build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ResourceBuilders.AndroidImageResourceByResId.Builder setResourceId(@DrawableRes int);
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId {
+    method public int getAnimatedImageFormat();
+    method public androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat? getProgress();
+    method @DrawableRes public int getResourceId();
+  }
+
+  public static final class ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId.Builder {
+    ctor public ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId.Builder();
+    method public androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId.Builder setAnimatedImageFormat(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId.Builder setProgress(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId.Builder setResourceId(@DrawableRes int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ResourceBuilders.ImageResource {
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental public androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId? getAndroidAnimatedResourceByResId();
+    method public androidx.wear.protolayout.ResourceBuilders.AndroidImageResourceByResId? getAndroidResourceByResId();
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental public androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId? getAndroidSeekableAnimatedResourceByResId();
+    method public androidx.wear.protolayout.ResourceBuilders.InlineImageResource? getInlineResource();
+  }
+
+  public static final class ResourceBuilders.ImageResource.Builder {
+    ctor public ResourceBuilders.ImageResource.Builder();
+    method public androidx.wear.protolayout.ResourceBuilders.ImageResource build();
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ResourceBuilders.ImageResource.Builder setAndroidAnimatedResourceByResId(androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ResourceBuilders.ImageResource.Builder setAndroidResourceByResId(androidx.wear.protolayout.ResourceBuilders.AndroidImageResourceByResId);
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ResourceBuilders.ImageResource.Builder setAndroidSeekableAnimatedResourceByResId(androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ResourceBuilders.ImageResource.Builder setInlineResource(androidx.wear.protolayout.ResourceBuilders.InlineImageResource);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ResourceBuilders.InlineImageResource {
+    method public byte[] getData();
+    method public int getFormat();
+    method @Dimension(unit=androidx.annotation.Dimension.PX) public int getHeightPx();
+    method @Dimension(unit=androidx.annotation.Dimension.PX) public int getWidthPx();
+  }
+
+  public static final class ResourceBuilders.InlineImageResource.Builder {
+    ctor public ResourceBuilders.InlineImageResource.Builder();
+    method public androidx.wear.protolayout.ResourceBuilders.InlineImageResource build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ResourceBuilders.InlineImageResource.Builder setData(byte[]);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ResourceBuilders.InlineImageResource.Builder setFormat(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ResourceBuilders.InlineImageResource.Builder setHeightPx(@Dimension(unit=androidx.annotation.Dimension.PX) int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ResourceBuilders.InlineImageResource.Builder setWidthPx(@Dimension(unit=androidx.annotation.Dimension.PX) int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ResourceBuilders.Resources {
+    method public java.util.Map<java.lang.String!,androidx.wear.protolayout.ResourceBuilders.ImageResource!> getIdToImageMapping();
+    method public String getVersion();
+  }
+
+  public static final class ResourceBuilders.Resources.Builder {
+    ctor public ResourceBuilders.Resources.Builder();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ResourceBuilders.Resources.Builder addIdToImageMapping(String, androidx.wear.protolayout.ResourceBuilders.ImageResource);
+    method public androidx.wear.protolayout.ResourceBuilders.Resources build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ResourceBuilders.Resources.Builder setVersion(String);
+  }
+
+  public final class StateBuilders {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class StateBuilders.State {
+    method public java.util.Map<androidx.wear.protolayout.expression.AppDataKey<? extends java.lang.Object!>!,androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<? extends java.lang.Object!>!> getKeyToValueMapping();
+    method public String getLastClickableId();
+    method public static int getMaxStateEntryCount();
+  }
+
+  public static final class StateBuilders.State.Builder {
+    ctor public StateBuilders.State.Builder();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public <T extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType> androidx.wear.protolayout.StateBuilders.State.Builder addKeyToValueMapping(androidx.wear.protolayout.expression.AppDataKey<T!>, androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<T!>);
+    method public androidx.wear.protolayout.StateBuilders.State build();
+  }
+
+  public final class TimelineBuilders {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class TimelineBuilders.TimeInterval {
+    method public long getEndMillis();
+    method public long getStartMillis();
+  }
+
+  public static final class TimelineBuilders.TimeInterval.Builder {
+    ctor public TimelineBuilders.TimeInterval.Builder();
+    method public androidx.wear.protolayout.TimelineBuilders.TimeInterval build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.TimelineBuilders.TimeInterval.Builder setEndMillis(long);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.TimelineBuilders.TimeInterval.Builder setStartMillis(long);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class TimelineBuilders.Timeline {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static androidx.wear.protolayout.TimelineBuilders.Timeline fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public java.util.List<androidx.wear.protolayout.TimelineBuilders.TimelineEntry!> getTimelineEntries();
+  }
+
+  public static final class TimelineBuilders.Timeline.Builder {
+    ctor public TimelineBuilders.Timeline.Builder();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.TimelineBuilders.Timeline.Builder addTimelineEntry(androidx.wear.protolayout.TimelineBuilders.TimelineEntry);
+    method public androidx.wear.protolayout.TimelineBuilders.Timeline build();
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class TimelineBuilders.TimelineEntry {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static androidx.wear.protolayout.TimelineBuilders.TimelineEntry fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.LayoutElementBuilders.Layout? getLayout();
+    method public androidx.wear.protolayout.TimelineBuilders.TimeInterval? getValidity();
+  }
+
+  public static final class TimelineBuilders.TimelineEntry.Builder {
+    ctor public TimelineBuilders.TimelineEntry.Builder();
+    method public androidx.wear.protolayout.TimelineBuilders.TimelineEntry build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.TimelineBuilders.TimelineEntry.Builder setLayout(androidx.wear.protolayout.LayoutElementBuilders.Layout);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.TimelineBuilders.TimelineEntry.Builder setValidity(androidx.wear.protolayout.TimelineBuilders.TimeInterval);
+  }
+
+  public final class TriggerBuilders {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.TriggerBuilders.Trigger createOnConditionMetTrigger(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.TriggerBuilders.Trigger createOnLoadTrigger();
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static interface TriggerBuilders.Trigger {
+  }
+
+  public final class TypeBuilders {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class TypeBuilders.BoolProp {
+    method public androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool? getDynamicValue();
+    method public boolean getValue();
+  }
+
+  public static final class TypeBuilders.BoolProp.Builder {
+    ctor @Deprecated public TypeBuilders.BoolProp.Builder();
+    ctor public TypeBuilders.BoolProp.Builder(boolean);
+    method public androidx.wear.protolayout.TypeBuilders.BoolProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.TypeBuilders.BoolProp.Builder setDynamicValue(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.TypeBuilders.BoolProp.Builder setValue(boolean);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class TypeBuilders.FloatProp {
+    method public androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat? getDynamicValue();
+    method public float getValue();
+  }
+
+  public static final class TypeBuilders.FloatProp.Builder {
+    ctor @Deprecated public TypeBuilders.FloatProp.Builder();
+    ctor public TypeBuilders.FloatProp.Builder(float);
+    method public androidx.wear.protolayout.TypeBuilders.FloatProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.TypeBuilders.FloatProp.Builder setDynamicValue(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.TypeBuilders.FloatProp.Builder setValue(float);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class TypeBuilders.Int32Prop {
+    method public int getValue();
+  }
+
+  public static final class TypeBuilders.Int32Prop.Builder {
+    ctor public TypeBuilders.Int32Prop.Builder();
+    method public androidx.wear.protolayout.TypeBuilders.Int32Prop build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.TypeBuilders.Int32Prop.Builder setValue(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class TypeBuilders.StringLayoutConstraint {
+    method public int getAlignment();
+    method public String getPatternForLayout();
+  }
+
+  public static final class TypeBuilders.StringLayoutConstraint.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public TypeBuilders.StringLayoutConstraint.Builder(String);
+    method public androidx.wear.protolayout.TypeBuilders.StringLayoutConstraint build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.TypeBuilders.StringLayoutConstraint.Builder setAlignment(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class TypeBuilders.StringProp {
+    method public androidx.wear.protolayout.expression.DynamicBuilders.DynamicString? getDynamicValue();
+    method public String getValue();
+  }
+
+  public static final class TypeBuilders.StringProp.Builder {
+    ctor @Deprecated public TypeBuilders.StringProp.Builder();
+    ctor public TypeBuilders.StringProp.Builder(String);
+    method public androidx.wear.protolayout.TypeBuilders.StringProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.TypeBuilders.StringProp.Builder setDynamicValue(androidx.wear.protolayout.expression.DynamicBuilders.DynamicString);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.TypeBuilders.StringProp.Builder setValue(String);
+  }
+
+}
+
diff --git a/wear/protolayout/protolayout/api/current.ignore b/wear/protolayout/protolayout/api/current.ignore
new file mode 100644
index 0000000..a151ec4
--- /dev/null
+++ b/wear/protolayout/protolayout/api/current.ignore
@@ -0,0 +1,3 @@
+// Baseline format: 1.0
+InvalidNullConversion: androidx.wear.protolayout.StateBuilders.State#getKeyToValueMapping():
+    Attempted to remove nullability from java.lang.Object (was NONNULL) in method androidx.wear.protolayout.StateBuilders.State.getKeyToValueMapping()
diff --git a/wear/protolayout/protolayout/api/current.txt b/wear/protolayout/protolayout/api/current.txt
index 6298259..721be43 100644
--- a/wear/protolayout/protolayout/api/current.txt
+++ b/wear/protolayout/protolayout/api/current.txt
@@ -154,13 +154,13 @@
   }
 
   @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class DeviceParametersBuilders.Capabilities {
-    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental public long getMinimumFreshnessLimitMillis();
+    method public long getMinimumFreshnessLimitMillis();
   }
 
   public static final class DeviceParametersBuilders.Capabilities.Builder {
     ctor public DeviceParametersBuilders.Capabilities.Builder();
     method public androidx.wear.protolayout.DeviceParametersBuilders.Capabilities build();
-    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DeviceParametersBuilders.Capabilities.Builder setMinimumFreshnessLimitMillis(long);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DeviceParametersBuilders.Capabilities.Builder setMinimumFreshnessLimitMillis(long);
   }
 
   @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class DeviceParametersBuilders.DeviceParameters {
@@ -180,7 +180,7 @@
     method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setCapabilities(androidx.wear.protolayout.DeviceParametersBuilders.Capabilities);
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setDevicePlatform(int);
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setFontScale(@FloatRange(from=0.0, fromInclusive=false, toInclusive=false) float);
-    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setRendererSchemaVersion(androidx.wear.protolayout.expression.VersionBuilders.VersionInfo);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setRendererSchemaVersion(androidx.wear.protolayout.expression.VersionBuilders.VersionInfo);
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setScreenDensity(@FloatRange(from=0.0, fromInclusive=false, toInclusive=false) float);
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setScreenHeightDp(@Dimension(unit=androidx.annotation.Dimension.DP) int);
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setScreenShape(int);
@@ -566,7 +566,7 @@
   }
 
   public static final class LayoutElementBuilders.ExtensionLayoutElement.Builder {
-    ctor public LayoutElementBuilders.ExtensionLayoutElement.Builder();
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public LayoutElementBuilders.ExtensionLayoutElement.Builder();
     method public androidx.wear.protolayout.LayoutElementBuilders.ExtensionLayoutElement build();
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.ExtensionLayoutElement.Builder setExtensionId(String);
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.ExtensionLayoutElement.Builder setHeight(androidx.wear.protolayout.DimensionBuilders.ExtensionDimension);
@@ -577,7 +577,7 @@
   @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static interface LayoutElementBuilders.FontSetting {
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static androidx.wear.protolayout.LayoutElementBuilders.FontSetting tabularNum();
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static androidx.wear.protolayout.LayoutElementBuilders.FontSetting weight(@IntRange(from=1, to=1000) int);
-    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static androidx.wear.protolayout.LayoutElementBuilders.FontSetting width(@FloatRange(from=0) float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static androidx.wear.protolayout.LayoutElementBuilders.FontSetting width(@FloatRange(from=25, to=200) float);
   }
 
   @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.FontStyle {
@@ -591,7 +591,6 @@
     method public androidx.wear.protolayout.TypeBuilders.BoolProp? getUnderline();
     method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental public androidx.wear.protolayout.LayoutElementBuilders.FontVariantProp? getVariant();
     method public androidx.wear.protolayout.LayoutElementBuilders.FontWeightProp? getWeight();
-    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static final String DEFAULT_SYSTEM_FONT = "default";
     field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static final String ROBOTO_FLEX_FONT = "roboto-flex";
     field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static final String ROBOTO_FONT = "roboto";
   }
@@ -813,7 +812,7 @@
   }
 
   public static final class LayoutElementBuilders.StrokeCapProp.Builder {
-    ctor public LayoutElementBuilders.StrokeCapProp.Builder();
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public LayoutElementBuilders.StrokeCapProp.Builder();
     method public androidx.wear.protolayout.LayoutElementBuilders.StrokeCapProp build();
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.LayoutElementBuilders.StrokeCapProp.Builder setShadow(androidx.wear.protolayout.ModifiersBuilders.Shadow);
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.StrokeCapProp.Builder setValue(int);
@@ -1357,7 +1356,7 @@
 
   public final class TriggerBuilders {
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.TriggerBuilders.Trigger createOnConditionMetTrigger(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
-    method public static androidx.wear.protolayout.TriggerBuilders.Trigger createOnLoadTrigger();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.TriggerBuilders.Trigger createOnLoadTrigger();
   }
 
   @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static interface TriggerBuilders.Trigger {
diff --git a/wear/protolayout/protolayout/api/res-1.2.0-beta01.txt b/wear/protolayout/protolayout/api/res-1.2.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wear/protolayout/protolayout/api/res-1.2.0-beta01.txt
diff --git a/wear/protolayout/protolayout/api/restricted_1.2.0-beta01.txt b/wear/protolayout/protolayout/api/restricted_1.2.0-beta01.txt
new file mode 100644
index 0000000..721be43
--- /dev/null
+++ b/wear/protolayout/protolayout/api/restricted_1.2.0-beta01.txt
@@ -0,0 +1,1429 @@
+// Signature format: 4.0
+package androidx.wear.protolayout {
+
+  public final class ActionBuilders {
+    method public static androidx.wear.protolayout.ActionBuilders.AndroidBooleanExtra booleanExtra(boolean);
+    method public static androidx.wear.protolayout.ActionBuilders.AndroidDoubleExtra doubleExtra(double);
+    method public static androidx.wear.protolayout.ActionBuilders.AndroidIntExtra intExtra(int);
+    method public static androidx.wear.protolayout.ActionBuilders.LaunchAction launchAction(android.content.ComponentName);
+    method public static androidx.wear.protolayout.ActionBuilders.LaunchAction launchAction(android.content.ComponentName, java.util.Map<java.lang.String!,androidx.wear.protolayout.ActionBuilders.AndroidExtra!>);
+    method public static androidx.wear.protolayout.ActionBuilders.AndroidLongExtra longExtra(long);
+    method public static androidx.wear.protolayout.ActionBuilders.AndroidStringExtra stringExtra(String);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static interface ActionBuilders.Action {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ActionBuilders.AndroidActivity {
+    method public String getClassName();
+    method public java.util.Map<java.lang.String!,androidx.wear.protolayout.ActionBuilders.AndroidExtra!> getKeyToExtraMapping();
+    method public String getPackageName();
+  }
+
+  public static final class ActionBuilders.AndroidActivity.Builder {
+    ctor public ActionBuilders.AndroidActivity.Builder();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ActionBuilders.AndroidActivity.Builder addKeyToExtraMapping(String, androidx.wear.protolayout.ActionBuilders.AndroidExtra);
+    method public androidx.wear.protolayout.ActionBuilders.AndroidActivity build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ActionBuilders.AndroidActivity.Builder setClassName(String);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ActionBuilders.AndroidActivity.Builder setPackageName(String);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ActionBuilders.AndroidBooleanExtra implements androidx.wear.protolayout.ActionBuilders.AndroidExtra {
+    method public boolean getValue();
+  }
+
+  public static final class ActionBuilders.AndroidBooleanExtra.Builder {
+    ctor public ActionBuilders.AndroidBooleanExtra.Builder();
+    method public androidx.wear.protolayout.ActionBuilders.AndroidBooleanExtra build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ActionBuilders.AndroidBooleanExtra.Builder setValue(boolean);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ActionBuilders.AndroidDoubleExtra implements androidx.wear.protolayout.ActionBuilders.AndroidExtra {
+    method public double getValue();
+  }
+
+  public static final class ActionBuilders.AndroidDoubleExtra.Builder {
+    ctor public ActionBuilders.AndroidDoubleExtra.Builder();
+    method public androidx.wear.protolayout.ActionBuilders.AndroidDoubleExtra build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ActionBuilders.AndroidDoubleExtra.Builder setValue(double);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static interface ActionBuilders.AndroidExtra {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ActionBuilders.AndroidIntExtra implements androidx.wear.protolayout.ActionBuilders.AndroidExtra {
+    method public int getValue();
+  }
+
+  public static final class ActionBuilders.AndroidIntExtra.Builder {
+    ctor public ActionBuilders.AndroidIntExtra.Builder();
+    method public androidx.wear.protolayout.ActionBuilders.AndroidIntExtra build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ActionBuilders.AndroidIntExtra.Builder setValue(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ActionBuilders.AndroidLongExtra implements androidx.wear.protolayout.ActionBuilders.AndroidExtra {
+    method public long getValue();
+  }
+
+  public static final class ActionBuilders.AndroidLongExtra.Builder {
+    ctor public ActionBuilders.AndroidLongExtra.Builder();
+    method public androidx.wear.protolayout.ActionBuilders.AndroidLongExtra build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ActionBuilders.AndroidLongExtra.Builder setValue(long);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ActionBuilders.AndroidStringExtra implements androidx.wear.protolayout.ActionBuilders.AndroidExtra {
+    method public String getValue();
+  }
+
+  public static final class ActionBuilders.AndroidStringExtra.Builder {
+    ctor public ActionBuilders.AndroidStringExtra.Builder();
+    method public androidx.wear.protolayout.ActionBuilders.AndroidStringExtra build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ActionBuilders.AndroidStringExtra.Builder setValue(String);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ActionBuilders.LaunchAction implements androidx.wear.protolayout.ActionBuilders.Action {
+    method public androidx.wear.protolayout.ActionBuilders.AndroidActivity? getAndroidActivity();
+  }
+
+  public static final class ActionBuilders.LaunchAction.Builder {
+    ctor public ActionBuilders.LaunchAction.Builder();
+    method public androidx.wear.protolayout.ActionBuilders.LaunchAction build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ActionBuilders.LaunchAction.Builder setAndroidActivity(androidx.wear.protolayout.ActionBuilders.AndroidActivity);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ActionBuilders.LoadAction implements androidx.wear.protolayout.ActionBuilders.Action {
+    method public androidx.wear.protolayout.StateBuilders.State? getRequestState();
+  }
+
+  public static final class ActionBuilders.LoadAction.Builder {
+    ctor public ActionBuilders.LoadAction.Builder();
+    method public androidx.wear.protolayout.ActionBuilders.LoadAction build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ActionBuilders.LoadAction.Builder setRequestState(androidx.wear.protolayout.StateBuilders.State);
+  }
+
+  public final class ColorBuilders {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static androidx.wear.protolayout.ColorBuilders.ColorProp argb(@ColorInt int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public static interface ColorBuilders.Brush {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ColorBuilders.ColorProp {
+    method @ColorInt public int getArgb();
+    method public androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor? getDynamicValue();
+  }
+
+  public static final class ColorBuilders.ColorProp.Builder {
+    ctor @Deprecated public ColorBuilders.ColorProp.Builder();
+    ctor public ColorBuilders.ColorProp.Builder(@ColorInt int);
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ColorBuilders.ColorProp.Builder setArgb(@ColorInt int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ColorBuilders.ColorProp.Builder setDynamicValue(androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public static final class ColorBuilders.ColorStop {
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getColor();
+    method public androidx.wear.protolayout.TypeBuilders.FloatProp? getOffset();
+  }
+
+  public static final class ColorBuilders.ColorStop.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public ColorBuilders.ColorStop.Builder(androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.TypeBuilders.FloatProp);
+    method public androidx.wear.protolayout.ColorBuilders.ColorStop build();
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public static final class ColorBuilders.SweepGradient implements androidx.wear.protolayout.ColorBuilders.Brush {
+    method public java.util.List<androidx.wear.protolayout.ColorBuilders.ColorStop!> getColorStops();
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp getEndAngle();
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp getStartAngle();
+  }
+
+  public static final class ColorBuilders.SweepGradient.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) @java.lang.SafeVarargs public ColorBuilders.SweepGradient.Builder(androidx.wear.protolayout.ColorBuilders.ColorProp!...);
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) @java.lang.SafeVarargs public ColorBuilders.SweepGradient.Builder(androidx.wear.protolayout.ColorBuilders.ColorStop!...);
+    method public androidx.wear.protolayout.ColorBuilders.SweepGradient build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.ColorBuilders.SweepGradient.Builder setEndAngle(androidx.wear.protolayout.DimensionBuilders.DegreesProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.ColorBuilders.SweepGradient.Builder setStartAngle(androidx.wear.protolayout.DimensionBuilders.DegreesProp);
+  }
+
+  public final class DeviceParametersBuilders {
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int DEVICE_PLATFORM_UNDEFINED = 0; // 0x0
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int DEVICE_PLATFORM_WEAR_OS = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int SCREEN_SHAPE_RECT = 2; // 0x2
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int SCREEN_SHAPE_ROUND = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int SCREEN_SHAPE_UNDEFINED = 0; // 0x0
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class DeviceParametersBuilders.Capabilities {
+    method public long getMinimumFreshnessLimitMillis();
+  }
+
+  public static final class DeviceParametersBuilders.Capabilities.Builder {
+    ctor public DeviceParametersBuilders.Capabilities.Builder();
+    method public androidx.wear.protolayout.DeviceParametersBuilders.Capabilities build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DeviceParametersBuilders.Capabilities.Builder setMinimumFreshnessLimitMillis(long);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class DeviceParametersBuilders.DeviceParameters {
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental public androidx.wear.protolayout.DeviceParametersBuilders.Capabilities? getCapabilities();
+    method public int getDevicePlatform();
+    method @FloatRange(from=0.0, fromInclusive=false, toInclusive=false) public float getFontScale();
+    method public androidx.wear.protolayout.expression.VersionBuilders.VersionInfo getRendererSchemaVersion();
+    method @FloatRange(from=0.0, fromInclusive=false, toInclusive=false) public float getScreenDensity();
+    method @Dimension(unit=androidx.annotation.Dimension.DP) public int getScreenHeightDp();
+    method public int getScreenShape();
+    method @Dimension(unit=androidx.annotation.Dimension.DP) public int getScreenWidthDp();
+  }
+
+  public static final class DeviceParametersBuilders.DeviceParameters.Builder {
+    ctor public DeviceParametersBuilders.DeviceParameters.Builder();
+    method public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters build();
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setCapabilities(androidx.wear.protolayout.DeviceParametersBuilders.Capabilities);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setDevicePlatform(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setFontScale(@FloatRange(from=0.0, fromInclusive=false, toInclusive=false) float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setRendererSchemaVersion(androidx.wear.protolayout.expression.VersionBuilders.VersionInfo);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setScreenDensity(@FloatRange(from=0.0, fromInclusive=false, toInclusive=false) float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setScreenHeightDp(@Dimension(unit=androidx.annotation.Dimension.DP) int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setScreenShape(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setScreenWidthDp(@Dimension(unit=androidx.annotation.Dimension.DP) int);
+  }
+
+  public final class DimensionBuilders {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static androidx.wear.protolayout.DimensionBuilders.DegreesProp degrees(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static androidx.wear.protolayout.DimensionBuilders.DpProp dp(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static androidx.wear.protolayout.DimensionBuilders.EmProp em(float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static androidx.wear.protolayout.DimensionBuilders.EmProp em(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static androidx.wear.protolayout.DimensionBuilders.ExpandedDimensionProp expand();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static androidx.wear.protolayout.DimensionBuilders.SpProp sp(@Dimension(unit=androidx.annotation.Dimension.SP) float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public static androidx.wear.protolayout.DimensionBuilders.ExpandedDimensionProp weight(@FloatRange(from=0.0) float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static androidx.wear.protolayout.DimensionBuilders.WrappedDimensionProp wrap();
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class DimensionBuilders.AngularLayoutConstraint {
+    method public int getAngularAlignment();
+    method @Dimension(unit=androidx.annotation.Dimension.DP) public float getValue();
+  }
+
+  public static final class DimensionBuilders.AngularLayoutConstraint.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public DimensionBuilders.AngularLayoutConstraint.Builder(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method public androidx.wear.protolayout.DimensionBuilders.AngularLayoutConstraint build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DimensionBuilders.AngularLayoutConstraint.Builder setAngularAlignment(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static final class DimensionBuilders.BoundingBoxRatio implements androidx.wear.protolayout.DimensionBuilders.PivotDimension {
+    method public androidx.wear.protolayout.TypeBuilders.FloatProp getRatio();
+  }
+
+  public static final class DimensionBuilders.BoundingBoxRatio.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public DimensionBuilders.BoundingBoxRatio.Builder(androidx.wear.protolayout.TypeBuilders.FloatProp);
+    method public androidx.wear.protolayout.DimensionBuilders.BoundingBoxRatio build();
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static interface DimensionBuilders.ContainerDimension {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class DimensionBuilders.DegreesProp {
+    method public androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat? getDynamicValue();
+    method public float getValue();
+  }
+
+  public static final class DimensionBuilders.DegreesProp.Builder {
+    ctor @Deprecated public DimensionBuilders.DegreesProp.Builder();
+    ctor public DimensionBuilders.DegreesProp.Builder(float);
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DimensionBuilders.DegreesProp.Builder setDynamicValue(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DimensionBuilders.DegreesProp.Builder setValue(float);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class DimensionBuilders.DpProp implements androidx.wear.protolayout.DimensionBuilders.ContainerDimension androidx.wear.protolayout.DimensionBuilders.ExtensionDimension androidx.wear.protolayout.DimensionBuilders.ImageDimension androidx.wear.protolayout.DimensionBuilders.PivotDimension androidx.wear.protolayout.DimensionBuilders.SpacerDimension {
+    method public androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat? getDynamicValue();
+    method @Dimension(unit=androidx.annotation.Dimension.DP) public float getValue();
+  }
+
+  public static final class DimensionBuilders.DpProp.Builder {
+    ctor @Deprecated public DimensionBuilders.DpProp.Builder();
+    ctor public DimensionBuilders.DpProp.Builder(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DimensionBuilders.DpProp.Builder setDynamicValue(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DimensionBuilders.DpProp.Builder setValue(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class DimensionBuilders.EmProp {
+    method public float getValue();
+  }
+
+  public static final class DimensionBuilders.EmProp.Builder {
+    ctor public DimensionBuilders.EmProp.Builder();
+    method public androidx.wear.protolayout.DimensionBuilders.EmProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DimensionBuilders.EmProp.Builder setValue(float);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class DimensionBuilders.ExpandedDimensionProp implements androidx.wear.protolayout.DimensionBuilders.ContainerDimension androidx.wear.protolayout.DimensionBuilders.ImageDimension androidx.wear.protolayout.DimensionBuilders.SpacerDimension {
+    method public androidx.wear.protolayout.TypeBuilders.FloatProp? getLayoutWeight();
+  }
+
+  public static final class DimensionBuilders.ExpandedDimensionProp.Builder {
+    ctor public DimensionBuilders.ExpandedDimensionProp.Builder();
+    method public androidx.wear.protolayout.DimensionBuilders.ExpandedDimensionProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DimensionBuilders.ExpandedDimensionProp.Builder setLayoutWeight(androidx.wear.protolayout.TypeBuilders.FloatProp);
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ExperimentalProtoLayoutExtensionApi @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static interface DimensionBuilders.ExtensionDimension {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class DimensionBuilders.HorizontalLayoutConstraint {
+    method public int getHorizontalAlignment();
+    method @Dimension(unit=androidx.annotation.Dimension.DP) public float getValue();
+  }
+
+  public static final class DimensionBuilders.HorizontalLayoutConstraint.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public DimensionBuilders.HorizontalLayoutConstraint.Builder(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method public androidx.wear.protolayout.DimensionBuilders.HorizontalLayoutConstraint build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DimensionBuilders.HorizontalLayoutConstraint.Builder setHorizontalAlignment(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static interface DimensionBuilders.ImageDimension {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static interface DimensionBuilders.PivotDimension {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class DimensionBuilders.ProportionalDimensionProp implements androidx.wear.protolayout.DimensionBuilders.ImageDimension {
+    method @IntRange(from=0) public int getAspectRatioHeight();
+    method @IntRange(from=0) public int getAspectRatioWidth();
+  }
+
+  public static final class DimensionBuilders.ProportionalDimensionProp.Builder {
+    ctor public DimensionBuilders.ProportionalDimensionProp.Builder();
+    method public androidx.wear.protolayout.DimensionBuilders.ProportionalDimensionProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DimensionBuilders.ProportionalDimensionProp.Builder setAspectRatioHeight(@IntRange(from=0) int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DimensionBuilders.ProportionalDimensionProp.Builder setAspectRatioWidth(@IntRange(from=0) int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class DimensionBuilders.SpProp {
+    method @Dimension(unit=androidx.annotation.Dimension.SP) public float getValue();
+  }
+
+  public static final class DimensionBuilders.SpProp.Builder {
+    ctor public DimensionBuilders.SpProp.Builder();
+    method public androidx.wear.protolayout.DimensionBuilders.SpProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DimensionBuilders.SpProp.Builder setValue(@Dimension(unit=androidx.annotation.Dimension.SP) float);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static interface DimensionBuilders.SpacerDimension {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class DimensionBuilders.VerticalLayoutConstraint {
+    method @Dimension(unit=androidx.annotation.Dimension.DP) public float getValue();
+    method public int getVerticalAlignment();
+  }
+
+  public static final class DimensionBuilders.VerticalLayoutConstraint.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public DimensionBuilders.VerticalLayoutConstraint.Builder(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method public androidx.wear.protolayout.DimensionBuilders.VerticalLayoutConstraint build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DimensionBuilders.VerticalLayoutConstraint.Builder setVerticalAlignment(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class DimensionBuilders.WrappedDimensionProp implements androidx.wear.protolayout.DimensionBuilders.ContainerDimension {
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp? getMinimumSize();
+  }
+
+  public static final class DimensionBuilders.WrappedDimensionProp.Builder {
+    ctor public DimensionBuilders.WrappedDimensionProp.Builder();
+    method public androidx.wear.protolayout.DimensionBuilders.WrappedDimensionProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DimensionBuilders.WrappedDimensionProp.Builder setMinimumSize(androidx.wear.protolayout.DimensionBuilders.DpProp);
+  }
+
+  public final class LayoutElementBuilders {
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int ANGULAR_ALIGNMENT_CENTER = 2; // 0x2
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int ANGULAR_ALIGNMENT_END = 3; // 0x3
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int ANGULAR_ALIGNMENT_START = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int ANGULAR_ALIGNMENT_UNDEFINED = 0; // 0x0
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int ARC_ANCHOR_CENTER = 2; // 0x2
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int ARC_ANCHOR_END = 3; // 0x3
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int ARC_ANCHOR_START = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int ARC_ANCHOR_UNDEFINED = 0; // 0x0
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int CONTENT_SCALE_MODE_CROP = 2; // 0x2
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int CONTENT_SCALE_MODE_FILL_BOUNDS = 3; // 0x3
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int CONTENT_SCALE_MODE_FIT = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int CONTENT_SCALE_MODE_UNDEFINED = 0; // 0x0
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int FONT_VARIANT_BODY = 2; // 0x2
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int FONT_VARIANT_TITLE = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int FONT_VARIANT_UNDEFINED = 0; // 0x0
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int FONT_WEIGHT_BOLD = 700; // 0x2bc
+    field @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int FONT_WEIGHT_MEDIUM = 500; // 0x1f4
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int FONT_WEIGHT_NORMAL = 400; // 0x190
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int FONT_WEIGHT_UNDEFINED = 0; // 0x0
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int HORIZONTAL_ALIGN_CENTER = 2; // 0x2
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int HORIZONTAL_ALIGN_END = 5; // 0x5
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int HORIZONTAL_ALIGN_LEFT = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int HORIZONTAL_ALIGN_RIGHT = 3; // 0x3
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int HORIZONTAL_ALIGN_START = 4; // 0x4
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int HORIZONTAL_ALIGN_UNDEFINED = 0; // 0x0
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int SPAN_VERTICAL_ALIGN_BOTTOM = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int SPAN_VERTICAL_ALIGN_TEXT_BASELINE = 2; // 0x2
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int SPAN_VERTICAL_ALIGN_UNDEFINED = 0; // 0x0
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int STROKE_CAP_BUTT = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int STROKE_CAP_ROUND = 2; // 0x2
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int STROKE_CAP_SQUARE = 3; // 0x3
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int STROKE_CAP_UNDEFINED = 0; // 0x0
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int TEXT_ALIGN_CENTER = 2; // 0x2
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int TEXT_ALIGN_END = 3; // 0x3
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int TEXT_ALIGN_START = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int TEXT_ALIGN_UNDEFINED = 0; // 0x0
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public static final int TEXT_OVERFLOW_ELLIPSIZE = 4; // 0x4
+    field @Deprecated @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int TEXT_OVERFLOW_ELLIPSIZE_END = 2; // 0x2
+    field @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int TEXT_OVERFLOW_MARQUEE = 3; // 0x3
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int TEXT_OVERFLOW_TRUNCATE = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int TEXT_OVERFLOW_UNDEFINED = 0; // 0x0
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int VERTICAL_ALIGN_BOTTOM = 3; // 0x3
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int VERTICAL_ALIGN_CENTER = 2; // 0x2
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int VERTICAL_ALIGN_TOP = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int VERTICAL_ALIGN_UNDEFINED = 0; // 0x0
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.Arc implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp? getAnchorAngle();
+    method public androidx.wear.protolayout.LayoutElementBuilders.ArcAnchorTypeProp? getAnchorType();
+    method public androidx.wear.protolayout.LayoutElementBuilders.ArcDirectionProp? getArcDirection();
+    method public java.util.List<androidx.wear.protolayout.LayoutElementBuilders.ArcLayoutElement!> getContents();
+    method public androidx.wear.protolayout.ModifiersBuilders.Modifiers? getModifiers();
+    method public androidx.wear.protolayout.LayoutElementBuilders.VerticalAlignmentProp? getVerticalAlign();
+  }
+
+  public static final class LayoutElementBuilders.Arc.Builder {
+    ctor public LayoutElementBuilders.Arc.Builder();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Arc.Builder addContent(androidx.wear.protolayout.LayoutElementBuilders.ArcLayoutElement);
+    method public androidx.wear.protolayout.LayoutElementBuilders.Arc build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Arc.Builder setAnchorAngle(androidx.wear.protolayout.DimensionBuilders.DegreesProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Arc.Builder setAnchorType(androidx.wear.protolayout.LayoutElementBuilders.ArcAnchorTypeProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Arc.Builder setAnchorType(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.LayoutElementBuilders.Arc.Builder setArcDirection(androidx.wear.protolayout.LayoutElementBuilders.ArcDirectionProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.LayoutElementBuilders.Arc.Builder setArcDirection(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Arc.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.Modifiers);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Arc.Builder setVerticalAlign(androidx.wear.protolayout.LayoutElementBuilders.VerticalAlignmentProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Arc.Builder setVerticalAlign(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.ArcAdapter implements androidx.wear.protolayout.LayoutElementBuilders.ArcLayoutElement {
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getContent();
+    method public androidx.wear.protolayout.TypeBuilders.BoolProp? getRotateContents();
+  }
+
+  public static final class LayoutElementBuilders.ArcAdapter.Builder {
+    ctor public LayoutElementBuilders.ArcAdapter.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.ArcAdapter build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ArcAdapter.Builder setContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ArcAdapter.Builder setRotateContents(androidx.wear.protolayout.TypeBuilders.BoolProp);
+    method public androidx.wear.protolayout.LayoutElementBuilders.ArcAdapter.Builder setRotateContents(boolean);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.ArcAnchorTypeProp {
+    method public int getValue();
+  }
+
+  public static final class LayoutElementBuilders.ArcAnchorTypeProp.Builder {
+    ctor public LayoutElementBuilders.ArcAnchorTypeProp.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.ArcAnchorTypeProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ArcAnchorTypeProp.Builder setValue(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public static final class LayoutElementBuilders.ArcDirectionProp {
+    method public int getValue();
+  }
+
+  public static final class LayoutElementBuilders.ArcDirectionProp.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public LayoutElementBuilders.ArcDirectionProp.Builder(int);
+    method public androidx.wear.protolayout.LayoutElementBuilders.ArcDirectionProp build();
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static interface LayoutElementBuilders.ArcLayoutElement {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.ArcLine implements androidx.wear.protolayout.LayoutElementBuilders.ArcLayoutElement {
+    method public androidx.wear.protolayout.LayoutElementBuilders.ArcDirectionProp? getArcDirection();
+    method public androidx.wear.protolayout.ColorBuilders.Brush? getBrush();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp? getColor();
+    method public androidx.wear.protolayout.DimensionBuilders.AngularLayoutConstraint? getLayoutConstraintsForDynamicLength();
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp? getLength();
+    method public androidx.wear.protolayout.ModifiersBuilders.ArcModifiers? getModifiers();
+    method public androidx.wear.protolayout.LayoutElementBuilders.StrokeCapProp? getStrokeCap();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp? getThickness();
+  }
+
+  public static final class LayoutElementBuilders.ArcLine.Builder {
+    ctor public LayoutElementBuilders.ArcLine.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.ArcLine build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.LayoutElementBuilders.ArcLine.Builder setArcDirection(androidx.wear.protolayout.LayoutElementBuilders.ArcDirectionProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.LayoutElementBuilders.ArcLine.Builder setArcDirection(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.LayoutElementBuilders.ArcLine.Builder setBrush(androidx.wear.protolayout.ColorBuilders.Brush);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ArcLine.Builder setColor(androidx.wear.protolayout.ColorBuilders.ColorProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.ArcLine.Builder setLayoutConstraintsForDynamicLength(androidx.wear.protolayout.DimensionBuilders.AngularLayoutConstraint);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ArcLine.Builder setLength(androidx.wear.protolayout.DimensionBuilders.DegreesProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ArcLine.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.ArcModifiers);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.ArcLine.Builder setStrokeCap(androidx.wear.protolayout.LayoutElementBuilders.StrokeCapProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.ArcLine.Builder setStrokeCap(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ArcLine.Builder setThickness(androidx.wear.protolayout.DimensionBuilders.DpProp);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.ArcSpacer implements androidx.wear.protolayout.LayoutElementBuilders.ArcLayoutElement {
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp? getLength();
+    method public androidx.wear.protolayout.ModifiersBuilders.ArcModifiers? getModifiers();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp? getThickness();
+  }
+
+  public static final class LayoutElementBuilders.ArcSpacer.Builder {
+    ctor public LayoutElementBuilders.ArcSpacer.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.ArcSpacer build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ArcSpacer.Builder setLength(androidx.wear.protolayout.DimensionBuilders.DegreesProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ArcSpacer.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.ArcModifiers);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ArcSpacer.Builder setThickness(androidx.wear.protolayout.DimensionBuilders.DpProp);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.ArcText implements androidx.wear.protolayout.LayoutElementBuilders.ArcLayoutElement {
+    method public androidx.wear.protolayout.LayoutElementBuilders.ArcDirectionProp? getArcDirection();
+    method public androidx.wear.protolayout.LayoutElementBuilders.FontStyle? getFontStyle();
+    method public androidx.wear.protolayout.ModifiersBuilders.ArcModifiers? getModifiers();
+    method public androidx.wear.protolayout.TypeBuilders.StringProp? getText();
+  }
+
+  public static final class LayoutElementBuilders.ArcText.Builder {
+    ctor public LayoutElementBuilders.ArcText.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.ArcText build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.LayoutElementBuilders.ArcText.Builder setArcDirection(androidx.wear.protolayout.LayoutElementBuilders.ArcDirectionProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.LayoutElementBuilders.ArcText.Builder setArcDirection(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ArcText.Builder setFontStyle(androidx.wear.protolayout.LayoutElementBuilders.FontStyle);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ArcText.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.ArcModifiers);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ArcText.Builder setText(androidx.wear.protolayout.TypeBuilders.StringProp);
+    method public androidx.wear.protolayout.LayoutElementBuilders.ArcText.Builder setText(String);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.Box implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public java.util.List<androidx.wear.protolayout.LayoutElementBuilders.LayoutElement!> getContents();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension? getHeight();
+    method public androidx.wear.protolayout.LayoutElementBuilders.HorizontalAlignmentProp? getHorizontalAlignment();
+    method public androidx.wear.protolayout.ModifiersBuilders.Modifiers? getModifiers();
+    method public androidx.wear.protolayout.LayoutElementBuilders.VerticalAlignmentProp? getVerticalAlignment();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension? getWidth();
+  }
+
+  public static final class LayoutElementBuilders.Box.Builder {
+    ctor public LayoutElementBuilders.Box.Builder();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Box.Builder addContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.LayoutElementBuilders.Box build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Box.Builder setHeight(androidx.wear.protolayout.DimensionBuilders.ContainerDimension);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Box.Builder setHorizontalAlignment(androidx.wear.protolayout.LayoutElementBuilders.HorizontalAlignmentProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Box.Builder setHorizontalAlignment(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Box.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.Modifiers);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Box.Builder setVerticalAlignment(androidx.wear.protolayout.LayoutElementBuilders.VerticalAlignmentProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Box.Builder setVerticalAlignment(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Box.Builder setWidth(androidx.wear.protolayout.DimensionBuilders.ContainerDimension);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.ColorFilter {
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp? getTint();
+  }
+
+  public static final class LayoutElementBuilders.ColorFilter.Builder {
+    ctor public LayoutElementBuilders.ColorFilter.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.ColorFilter build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ColorFilter.Builder setTint(androidx.wear.protolayout.ColorBuilders.ColorProp);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.Column implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public java.util.List<androidx.wear.protolayout.LayoutElementBuilders.LayoutElement!> getContents();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension? getHeight();
+    method public androidx.wear.protolayout.LayoutElementBuilders.HorizontalAlignmentProp? getHorizontalAlignment();
+    method public androidx.wear.protolayout.ModifiersBuilders.Modifiers? getModifiers();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension? getWidth();
+  }
+
+  public static final class LayoutElementBuilders.Column.Builder {
+    ctor public LayoutElementBuilders.Column.Builder();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Column.Builder addContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.LayoutElementBuilders.Column build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Column.Builder setHeight(androidx.wear.protolayout.DimensionBuilders.ContainerDimension);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Column.Builder setHorizontalAlignment(androidx.wear.protolayout.LayoutElementBuilders.HorizontalAlignmentProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Column.Builder setHorizontalAlignment(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Column.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.Modifiers);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Column.Builder setWidth(androidx.wear.protolayout.DimensionBuilders.ContainerDimension);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.ContentScaleModeProp {
+    method public int getValue();
+  }
+
+  public static final class LayoutElementBuilders.ContentScaleModeProp.Builder {
+    ctor public LayoutElementBuilders.ContentScaleModeProp.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.ContentScaleModeProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.ContentScaleModeProp.Builder setValue(int);
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ExperimentalProtoLayoutExtensionApi @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class LayoutElementBuilders.ExtensionLayoutElement implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public String getExtensionId();
+    method public androidx.wear.protolayout.DimensionBuilders.ExtensionDimension? getHeight();
+    method public byte[] getPayload();
+    method public androidx.wear.protolayout.DimensionBuilders.ExtensionDimension? getWidth();
+  }
+
+  public static final class LayoutElementBuilders.ExtensionLayoutElement.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public LayoutElementBuilders.ExtensionLayoutElement.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.ExtensionLayoutElement build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.ExtensionLayoutElement.Builder setExtensionId(String);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.ExtensionLayoutElement.Builder setHeight(androidx.wear.protolayout.DimensionBuilders.ExtensionDimension);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.ExtensionLayoutElement.Builder setPayload(byte[]);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.ExtensionLayoutElement.Builder setWidth(androidx.wear.protolayout.DimensionBuilders.ExtensionDimension);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static interface LayoutElementBuilders.FontSetting {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static androidx.wear.protolayout.LayoutElementBuilders.FontSetting tabularNum();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static androidx.wear.protolayout.LayoutElementBuilders.FontSetting weight(@IntRange(from=1, to=1000) int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static androidx.wear.protolayout.LayoutElementBuilders.FontSetting width(@FloatRange(from=25, to=200) float);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.FontStyle {
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp? getColor();
+    method public androidx.wear.protolayout.TypeBuilders.BoolProp? getItalic();
+    method public androidx.wear.protolayout.DimensionBuilders.EmProp? getLetterSpacing();
+    method public java.util.List<java.lang.String!> getPreferredFontFamilies();
+    method public java.util.List<androidx.wear.protolayout.LayoutElementBuilders.FontSetting!> getSettings();
+    method public androidx.wear.protolayout.DimensionBuilders.SpProp? getSize();
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental public java.util.List<androidx.wear.protolayout.DimensionBuilders.SpProp!> getSizes();
+    method public androidx.wear.protolayout.TypeBuilders.BoolProp? getUnderline();
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental public androidx.wear.protolayout.LayoutElementBuilders.FontVariantProp? getVariant();
+    method public androidx.wear.protolayout.LayoutElementBuilders.FontWeightProp? getWeight();
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static final String ROBOTO_FLEX_FONT = "roboto-flex";
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static final String ROBOTO_FONT = "roboto";
+  }
+
+  public static final class LayoutElementBuilders.FontStyle.Builder {
+    ctor public LayoutElementBuilders.FontStyle.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.FontStyle build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder setColor(androidx.wear.protolayout.ColorBuilders.ColorProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder setItalic(androidx.wear.protolayout.TypeBuilders.BoolProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder setItalic(boolean);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder setLetterSpacing(androidx.wear.protolayout.DimensionBuilders.EmProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder setPreferredFontFamilies(String, java.lang.String!...);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder setSettings(androidx.wear.protolayout.LayoutElementBuilders.FontSetting!...);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder setSize(androidx.wear.protolayout.DimensionBuilders.SpProp);
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder setSizes(@Dimension(unit=androidx.annotation.Dimension.SP) @IntRange(from=1) int...);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder setUnderline(androidx.wear.protolayout.TypeBuilders.BoolProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder setUnderline(boolean);
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder setVariant(androidx.wear.protolayout.LayoutElementBuilders.FontVariantProp);
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder setVariant(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder setWeight(androidx.wear.protolayout.LayoutElementBuilders.FontWeightProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder setWeight(int);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.FontStyles {
+    method @Deprecated public static androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder body1(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder body2(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder button(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder caption1(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder caption2(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder display1(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder display2(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder display3(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder title1(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder title2(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.protolayout.LayoutElementBuilders.FontStyle.Builder title3(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.FontVariantProp {
+    method public int getValue();
+  }
+
+  public static final class LayoutElementBuilders.FontVariantProp.Builder {
+    ctor public LayoutElementBuilders.FontVariantProp.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.FontVariantProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.FontVariantProp.Builder setValue(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.FontWeightProp {
+    method public int getValue();
+  }
+
+  public static final class LayoutElementBuilders.FontWeightProp.Builder {
+    ctor public LayoutElementBuilders.FontWeightProp.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.FontWeightProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.FontWeightProp.Builder setValue(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.HorizontalAlignmentProp {
+    method public int getValue();
+  }
+
+  public static final class LayoutElementBuilders.HorizontalAlignmentProp.Builder {
+    ctor public LayoutElementBuilders.HorizontalAlignmentProp.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.HorizontalAlignmentProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.HorizontalAlignmentProp.Builder setValue(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.Image implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public androidx.wear.protolayout.LayoutElementBuilders.ColorFilter? getColorFilter();
+    method public androidx.wear.protolayout.LayoutElementBuilders.ContentScaleModeProp? getContentScaleMode();
+    method public androidx.wear.protolayout.DimensionBuilders.ImageDimension? getHeight();
+    method public androidx.wear.protolayout.ModifiersBuilders.Modifiers? getModifiers();
+    method public androidx.wear.protolayout.TypeBuilders.StringProp? getResourceId();
+    method public androidx.wear.protolayout.DimensionBuilders.ImageDimension? getWidth();
+  }
+
+  public static final class LayoutElementBuilders.Image.Builder {
+    ctor public LayoutElementBuilders.Image.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.Image build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Image.Builder setColorFilter(androidx.wear.protolayout.LayoutElementBuilders.ColorFilter);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Image.Builder setContentScaleMode(androidx.wear.protolayout.LayoutElementBuilders.ContentScaleModeProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Image.Builder setContentScaleMode(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Image.Builder setHeight(androidx.wear.protolayout.DimensionBuilders.ImageDimension);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Image.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.Modifiers);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Image.Builder setResourceId(androidx.wear.protolayout.TypeBuilders.StringProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Image.Builder setResourceId(String);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Image.Builder setWidth(androidx.wear.protolayout.DimensionBuilders.ImageDimension);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.Layout {
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental public static androidx.wear.protolayout.LayoutElementBuilders.Layout? fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.LayoutElementBuilders.Layout fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getRoot();
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental public byte[] toByteArray();
+  }
+
+  public static final class LayoutElementBuilders.Layout.Builder {
+    ctor public LayoutElementBuilders.Layout.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.Layout build();
+    method public androidx.wear.protolayout.LayoutElementBuilders.Layout.Builder setRoot(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static interface LayoutElementBuilders.LayoutElement {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.Row implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public java.util.List<androidx.wear.protolayout.LayoutElementBuilders.LayoutElement!> getContents();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension? getHeight();
+    method public androidx.wear.protolayout.ModifiersBuilders.Modifiers? getModifiers();
+    method public androidx.wear.protolayout.LayoutElementBuilders.VerticalAlignmentProp? getVerticalAlignment();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension? getWidth();
+  }
+
+  public static final class LayoutElementBuilders.Row.Builder {
+    ctor public LayoutElementBuilders.Row.Builder();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Row.Builder addContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.LayoutElementBuilders.Row build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Row.Builder setHeight(androidx.wear.protolayout.DimensionBuilders.ContainerDimension);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Row.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.Modifiers);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Row.Builder setVerticalAlignment(androidx.wear.protolayout.LayoutElementBuilders.VerticalAlignmentProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Row.Builder setVerticalAlignment(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Row.Builder setWidth(androidx.wear.protolayout.DimensionBuilders.ContainerDimension);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.Spacer implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public androidx.wear.protolayout.DimensionBuilders.SpacerDimension? getHeight();
+    method public androidx.wear.protolayout.DimensionBuilders.VerticalLayoutConstraint? getLayoutConstraintsForDynamicHeight();
+    method public androidx.wear.protolayout.DimensionBuilders.HorizontalLayoutConstraint? getLayoutConstraintsForDynamicWidth();
+    method public androidx.wear.protolayout.ModifiersBuilders.Modifiers? getModifiers();
+    method public androidx.wear.protolayout.DimensionBuilders.SpacerDimension? getWidth();
+  }
+
+  public static final class LayoutElementBuilders.Spacer.Builder {
+    ctor public LayoutElementBuilders.Spacer.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.Spacer build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Spacer.Builder setHeight(androidx.wear.protolayout.DimensionBuilders.SpacerDimension);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.Spacer.Builder setLayoutConstraintsForDynamicHeight(androidx.wear.protolayout.DimensionBuilders.VerticalLayoutConstraint);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.Spacer.Builder setLayoutConstraintsForDynamicWidth(androidx.wear.protolayout.DimensionBuilders.HorizontalLayoutConstraint);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Spacer.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.Modifiers);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Spacer.Builder setWidth(androidx.wear.protolayout.DimensionBuilders.SpacerDimension);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static interface LayoutElementBuilders.Span {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.SpanImage implements androidx.wear.protolayout.LayoutElementBuilders.Span {
+    method public androidx.wear.protolayout.LayoutElementBuilders.SpanVerticalAlignmentProp? getAlignment();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp? getHeight();
+    method public androidx.wear.protolayout.ModifiersBuilders.SpanModifiers? getModifiers();
+    method public androidx.wear.protolayout.TypeBuilders.StringProp? getResourceId();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp? getWidth();
+  }
+
+  public static final class LayoutElementBuilders.SpanImage.Builder {
+    ctor public LayoutElementBuilders.SpanImage.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.SpanImage build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.SpanImage.Builder setAlignment(androidx.wear.protolayout.LayoutElementBuilders.SpanVerticalAlignmentProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.SpanImage.Builder setAlignment(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.SpanImage.Builder setHeight(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.SpanImage.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.SpanModifiers);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.SpanImage.Builder setResourceId(androidx.wear.protolayout.TypeBuilders.StringProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.SpanImage.Builder setResourceId(String);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.SpanImage.Builder setWidth(androidx.wear.protolayout.DimensionBuilders.DpProp);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.SpanText implements androidx.wear.protolayout.LayoutElementBuilders.Span {
+    method public androidx.wear.protolayout.LayoutElementBuilders.FontStyle? getFontStyle();
+    method public androidx.wear.protolayout.ModifiersBuilders.SpanModifiers? getModifiers();
+    method public androidx.wear.protolayout.TypeBuilders.StringProp? getText();
+  }
+
+  public static final class LayoutElementBuilders.SpanText.Builder {
+    ctor public LayoutElementBuilders.SpanText.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.SpanText build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.SpanText.Builder setFontStyle(androidx.wear.protolayout.LayoutElementBuilders.FontStyle);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.SpanText.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.SpanModifiers);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.SpanText.Builder setText(androidx.wear.protolayout.TypeBuilders.StringProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.SpanText.Builder setText(String);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.SpanVerticalAlignmentProp {
+    method public int getValue();
+  }
+
+  public static final class LayoutElementBuilders.SpanVerticalAlignmentProp.Builder {
+    ctor public LayoutElementBuilders.SpanVerticalAlignmentProp.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.SpanVerticalAlignmentProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.SpanVerticalAlignmentProp.Builder setValue(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.Spannable implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public androidx.wear.protolayout.DimensionBuilders.SpProp? getLineHeight();
+    method @SuppressCompatibility @IntRange(from=0xffffffff) @androidx.wear.protolayout.expression.ProtoLayoutExperimental public int getMarqueeIterations();
+    method public androidx.wear.protolayout.TypeBuilders.Int32Prop? getMaxLines();
+    method public androidx.wear.protolayout.ModifiersBuilders.Modifiers? getModifiers();
+    method public androidx.wear.protolayout.LayoutElementBuilders.HorizontalAlignmentProp? getMultilineAlignment();
+    method public androidx.wear.protolayout.LayoutElementBuilders.TextOverflowProp? getOverflow();
+    method public java.util.List<androidx.wear.protolayout.LayoutElementBuilders.Span!> getSpans();
+  }
+
+  public static final class LayoutElementBuilders.Spannable.Builder {
+    ctor public LayoutElementBuilders.Spannable.Builder();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Spannable.Builder addSpan(androidx.wear.protolayout.LayoutElementBuilders.Span);
+    method public androidx.wear.protolayout.LayoutElementBuilders.Spannable build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Spannable.Builder setLineHeight(androidx.wear.protolayout.DimensionBuilders.SpProp);
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.Spannable.Builder setMarqueeIterations(@IntRange(from=0xffffffff) int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Spannable.Builder setMaxLines(androidx.wear.protolayout.TypeBuilders.Int32Prop);
+    method public androidx.wear.protolayout.LayoutElementBuilders.Spannable.Builder setMaxLines(@IntRange(from=1) int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Spannable.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.Modifiers);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Spannable.Builder setMultilineAlignment(androidx.wear.protolayout.LayoutElementBuilders.HorizontalAlignmentProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Spannable.Builder setMultilineAlignment(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Spannable.Builder setOverflow(androidx.wear.protolayout.LayoutElementBuilders.TextOverflowProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Spannable.Builder setOverflow(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class LayoutElementBuilders.StrokeCapProp {
+    method public androidx.wear.protolayout.ModifiersBuilders.Shadow? getShadow();
+    method public int getValue();
+  }
+
+  public static final class LayoutElementBuilders.StrokeCapProp.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public LayoutElementBuilders.StrokeCapProp.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.StrokeCapProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.LayoutElementBuilders.StrokeCapProp.Builder setShadow(androidx.wear.protolayout.ModifiersBuilders.Shadow);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.StrokeCapProp.Builder setValue(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.Text implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+    method public androidx.wear.protolayout.LayoutElementBuilders.FontStyle? getFontStyle();
+    method public androidx.wear.protolayout.TypeBuilders.StringLayoutConstraint? getLayoutConstraintsForDynamicText();
+    method public androidx.wear.protolayout.DimensionBuilders.SpProp? getLineHeight();
+    method @SuppressCompatibility @IntRange(from=0xffffffff) @androidx.wear.protolayout.expression.ProtoLayoutExperimental public int getMarqueeIterations();
+    method public androidx.wear.protolayout.TypeBuilders.Int32Prop? getMaxLines();
+    method public androidx.wear.protolayout.ModifiersBuilders.Modifiers? getModifiers();
+    method public androidx.wear.protolayout.LayoutElementBuilders.TextAlignmentProp? getMultilineAlignment();
+    method public androidx.wear.protolayout.LayoutElementBuilders.TextOverflowProp? getOverflow();
+    method public androidx.wear.protolayout.TypeBuilders.StringProp? getText();
+  }
+
+  public static final class LayoutElementBuilders.Text.Builder {
+    ctor public LayoutElementBuilders.Text.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.Text build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Text.Builder setFontStyle(androidx.wear.protolayout.LayoutElementBuilders.FontStyle);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.Text.Builder setLayoutConstraintsForDynamicText(androidx.wear.protolayout.TypeBuilders.StringLayoutConstraint);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Text.Builder setLineHeight(androidx.wear.protolayout.DimensionBuilders.SpProp);
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.Text.Builder setMarqueeIterations(@IntRange(from=0xffffffff) int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Text.Builder setMaxLines(androidx.wear.protolayout.TypeBuilders.Int32Prop);
+    method public androidx.wear.protolayout.LayoutElementBuilders.Text.Builder setMaxLines(@IntRange(from=1) int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Text.Builder setModifiers(androidx.wear.protolayout.ModifiersBuilders.Modifiers);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Text.Builder setMultilineAlignment(androidx.wear.protolayout.LayoutElementBuilders.TextAlignmentProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Text.Builder setMultilineAlignment(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Text.Builder setOverflow(androidx.wear.protolayout.LayoutElementBuilders.TextOverflowProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Text.Builder setOverflow(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Text.Builder setText(androidx.wear.protolayout.TypeBuilders.StringProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.Text.Builder setText(String);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.TextAlignmentProp {
+    method public int getValue();
+  }
+
+  public static final class LayoutElementBuilders.TextAlignmentProp.Builder {
+    ctor public LayoutElementBuilders.TextAlignmentProp.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.TextAlignmentProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.TextAlignmentProp.Builder setValue(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.TextOverflowProp {
+    method public int getValue();
+  }
+
+  public static final class LayoutElementBuilders.TextOverflowProp.Builder {
+    ctor public LayoutElementBuilders.TextOverflowProp.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.TextOverflowProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.TextOverflowProp.Builder setValue(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.VerticalAlignmentProp {
+    method public int getValue();
+  }
+
+  public static final class LayoutElementBuilders.VerticalAlignmentProp.Builder {
+    ctor public LayoutElementBuilders.VerticalAlignmentProp.Builder();
+    method public androidx.wear.protolayout.LayoutElementBuilders.VerticalAlignmentProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.LayoutElementBuilders.VerticalAlignmentProp.Builder setValue(int);
+  }
+
+  public final class ModifiersBuilders {
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int SEMANTICS_ROLE_BUTTON = 2; // 0x2
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int SEMANTICS_ROLE_CHECKBOX = 3; // 0x3
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int SEMANTICS_ROLE_IMAGE = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int SEMANTICS_ROLE_NONE = 0; // 0x0
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int SEMANTICS_ROLE_RADIOBUTTON = 5; // 0x5
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int SEMANTICS_ROLE_SWITCH = 4; // 0x4
+    field @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int SLIDE_DIRECTION_BOTTOM_TO_TOP = 4; // 0x4
+    field @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int SLIDE_DIRECTION_LEFT_TO_RIGHT = 1; // 0x1
+    field @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int SLIDE_DIRECTION_RIGHT_TO_LEFT = 2; // 0x2
+    field @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int SLIDE_DIRECTION_TOP_TO_BOTTOM = 3; // 0x3
+    field @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int SLIDE_DIRECTION_UNDEFINED = 0; // 0x0
+    field @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int SLIDE_PARENT_SNAP_TO_INSIDE = 1; // 0x1
+    field @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int SLIDE_PARENT_SNAP_TO_OUTSIDE = 2; // 0x2
+    field @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int SLIDE_PARENT_SNAP_UNDEFINED = 0; // 0x0
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class ModifiersBuilders.AnimatedVisibility {
+    method public androidx.wear.protolayout.ModifiersBuilders.EnterTransition? getEnterTransition();
+    method public androidx.wear.protolayout.ModifiersBuilders.ExitTransition? getExitTransition();
+  }
+
+  public static final class ModifiersBuilders.AnimatedVisibility.Builder {
+    ctor public ModifiersBuilders.AnimatedVisibility.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.AnimatedVisibility build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.AnimatedVisibility.Builder setEnterTransition(androidx.wear.protolayout.ModifiersBuilders.EnterTransition);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.AnimatedVisibility.Builder setExitTransition(androidx.wear.protolayout.ModifiersBuilders.ExitTransition);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ModifiersBuilders.ArcModifiers {
+    method public androidx.wear.protolayout.ModifiersBuilders.Clickable? getClickable();
+    method public androidx.wear.protolayout.TypeBuilders.FloatProp? getOpacity();
+    method public androidx.wear.protolayout.ModifiersBuilders.Semantics? getSemantics();
+  }
+
+  public static final class ModifiersBuilders.ArcModifiers.Builder {
+    ctor public ModifiersBuilders.ArcModifiers.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.ArcModifiers build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.ArcModifiers.Builder setClickable(androidx.wear.protolayout.ModifiersBuilders.Clickable);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.ArcModifiers.Builder setOpacity(androidx.wear.protolayout.TypeBuilders.FloatProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.ArcModifiers.Builder setSemantics(androidx.wear.protolayout.ModifiersBuilders.Semantics);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ModifiersBuilders.Background {
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp? getColor();
+    method public androidx.wear.protolayout.ModifiersBuilders.Corner? getCorner();
+  }
+
+  public static final class ModifiersBuilders.Background.Builder {
+    ctor public ModifiersBuilders.Background.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.Background build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Background.Builder setColor(androidx.wear.protolayout.ColorBuilders.ColorProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Background.Builder setCorner(androidx.wear.protolayout.ModifiersBuilders.Corner);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ModifiersBuilders.Border {
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp? getColor();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp? getWidth();
+  }
+
+  public static final class ModifiersBuilders.Border.Builder {
+    ctor public ModifiersBuilders.Border.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.Border build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Border.Builder setColor(androidx.wear.protolayout.ColorBuilders.ColorProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Border.Builder setWidth(androidx.wear.protolayout.DimensionBuilders.DpProp);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ModifiersBuilders.Clickable {
+    method public String getId();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp getMinimumClickableHeight();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp getMinimumClickableWidth();
+    method public androidx.wear.protolayout.ActionBuilders.Action? getOnClick();
+    method public boolean isVisualFeedbackEnabled();
+  }
+
+  public static final class ModifiersBuilders.Clickable.Builder {
+    ctor public ModifiersBuilders.Clickable.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.Clickable build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Clickable.Builder setId(String);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.ModifiersBuilders.Clickable.Builder setMinimumClickableHeight(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.ModifiersBuilders.Clickable.Builder setMinimumClickableWidth(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Clickable.Builder setOnClick(androidx.wear.protolayout.ActionBuilders.Action);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Clickable.Builder setVisualFeedbackEnabled(boolean);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ModifiersBuilders.Corner {
+    method public androidx.wear.protolayout.ModifiersBuilders.CornerRadius getBottomLeftRadius();
+    method public androidx.wear.protolayout.ModifiersBuilders.CornerRadius getBottomRightRadius();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp? getRadius();
+    method public androidx.wear.protolayout.ModifiersBuilders.CornerRadius getTopLeftRadius();
+    method public androidx.wear.protolayout.ModifiersBuilders.CornerRadius getTopRightRadius();
+  }
+
+  public static final class ModifiersBuilders.Corner.Builder {
+    ctor public ModifiersBuilders.Corner.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.Corner build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Corner.Builder setBottomLeftRadius(androidx.wear.protolayout.DimensionBuilders.DpProp, androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Corner.Builder setBottomLeftRadius(androidx.wear.protolayout.ModifiersBuilders.CornerRadius);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Corner.Builder setBottomRightRadius(androidx.wear.protolayout.DimensionBuilders.DpProp, androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Corner.Builder setBottomRightRadius(androidx.wear.protolayout.ModifiersBuilders.CornerRadius);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Corner.Builder setRadius(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Corner.Builder setTopLeftRadius(androidx.wear.protolayout.DimensionBuilders.DpProp, androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Corner.Builder setTopLeftRadius(androidx.wear.protolayout.ModifiersBuilders.CornerRadius);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Corner.Builder setTopRightRadius(androidx.wear.protolayout.DimensionBuilders.DpProp, androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Corner.Builder setTopRightRadius(androidx.wear.protolayout.ModifiersBuilders.CornerRadius);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static final class ModifiersBuilders.CornerRadius {
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp getX();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp getY();
+  }
+
+  public static final class ModifiersBuilders.CornerRadius.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public ModifiersBuilders.CornerRadius.Builder(androidx.wear.protolayout.DimensionBuilders.DpProp, androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method public androidx.wear.protolayout.ModifiersBuilders.CornerRadius build();
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental public static final class ModifiersBuilders.DefaultContentTransitions {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.ModifiersBuilders.EnterTransition fadeIn();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.ModifiersBuilders.EnterTransition fadeInSlideIn(@SuppressCompatibility int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.ModifiersBuilders.ExitTransition fadeOut();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.ModifiersBuilders.ExitTransition fadeOutSlideOut(@SuppressCompatibility int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.ModifiersBuilders.EnterTransition slideIn(@SuppressCompatibility int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.ModifiersBuilders.ExitTransition slideOut(@SuppressCompatibility int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ModifiersBuilders.ElementMetadata {
+    method public byte[] getTagData();
+  }
+
+  public static final class ModifiersBuilders.ElementMetadata.Builder {
+    ctor public ModifiersBuilders.ElementMetadata.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.ElementMetadata build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.ElementMetadata.Builder setTagData(byte[]);
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class ModifiersBuilders.EnterTransition {
+    method public androidx.wear.protolayout.ModifiersBuilders.FadeInTransition? getFadeIn();
+    method public androidx.wear.protolayout.ModifiersBuilders.SlideInTransition? getSlideIn();
+  }
+
+  public static final class ModifiersBuilders.EnterTransition.Builder {
+    ctor public ModifiersBuilders.EnterTransition.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.EnterTransition build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.EnterTransition.Builder setFadeIn(androidx.wear.protolayout.ModifiersBuilders.FadeInTransition);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.EnterTransition.Builder setSlideIn(androidx.wear.protolayout.ModifiersBuilders.SlideInTransition);
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class ModifiersBuilders.ExitTransition {
+    method public androidx.wear.protolayout.ModifiersBuilders.FadeOutTransition? getFadeOut();
+    method public androidx.wear.protolayout.ModifiersBuilders.SlideOutTransition? getSlideOut();
+  }
+
+  public static final class ModifiersBuilders.ExitTransition.Builder {
+    ctor public ModifiersBuilders.ExitTransition.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.ExitTransition build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.ExitTransition.Builder setFadeOut(androidx.wear.protolayout.ModifiersBuilders.FadeOutTransition);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.ExitTransition.Builder setSlideOut(androidx.wear.protolayout.ModifiersBuilders.SlideOutTransition);
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class ModifiersBuilders.FadeInTransition {
+    method public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec? getAnimationSpec();
+    method @FloatRange(from=0.0, to=1.0) public float getInitialAlpha();
+  }
+
+  public static final class ModifiersBuilders.FadeInTransition.Builder {
+    ctor public ModifiersBuilders.FadeInTransition.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.FadeInTransition build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.FadeInTransition.Builder setAnimationSpec(androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.FadeInTransition.Builder setInitialAlpha(@FloatRange(from=0.0, to=1.0) float);
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class ModifiersBuilders.FadeOutTransition {
+    method public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec? getAnimationSpec();
+    method @FloatRange(from=0.0, to=1.0) public float getTargetAlpha();
+  }
+
+  public static final class ModifiersBuilders.FadeOutTransition.Builder {
+    ctor public ModifiersBuilders.FadeOutTransition.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.FadeOutTransition build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.FadeOutTransition.Builder setAnimationSpec(androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
+    method public androidx.wear.protolayout.ModifiersBuilders.FadeOutTransition.Builder setTargetAlpha(@FloatRange(from=0.0, to=1.0) float);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ModifiersBuilders.Modifiers {
+    method public androidx.wear.protolayout.ModifiersBuilders.Background? getBackground();
+    method public androidx.wear.protolayout.ModifiersBuilders.Border? getBorder();
+    method public androidx.wear.protolayout.ModifiersBuilders.Clickable? getClickable();
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental public androidx.wear.protolayout.ModifiersBuilders.AnimatedVisibility? getContentUpdateAnimation();
+    method public androidx.wear.protolayout.ModifiersBuilders.ElementMetadata? getMetadata();
+    method public androidx.wear.protolayout.TypeBuilders.FloatProp? getOpacity();
+    method public androidx.wear.protolayout.ModifiersBuilders.Padding? getPadding();
+    method public androidx.wear.protolayout.ModifiersBuilders.Semantics? getSemantics();
+    method public androidx.wear.protolayout.ModifiersBuilders.Transformation? getTransformation();
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental public androidx.wear.protolayout.TypeBuilders.BoolProp isVisible();
+  }
+
+  public static final class ModifiersBuilders.Modifiers.Builder {
+    ctor public ModifiersBuilders.Modifiers.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.Modifiers build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Modifiers.Builder setBackground(androidx.wear.protolayout.ModifiersBuilders.Background);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Modifiers.Builder setBorder(androidx.wear.protolayout.ModifiersBuilders.Border);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Modifiers.Builder setClickable(androidx.wear.protolayout.ModifiersBuilders.Clickable);
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.Modifiers.Builder setContentUpdateAnimation(androidx.wear.protolayout.ModifiersBuilders.AnimatedVisibility);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Modifiers.Builder setMetadata(androidx.wear.protolayout.ModifiersBuilders.ElementMetadata);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Modifiers.Builder setOpacity(androidx.wear.protolayout.TypeBuilders.FloatProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Modifiers.Builder setPadding(androidx.wear.protolayout.ModifiersBuilders.Padding);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Modifiers.Builder setSemantics(androidx.wear.protolayout.ModifiersBuilders.Semantics);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Modifiers.Builder setTransformation(androidx.wear.protolayout.ModifiersBuilders.Transformation);
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.ModifiersBuilders.Modifiers.Builder setVisible(androidx.wear.protolayout.TypeBuilders.BoolProp);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ModifiersBuilders.Padding {
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp? getBottom();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp? getEnd();
+    method public androidx.wear.protolayout.TypeBuilders.BoolProp? getRtlAware();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp? getStart();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp? getTop();
+  }
+
+  public static final class ModifiersBuilders.Padding.Builder {
+    ctor public ModifiersBuilders.Padding.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.Padding build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Padding.Builder setAll(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Padding.Builder setBottom(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Padding.Builder setEnd(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Padding.Builder setRtlAware(androidx.wear.protolayout.TypeBuilders.BoolProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Padding.Builder setRtlAware(boolean);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Padding.Builder setStart(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Padding.Builder setTop(androidx.wear.protolayout.DimensionBuilders.DpProp);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ModifiersBuilders.Semantics {
+    method public androidx.wear.protolayout.TypeBuilders.StringProp? getContentDescription();
+    method public int getRole();
+    method public androidx.wear.protolayout.TypeBuilders.StringProp? getStateDescription();
+  }
+
+  public static final class ModifiersBuilders.Semantics.Builder {
+    ctor public ModifiersBuilders.Semantics.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.Semantics build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Semantics.Builder setContentDescription(androidx.wear.protolayout.TypeBuilders.StringProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.Semantics.Builder setContentDescription(String);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.Semantics.Builder setRole(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.Semantics.Builder setStateDescription(androidx.wear.protolayout.TypeBuilders.StringProp);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public static final class ModifiersBuilders.Shadow {
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp getBlurRadius();
+    method public androidx.wear.protolayout.ColorBuilders.ColorProp getColor();
+  }
+
+  public static final class ModifiersBuilders.Shadow.Builder {
+    ctor public ModifiersBuilders.Shadow.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.Shadow build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.ModifiersBuilders.Shadow.Builder setBlurRadius(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.ModifiersBuilders.Shadow.Builder setColor(androidx.wear.protolayout.ColorBuilders.ColorProp);
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static interface ModifiersBuilders.SlideBound {
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class ModifiersBuilders.SlideInTransition {
+    method public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec? getAnimationSpec();
+    method @SuppressCompatibility public int getDirection();
+    method public androidx.wear.protolayout.ModifiersBuilders.SlideBound? getInitialSlideBound();
+  }
+
+  public static final class ModifiersBuilders.SlideInTransition.Builder {
+    ctor public ModifiersBuilders.SlideInTransition.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.SlideInTransition build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.SlideInTransition.Builder setAnimationSpec(androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.SlideInTransition.Builder setDirection(@SuppressCompatibility int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.SlideInTransition.Builder setInitialSlideBound(androidx.wear.protolayout.ModifiersBuilders.SlideBound);
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class ModifiersBuilders.SlideOutTransition {
+    method public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec? getAnimationSpec();
+    method @SuppressCompatibility public int getDirection();
+    method public androidx.wear.protolayout.ModifiersBuilders.SlideBound? getTargetSlideBound();
+  }
+
+  public static final class ModifiersBuilders.SlideOutTransition.Builder {
+    ctor public ModifiersBuilders.SlideOutTransition.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.SlideOutTransition build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.SlideOutTransition.Builder setAnimationSpec(androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.SlideOutTransition.Builder setDirection(@SuppressCompatibility int);
+    method public androidx.wear.protolayout.ModifiersBuilders.SlideOutTransition.Builder setTargetSlideBound(androidx.wear.protolayout.ModifiersBuilders.SlideBound);
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class ModifiersBuilders.SlideParentBound implements androidx.wear.protolayout.ModifiersBuilders.SlideBound {
+    method @SuppressCompatibility public int getSnapTo();
+  }
+
+  public static final class ModifiersBuilders.SlideParentBound.Builder {
+    ctor public ModifiersBuilders.SlideParentBound.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.SlideParentBound build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ModifiersBuilders.SlideParentBound.Builder setSnapTo(@SuppressCompatibility int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ModifiersBuilders.SpanModifiers {
+    method public androidx.wear.protolayout.ModifiersBuilders.Clickable? getClickable();
+  }
+
+  public static final class ModifiersBuilders.SpanModifiers.Builder {
+    ctor public ModifiersBuilders.SpanModifiers.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.SpanModifiers build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ModifiersBuilders.SpanModifiers.Builder setClickable(androidx.wear.protolayout.ModifiersBuilders.Clickable);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static final class ModifiersBuilders.Transformation {
+    method public androidx.wear.protolayout.DimensionBuilders.PivotDimension getPivotX();
+    method public androidx.wear.protolayout.DimensionBuilders.PivotDimension getPivotY();
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp getRotation();
+    method public androidx.wear.protolayout.TypeBuilders.FloatProp getScaleX();
+    method public androidx.wear.protolayout.TypeBuilders.FloatProp getScaleY();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp getTranslationX();
+    method public androidx.wear.protolayout.DimensionBuilders.DpProp getTranslationY();
+  }
+
+  public static final class ModifiersBuilders.Transformation.Builder {
+    ctor public ModifiersBuilders.Transformation.Builder();
+    method public androidx.wear.protolayout.ModifiersBuilders.Transformation build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Transformation.Builder setPivotX(androidx.wear.protolayout.DimensionBuilders.PivotDimension);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Transformation.Builder setPivotY(androidx.wear.protolayout.DimensionBuilders.PivotDimension);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Transformation.Builder setRotation(androidx.wear.protolayout.DimensionBuilders.DegreesProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Transformation.Builder setScaleX(androidx.wear.protolayout.TypeBuilders.FloatProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Transformation.Builder setScaleY(androidx.wear.protolayout.TypeBuilders.FloatProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Transformation.Builder setTranslationX(androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.protolayout.ModifiersBuilders.Transformation.Builder setTranslationY(androidx.wear.protolayout.DimensionBuilders.DpProp);
+  }
+
+  public final class ResourceBuilders {
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int ANIMATED_IMAGE_FORMAT_AVD = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int ANIMATED_IMAGE_FORMAT_UNDEFINED = 0; // 0x0
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final int IMAGE_FORMAT_ARGB_8888 = 2; // 0x2
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int IMAGE_FORMAT_RGB_565 = 1; // 0x1
+    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final int IMAGE_FORMAT_UNDEFINED = 0; // 0x0
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class ResourceBuilders.AndroidAnimatedImageResourceByResId {
+    method public int getAnimatedImageFormat();
+    method @DrawableRes public int getResourceId();
+    method public androidx.wear.protolayout.TriggerBuilders.Trigger? getStartTrigger();
+  }
+
+  public static final class ResourceBuilders.AndroidAnimatedImageResourceByResId.Builder {
+    ctor public ResourceBuilders.AndroidAnimatedImageResourceByResId.Builder();
+    method public androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId.Builder setAnimatedImageFormat(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId.Builder setResourceId(@DrawableRes int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId.Builder setStartTrigger(androidx.wear.protolayout.TriggerBuilders.Trigger);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ResourceBuilders.AndroidImageResourceByResId {
+    method @DrawableRes public int getResourceId();
+  }
+
+  public static final class ResourceBuilders.AndroidImageResourceByResId.Builder {
+    ctor public ResourceBuilders.AndroidImageResourceByResId.Builder();
+    method public androidx.wear.protolayout.ResourceBuilders.AndroidImageResourceByResId build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ResourceBuilders.AndroidImageResourceByResId.Builder setResourceId(@DrawableRes int);
+  }
+
+  @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId {
+    method public int getAnimatedImageFormat();
+    method public androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat? getProgress();
+    method @DrawableRes public int getResourceId();
+  }
+
+  public static final class ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId.Builder {
+    ctor public ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId.Builder();
+    method public androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId.Builder setAnimatedImageFormat(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId.Builder setProgress(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId.Builder setResourceId(@DrawableRes int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ResourceBuilders.ImageResource {
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental public androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId? getAndroidAnimatedResourceByResId();
+    method public androidx.wear.protolayout.ResourceBuilders.AndroidImageResourceByResId? getAndroidResourceByResId();
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental public androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId? getAndroidSeekableAnimatedResourceByResId();
+    method public androidx.wear.protolayout.ResourceBuilders.InlineImageResource? getInlineResource();
+  }
+
+  public static final class ResourceBuilders.ImageResource.Builder {
+    ctor public ResourceBuilders.ImageResource.Builder();
+    method public androidx.wear.protolayout.ResourceBuilders.ImageResource build();
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ResourceBuilders.ImageResource.Builder setAndroidAnimatedResourceByResId(androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ResourceBuilders.ImageResource.Builder setAndroidResourceByResId(androidx.wear.protolayout.ResourceBuilders.AndroidImageResourceByResId);
+    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.ResourceBuilders.ImageResource.Builder setAndroidSeekableAnimatedResourceByResId(androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ResourceBuilders.ImageResource.Builder setInlineResource(androidx.wear.protolayout.ResourceBuilders.InlineImageResource);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ResourceBuilders.InlineImageResource {
+    method public byte[] getData();
+    method public int getFormat();
+    method @Dimension(unit=androidx.annotation.Dimension.PX) public int getHeightPx();
+    method @Dimension(unit=androidx.annotation.Dimension.PX) public int getWidthPx();
+  }
+
+  public static final class ResourceBuilders.InlineImageResource.Builder {
+    ctor public ResourceBuilders.InlineImageResource.Builder();
+    method public androidx.wear.protolayout.ResourceBuilders.InlineImageResource build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ResourceBuilders.InlineImageResource.Builder setData(byte[]);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ResourceBuilders.InlineImageResource.Builder setFormat(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ResourceBuilders.InlineImageResource.Builder setHeightPx(@Dimension(unit=androidx.annotation.Dimension.PX) int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ResourceBuilders.InlineImageResource.Builder setWidthPx(@Dimension(unit=androidx.annotation.Dimension.PX) int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class ResourceBuilders.Resources {
+    method public java.util.Map<java.lang.String!,androidx.wear.protolayout.ResourceBuilders.ImageResource!> getIdToImageMapping();
+    method public String getVersion();
+  }
+
+  public static final class ResourceBuilders.Resources.Builder {
+    ctor public ResourceBuilders.Resources.Builder();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ResourceBuilders.Resources.Builder addIdToImageMapping(String, androidx.wear.protolayout.ResourceBuilders.ImageResource);
+    method public androidx.wear.protolayout.ResourceBuilders.Resources build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.ResourceBuilders.Resources.Builder setVersion(String);
+  }
+
+  public final class StateBuilders {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class StateBuilders.State {
+    method public java.util.Map<androidx.wear.protolayout.expression.AppDataKey<? extends java.lang.Object!>!,androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<? extends java.lang.Object!>!> getKeyToValueMapping();
+    method public String getLastClickableId();
+    method public static int getMaxStateEntryCount();
+  }
+
+  public static final class StateBuilders.State.Builder {
+    ctor public StateBuilders.State.Builder();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public <T extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType> androidx.wear.protolayout.StateBuilders.State.Builder addKeyToValueMapping(androidx.wear.protolayout.expression.AppDataKey<T!>, androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<T!>);
+    method public androidx.wear.protolayout.StateBuilders.State build();
+  }
+
+  public final class TimelineBuilders {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class TimelineBuilders.TimeInterval {
+    method public long getEndMillis();
+    method public long getStartMillis();
+  }
+
+  public static final class TimelineBuilders.TimeInterval.Builder {
+    ctor public TimelineBuilders.TimeInterval.Builder();
+    method public androidx.wear.protolayout.TimelineBuilders.TimeInterval build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.TimelineBuilders.TimeInterval.Builder setEndMillis(long);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.TimelineBuilders.TimeInterval.Builder setStartMillis(long);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class TimelineBuilders.Timeline {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static androidx.wear.protolayout.TimelineBuilders.Timeline fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public java.util.List<androidx.wear.protolayout.TimelineBuilders.TimelineEntry!> getTimelineEntries();
+  }
+
+  public static final class TimelineBuilders.Timeline.Builder {
+    ctor public TimelineBuilders.Timeline.Builder();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.TimelineBuilders.Timeline.Builder addTimelineEntry(androidx.wear.protolayout.TimelineBuilders.TimelineEntry);
+    method public androidx.wear.protolayout.TimelineBuilders.Timeline build();
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class TimelineBuilders.TimelineEntry {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static androidx.wear.protolayout.TimelineBuilders.TimelineEntry fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.LayoutElementBuilders.Layout? getLayout();
+    method public androidx.wear.protolayout.TimelineBuilders.TimeInterval? getValidity();
+  }
+
+  public static final class TimelineBuilders.TimelineEntry.Builder {
+    ctor public TimelineBuilders.TimelineEntry.Builder();
+    method public androidx.wear.protolayout.TimelineBuilders.TimelineEntry build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.TimelineBuilders.TimelineEntry.Builder setLayout(androidx.wear.protolayout.LayoutElementBuilders.Layout);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.TimelineBuilders.TimelineEntry.Builder setValidity(androidx.wear.protolayout.TimelineBuilders.TimeInterval);
+  }
+
+  public final class TriggerBuilders {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.TriggerBuilders.Trigger createOnConditionMetTrigger(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.TriggerBuilders.Trigger createOnLoadTrigger();
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static interface TriggerBuilders.Trigger {
+  }
+
+  public final class TypeBuilders {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class TypeBuilders.BoolProp {
+    method public androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool? getDynamicValue();
+    method public boolean getValue();
+  }
+
+  public static final class TypeBuilders.BoolProp.Builder {
+    ctor @Deprecated public TypeBuilders.BoolProp.Builder();
+    ctor public TypeBuilders.BoolProp.Builder(boolean);
+    method public androidx.wear.protolayout.TypeBuilders.BoolProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.TypeBuilders.BoolProp.Builder setDynamicValue(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.TypeBuilders.BoolProp.Builder setValue(boolean);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class TypeBuilders.FloatProp {
+    method public androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat? getDynamicValue();
+    method public float getValue();
+  }
+
+  public static final class TypeBuilders.FloatProp.Builder {
+    ctor @Deprecated public TypeBuilders.FloatProp.Builder();
+    ctor public TypeBuilders.FloatProp.Builder(float);
+    method public androidx.wear.protolayout.TypeBuilders.FloatProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.TypeBuilders.FloatProp.Builder setDynamicValue(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.TypeBuilders.FloatProp.Builder setValue(float);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class TypeBuilders.Int32Prop {
+    method public int getValue();
+  }
+
+  public static final class TypeBuilders.Int32Prop.Builder {
+    ctor public TypeBuilders.Int32Prop.Builder();
+    method public androidx.wear.protolayout.TypeBuilders.Int32Prop build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.TypeBuilders.Int32Prop.Builder setValue(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class TypeBuilders.StringLayoutConstraint {
+    method public int getAlignment();
+    method public String getPatternForLayout();
+  }
+
+  public static final class TypeBuilders.StringLayoutConstraint.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public TypeBuilders.StringLayoutConstraint.Builder(String);
+    method public androidx.wear.protolayout.TypeBuilders.StringLayoutConstraint build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.TypeBuilders.StringLayoutConstraint.Builder setAlignment(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class TypeBuilders.StringProp {
+    method public androidx.wear.protolayout.expression.DynamicBuilders.DynamicString? getDynamicValue();
+    method public String getValue();
+  }
+
+  public static final class TypeBuilders.StringProp.Builder {
+    ctor @Deprecated public TypeBuilders.StringProp.Builder();
+    ctor public TypeBuilders.StringProp.Builder(String);
+    method public androidx.wear.protolayout.TypeBuilders.StringProp build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.TypeBuilders.StringProp.Builder setDynamicValue(androidx.wear.protolayout.expression.DynamicBuilders.DynamicString);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.TypeBuilders.StringProp.Builder setValue(String);
+  }
+
+}
+
diff --git a/wear/protolayout/protolayout/api/restricted_current.ignore b/wear/protolayout/protolayout/api/restricted_current.ignore
new file mode 100644
index 0000000..a151ec4
--- /dev/null
+++ b/wear/protolayout/protolayout/api/restricted_current.ignore
@@ -0,0 +1,3 @@
+// Baseline format: 1.0
+InvalidNullConversion: androidx.wear.protolayout.StateBuilders.State#getKeyToValueMapping():
+    Attempted to remove nullability from java.lang.Object (was NONNULL) in method androidx.wear.protolayout.StateBuilders.State.getKeyToValueMapping()
diff --git a/wear/protolayout/protolayout/api/restricted_current.txt b/wear/protolayout/protolayout/api/restricted_current.txt
index 6298259..721be43 100644
--- a/wear/protolayout/protolayout/api/restricted_current.txt
+++ b/wear/protolayout/protolayout/api/restricted_current.txt
@@ -154,13 +154,13 @@
   }
 
   @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static final class DeviceParametersBuilders.Capabilities {
-    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental public long getMinimumFreshnessLimitMillis();
+    method public long getMinimumFreshnessLimitMillis();
   }
 
   public static final class DeviceParametersBuilders.Capabilities.Builder {
     ctor public DeviceParametersBuilders.Capabilities.Builder();
     method public androidx.wear.protolayout.DeviceParametersBuilders.Capabilities build();
-    method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DeviceParametersBuilders.Capabilities.Builder setMinimumFreshnessLimitMillis(long);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DeviceParametersBuilders.Capabilities.Builder setMinimumFreshnessLimitMillis(long);
   }
 
   @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class DeviceParametersBuilders.DeviceParameters {
@@ -180,7 +180,7 @@
     method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setCapabilities(androidx.wear.protolayout.DeviceParametersBuilders.Capabilities);
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setDevicePlatform(int);
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setFontScale(@FloatRange(from=0.0, fromInclusive=false, toInclusive=false) float);
-    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setRendererSchemaVersion(androidx.wear.protolayout.expression.VersionBuilders.VersionInfo);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setRendererSchemaVersion(androidx.wear.protolayout.expression.VersionBuilders.VersionInfo);
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setScreenDensity(@FloatRange(from=0.0, fromInclusive=false, toInclusive=false) float);
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setScreenHeightDp(@Dimension(unit=androidx.annotation.Dimension.DP) int);
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters.Builder setScreenShape(int);
@@ -566,7 +566,7 @@
   }
 
   public static final class LayoutElementBuilders.ExtensionLayoutElement.Builder {
-    ctor public LayoutElementBuilders.ExtensionLayoutElement.Builder();
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public LayoutElementBuilders.ExtensionLayoutElement.Builder();
     method public androidx.wear.protolayout.LayoutElementBuilders.ExtensionLayoutElement build();
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.ExtensionLayoutElement.Builder setExtensionId(String);
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.ExtensionLayoutElement.Builder setHeight(androidx.wear.protolayout.DimensionBuilders.ExtensionDimension);
@@ -577,7 +577,7 @@
   @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static interface LayoutElementBuilders.FontSetting {
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static androidx.wear.protolayout.LayoutElementBuilders.FontSetting tabularNum();
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static androidx.wear.protolayout.LayoutElementBuilders.FontSetting weight(@IntRange(from=1, to=1000) int);
-    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static androidx.wear.protolayout.LayoutElementBuilders.FontSetting width(@FloatRange(from=0) float);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static androidx.wear.protolayout.LayoutElementBuilders.FontSetting width(@FloatRange(from=25, to=200) float);
   }
 
   @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class LayoutElementBuilders.FontStyle {
@@ -591,7 +591,6 @@
     method public androidx.wear.protolayout.TypeBuilders.BoolProp? getUnderline();
     method @SuppressCompatibility @androidx.wear.protolayout.expression.ProtoLayoutExperimental public androidx.wear.protolayout.LayoutElementBuilders.FontVariantProp? getVariant();
     method public androidx.wear.protolayout.LayoutElementBuilders.FontWeightProp? getWeight();
-    field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static final String DEFAULT_SYSTEM_FONT = "default";
     field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static final String ROBOTO_FLEX_FONT = "roboto-flex";
     field @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static final String ROBOTO_FONT = "roboto";
   }
@@ -813,7 +812,7 @@
   }
 
   public static final class LayoutElementBuilders.StrokeCapProp.Builder {
-    ctor public LayoutElementBuilders.StrokeCapProp.Builder();
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public LayoutElementBuilders.StrokeCapProp.Builder();
     method public androidx.wear.protolayout.LayoutElementBuilders.StrokeCapProp build();
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=300) public androidx.wear.protolayout.LayoutElementBuilders.StrokeCapProp.Builder setShadow(androidx.wear.protolayout.ModifiersBuilders.Shadow);
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.LayoutElementBuilders.StrokeCapProp.Builder setValue(int);
@@ -1357,7 +1356,7 @@
 
   public final class TriggerBuilders {
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.TriggerBuilders.Trigger createOnConditionMetTrigger(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
-    method public static androidx.wear.protolayout.TriggerBuilders.Trigger createOnLoadTrigger();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.TriggerBuilders.Trigger createOnLoadTrigger();
   }
 
   @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static interface TriggerBuilders.Trigger {
diff --git a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/ActionBuilders.java b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/ActionBuilders.java
index a33e2eb..84c192e 100644
--- a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/ActionBuilders.java
+++ b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/ActionBuilders.java
@@ -220,7 +220,6 @@
         }
 
         /** Returns the internal proto instance. */
-        @RestrictTo(Scope.LIBRARY_GROUP)
         @NonNull
         ActionProto.AndroidIntExtra toProto() {
             return mImpl;
@@ -304,7 +303,6 @@
         }
 
         /** Returns the internal proto instance. */
-        @RestrictTo(Scope.LIBRARY_GROUP)
         @NonNull
         ActionProto.AndroidLongExtra toProto() {
             return mImpl;
@@ -388,7 +386,6 @@
         }
 
         /** Returns the internal proto instance. */
-        @RestrictTo(Scope.LIBRARY_GROUP)
         @NonNull
         ActionProto.AndroidDoubleExtra toProto() {
             return mImpl;
@@ -841,7 +838,6 @@
         }
 
         /** Returns the internal proto instance. */
-        @RestrictTo(Scope.LIBRARY_GROUP)
         @NonNull
         ActionProto.LoadAction toProto() {
             return mImpl;
diff --git a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/DeviceParametersBuilders.java b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/DeviceParametersBuilders.java
index 64dcf08..c844392 100644
--- a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/DeviceParametersBuilders.java
+++ b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/DeviceParametersBuilders.java
@@ -262,7 +262,7 @@
              * layout that uses features not available on schema version 1.0 , this can be used to
              * conditionally choose which feature to use.
              */
-            @RequiresSchemaVersion(major = 1, minor = 200)
+            @RequiresSchemaVersion(major = 1, minor = 0)
             @NonNull
             public Builder setRendererSchemaVersion(@NonNull VersionInfo rendererSchemaVersion) {
                 mImpl.setRendererSchemaVersion(rendererSchemaVersion.toProto());
@@ -306,7 +306,6 @@
          * on various factors. Any freshness request lower than the current limit will be replaced
          * by that limit. A value of 0 here signifies that the minimum freshness limit in unknown.
          */
-        @ProtoLayoutExperimental
         public long getMinimumFreshnessLimitMillis() {
             return mImpl.getMinimumFreshnessLimitMillis();
         }
@@ -350,7 +349,6 @@
              */
             @RequiresSchemaVersion(major = 1, minor = 200)
             @NonNull
-            @ProtoLayoutExperimental
             public Builder setMinimumFreshnessLimitMillis(long minimumFreshnessLimitMillis) {
                 mImpl.setMinimumFreshnessLimitMillis(minimumFreshnessLimitMillis);
                 return this;
diff --git a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/LayoutElementBuilders.java b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/LayoutElementBuilders.java
index c63519e..f76e662 100644
--- a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/LayoutElementBuilders.java
+++ b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/LayoutElementBuilders.java
@@ -592,7 +592,7 @@
          * to "false".
          */
         @Nullable
-        public BoolProp getItalic() {
+        private BoolProp isItalic() {
             if (mImpl.hasItalic()) {
                 return BoolProp.fromProto(mImpl.getItalic());
             } else {
@@ -605,7 +605,7 @@
          * "false".
          */
         @Nullable
-        public BoolProp getUnderline() {
+        private BoolProp isUnderline() {
             if (mImpl.hasUnderline()) {
                 return BoolProp.fromProto(mImpl.getUnderline());
             } else {
@@ -715,21 +715,34 @@
             return Collections.unmodifiableList(list);
         }
 
+
+        /**
+         * Gets whether the text should be rendered in a italic typeface. If not specified, defaults to
+         * "false".
+         */
+        @Nullable
+        public BoolProp getItalic() {
+            return isItalic();
+        }
+
+        /**
+         * Gets whether the text should be rendered with an underline. If not specified, defaults to
+         * "false".
+         */
+        @Nullable
+        public BoolProp getUnderline() {
+            return isUnderline();
+        }
+
         /** The recommended font family names to be used within {@link FontStyle}. */
         @RequiresSchemaVersion(major = 1, minor = 400)
         @RestrictTo(RestrictTo.Scope.LIBRARY)
         @Retention(RetentionPolicy.SOURCE)
         @StringDef(
-                value = {DEFAULT_SYSTEM_FONT, ROBOTO_FONT, ROBOTO_FLEX_FONT},
+                value = {ROBOTO_FONT, ROBOTO_FLEX_FONT},
                 open = true)
         public @interface FontFamilyName {}
 
-        /**
-         * Font family name that uses default system font. Supported in any renderer version.
-         */
-        @RequiresSchemaVersion(major = 1, minor = 400)
-        public static final String DEFAULT_SYSTEM_FONT = "default";
-
         /** Font family name that uses Roboto font. Supported in renderers supporting 1.4. */
         @RequiresSchemaVersion(major = 1, minor = 400)
         public static final String ROBOTO_FONT = "roboto";
@@ -1014,7 +1027,7 @@
                     @NonNull @IntRange(from = 1) @Dimension(unit = Dimension.SP) int... sizes) {
                 if (sizes.length > TEXT_SIZES_LIMIT) {
                     throw new IllegalArgumentException(
-                            "Number of available sizes can't be larger than 10.");
+                            "Number of available sizes of the font style can't be larger than 10.");
                 }
 
                 mImpl.clearSize();
@@ -1059,9 +1072,8 @@
              * <p>If the given font family is not available on a device, the fallback values will be
              * attempted to use, in order in which they are given.
              *
-             * <p>Renderer support for values outside of the given constants ( {@link
-             * #DEFAULT_SYSTEM_FONT}, {@link #ROBOTO_FONT} or {@link #ROBOTO_FLEX_FONT}) is not
-             * guaranteed for all devices.
+             * <p>Renderer support for values outside of the given constants ({@link #ROBOTO_FONT}
+             * or {@link #ROBOTO_FLEX_FONT}) is not guaranteed for all devices.
              *
              * <p>If not set, default system font will be used.
              *
@@ -1177,7 +1189,7 @@
          */
         @NonNull
         @RequiresSchemaVersion(major = 1, minor = 400)
-        static FontSetting width(@FloatRange(from = 0) float value) {
+        static FontSetting width(@FloatRange(from = 25, to = 200) float value) {
             return new FontVariationSetting.Builder(WIDTH_AXIS_TAG, value).build();
         }
 
@@ -1622,6 +1634,7 @@
             private final Fingerprint mFingerprint = new Fingerprint(1405971293);
 
             /** Creates an instance of {@link Builder}. */
+            @RequiresSchemaVersion(major = 1, minor = 200)
             public Builder() {}
 
             /**
@@ -1661,6 +1674,11 @@
          *
          * <p>While this field is statically accessible from 1.0, it's only bindable since version
          * 1.2 and renderers supporting version 1.2 will use the dynamic value (if set).
+         *
+         * <p>When using a dynamic value, make sure to specify the bounding constraints for the
+         * affected layout element through
+         * {@code setLayoutConstraintsForDynamicText(StringLayoutConstraint)} otherwise
+         * {@code build()} fails.
          */
         @Nullable
         public StringProp getText() {
@@ -2488,6 +2506,11 @@
          *
          * <p>While this field is statically accessible from 1.0, it's only bindable since version
          * 1.2 and renderers supporting version 1.2 will use the dynamic value (if set).
+         *
+         * <p>When using a dynamic value, make sure to specify the bounding constraints for the
+         * affected layout element through {@code
+         * setLayoutConstraintsForDynamicWidth(HorizontalLayoutConstraint)} otherwise {@code
+         * build()} fails.
          */
         @Nullable
         public SpacerDimension getWidth() {
@@ -2503,6 +2526,11 @@
          *
          * <p>While this field is statically accessible from 1.0, it's only bindable since version
          * 1.2 and renderers supporting version 1.2 will use the dynamic value (if set).
+         *
+         * <p>When using a dynamic value, make sure to specify the bounding constraints for the
+         * affected layout element through {@code
+         * setLayoutConstraintsForDynamicWidth(HorizontalLayoutConstraint)} otherwise {@code
+         * build()} fails.
          */
         @Nullable
         public SpacerDimension getHeight() {
@@ -3102,7 +3130,7 @@
             @NonNull
             public Builder setText(@NonNull StringProp text) {
                 if (text.getDynamicValue() != null) {
-                    throw new IllegalArgumentException("setText doesn't support dynamic values.");
+                    throw new IllegalArgumentException("SpanText.Builder.setText doesn't support dynamic values.");
                 }
                 mImpl.setText(text.toProto());
                 mFingerprint.recordPropertyUpdate(
@@ -4203,6 +4231,10 @@
      * An arc container. This container will fill itself to a circle, which fits inside its parent
      * container, and all of its children will be placed on that circle. The fields anchor_angle and
      * anchor_type can be used to specify where to draw children within this circle.
+     *
+     * <p>Note that when setting padding for the arc, if padding values (top, button, left, and
+     * right) are not equal, the largest between them will be used to apply padding uniformly to all
+     * sides.
      */
     @RequiresSchemaVersion(major = 1, minor = 0)
     public static final class Arc implements LayoutElement {
@@ -4693,6 +4725,11 @@
          *
          * <p>While this field is statically accessible from 1.0, it's only bindable since version
          * 1.2 and renderers supporting version 1.2 will use the dynamic value (if set).
+         *
+         * <p>When using a dynamic value, make sure to specify the bounding constraints for the
+         * affected layout element through
+         * {@code setLayoutConstraintsForDynamicLength(AngularLayoutConstraint)} otherwise {@code
+         * build()} fails.
          */
         @Nullable
         public DegreesProp getLength() {
@@ -5094,6 +5131,7 @@
             private final Fingerprint mFingerprint = new Fingerprint(-956183418);
 
             /** Creates an instance of {@link Builder}. */
+            @RequiresSchemaVersion(major = 1, minor = 200)
             public Builder() {}
 
             /** Sets the value. */
@@ -5314,7 +5352,7 @@
          * will not be rotated. If not defined, defaults to false.
          */
         @Nullable
-        public BoolProp getRotateContents() {
+        private BoolProp isRotateContents() {
             if (mImpl.hasRotateContents()) {
                 return BoolProp.fromProto(mImpl.getRotateContents());
             } else {
@@ -5322,6 +5360,20 @@
             }
         }
 
+
+        /**
+         * Gets whether this adapter's contents should be rotated, according to its position in the arc
+         * or not. As an example, assume that an {@link Image} has been added to the arc, and ends up at
+         * the 3 o clock position. If rotate_contents = true, the image will be placed at the 3 o clock
+         * position, and will be rotated clockwise through 90 degrees. If rotate_contents = false, the
+         * image will be placed at the 3 o clock position, but itself will not be rotated. If not
+         * defined, defaults to false.
+         */
+        @Nullable
+        public BoolProp getRotateContents() {
+            return isRotateContents();
+        }
+
         @Override
         @RestrictTo(Scope.LIBRARY_GROUP)
         @Nullable
@@ -5514,7 +5566,7 @@
             @RequiresSchemaVersion(major = 1, minor = 300)
             Builder() {}
 
-            /** Sets the value. */
+            /** Sets the arc direction value. */
             @RequiresSchemaVersion(major = 1, minor = 300)
             @NonNull
             Builder setValue(@ArcDirection int value) {
@@ -5650,6 +5702,7 @@
             private final Fingerprint mFingerprint = new Fingerprint(661980356);
 
             /** Creates an instance of {@link Builder}. */
+            @RequiresSchemaVersion(major = 1, minor = 200)
             public Builder() {}
 
             /**
diff --git a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/ModifiersBuilders.java b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/ModifiersBuilders.java
index 4f9bf6d..e667ac5 100644
--- a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/ModifiersBuilders.java
+++ b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/ModifiersBuilders.java
@@ -757,7 +757,7 @@
          * map to left/right, accordingly.
          */
         @Nullable
-        public BoolProp getRtlAware() {
+        BoolProp isRtlAware() {
             if (mImpl.hasRtlAware()) {
                 return BoolProp.fromProto(mImpl.getRtlAware());
             } else {
@@ -765,6 +765,17 @@
             }
         }
 
+        /**
+         * Gets whether the start/end padding is aware of RTL support. If true, the values for
+         * start/end will follow the layout direction (i.e. start will refer to the right hand side
+         * of the container if the device is using an RTL locale). If false, start/end will always
+         * map to left/right, accordingly.
+         */
+        @Nullable
+        public BoolProp getRtlAware() {
+            return isRtlAware();
+        }
+
         /** Get the fingerprint for this object, or null if unknown. */
         @RestrictTo(Scope.LIBRARY_GROUP)
         @Nullable
diff --git a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/TriggerBuilders.java b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/TriggerBuilders.java
index ab09eba..a35d6f8 100644
--- a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/TriggerBuilders.java
+++ b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/TriggerBuilders.java
@@ -33,6 +33,7 @@
     private TriggerBuilders() {}
 
     /** Creates a {@link Trigger} that fires immediately when the layout is loaded / reloaded. */
+    @RequiresSchemaVersion(major = 1, minor = 200)
     @NonNull
     public static Trigger createOnLoadTrigger() {
         return new OnLoadTrigger.Builder().build();
@@ -106,6 +107,7 @@
             private final Fingerprint mFingerprint = new Fingerprint(-1262805599);
 
             /** Creates an instance of {@link Builder}. */
+            @RequiresSchemaVersion(major = 1, minor = 200)
             public Builder() {}
 
             /** Builds an instance from accumulated values. */
@@ -190,6 +192,7 @@
             private final Fingerprint mFingerprint = new Fingerprint(756642641);
 
             /** Creates an instance of {@link Builder}. */
+            @RequiresSchemaVersion(major = 1, minor = 200)
             public Builder() {}
 
             /** Sets dynamic boolean used as trigger. */
diff --git a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/TypeBuilders.java b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/TypeBuilders.java
index 96f7117..8b32550 100644
--- a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/TypeBuilders.java
+++ b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/TypeBuilders.java
@@ -499,11 +499,20 @@
          * values for the corresponding field, this static value will be ignored. If the static
          * value is not specified, false will be used instead.
          */
-        public boolean getValue() {
+        boolean isValue() {
             return mImpl.getValue();
         }
 
         /**
+         * Gets the static value. If a dynamic value is also set and the renderer supports dynamic
+         * values for the corresponding field, this static value will be ignored. If the static
+         * value is not specified, false will be used instead.
+         */
+        public boolean getValue() {
+            return isValue();
+        }
+
+        /**
          * Gets the dynamic value. Note that when setting this value, the static value is still
          * required to be set to support older renderers that only read the static value. If {@code
          * dynamicValue} has an invalid result, the provided static value will be used instead.
diff --git a/wear/tiles/tiles-material/api/1.4.0-beta01.txt b/wear/tiles/tiles-material/api/1.4.0-beta01.txt
new file mode 100644
index 0000000..85c110b
--- /dev/null
+++ b/wear/tiles/tiles-material/api/1.4.0-beta01.txt
@@ -0,0 +1,298 @@
+// Signature format: 4.0
+package androidx.wear.tiles.material {
+
+  @Deprecated public class Button implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public static androidx.wear.tiles.material.Button? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.ButtonColors getButtonColors();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Clickable getClickable();
+    method @Deprecated public CharSequence? getContentDescription();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getCustomContent();
+    method @Deprecated public String? getIconContent();
+    method @Deprecated public String? getImageContent();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ContainerDimension getSize();
+    method @Deprecated public String? getTextContent();
+  }
+
+  @Deprecated public static final class Button.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public Button.Builder(android.content.Context, androidx.wear.tiles.ModifiersBuilders.Clickable);
+    method @Deprecated public androidx.wear.tiles.material.Button build();
+    method @Deprecated public androidx.wear.tiles.material.Button.Builder setButtonColors(androidx.wear.tiles.material.ButtonColors);
+    method @Deprecated public androidx.wear.tiles.material.Button.Builder setContentDescription(CharSequence);
+    method @Deprecated public androidx.wear.tiles.material.Button.Builder setCustomContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.Button.Builder setIconContent(String);
+    method @Deprecated public androidx.wear.tiles.material.Button.Builder setIconContent(String, androidx.wear.tiles.DimensionBuilders.DpProp);
+    method @Deprecated public androidx.wear.tiles.material.Button.Builder setImageContent(String);
+    method @Deprecated public androidx.wear.tiles.material.Button.Builder setSize(androidx.wear.tiles.DimensionBuilders.DpProp);
+    method @Deprecated public androidx.wear.tiles.material.Button.Builder setSize(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method @Deprecated public androidx.wear.tiles.material.Button.Builder setTextContent(String);
+    method @Deprecated public androidx.wear.tiles.material.Button.Builder setTextContent(String, int);
+  }
+
+  @Deprecated public class ButtonColors {
+    ctor @Deprecated public ButtonColors(androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp);
+    ctor @Deprecated public ButtonColors(@ColorInt int, @ColorInt int);
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp getBackgroundColor();
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp getContentColor();
+    method @Deprecated public static androidx.wear.tiles.material.ButtonColors primaryButtonColors(androidx.wear.tiles.material.Colors);
+    method @Deprecated public static androidx.wear.tiles.material.ButtonColors secondaryButtonColors(androidx.wear.tiles.material.Colors);
+  }
+
+  @Deprecated public class ButtonDefaults {
+    method @Deprecated public static androidx.wear.tiles.DimensionBuilders.DpProp recommendedIconSize(androidx.wear.tiles.DimensionBuilders.DpProp);
+    method @Deprecated public static androidx.wear.tiles.DimensionBuilders.DpProp recommendedIconSize(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    field @Deprecated public static final androidx.wear.tiles.DimensionBuilders.DpProp DEFAULT_SIZE;
+    field @Deprecated public static final androidx.wear.tiles.DimensionBuilders.DpProp EXTRA_LARGE_SIZE;
+    field @Deprecated public static final androidx.wear.tiles.DimensionBuilders.DpProp LARGE_SIZE;
+    field @Deprecated public static final androidx.wear.tiles.material.ButtonColors PRIMARY_COLORS;
+    field @Deprecated public static final androidx.wear.tiles.material.ButtonColors SECONDARY_COLORS;
+  }
+
+  @Deprecated public class Chip implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public static androidx.wear.tiles.material.Chip? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.ChipColors getChipColors();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Clickable getClickable();
+    method @Deprecated public CharSequence? getContentDescription();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getCustomContent();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ContainerDimension getHeight();
+    method @Deprecated public int getHorizontalAlignment();
+    method @Deprecated public String? getIconContent();
+    method @Deprecated public String? getPrimaryLabelContent();
+    method @Deprecated public String? getSecondaryLabelContent();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ContainerDimension getWidth();
+  }
+
+  @Deprecated public static final class Chip.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public Chip.Builder(android.content.Context, androidx.wear.tiles.ModifiersBuilders.Clickable, androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public androidx.wear.tiles.material.Chip build();
+    method @Deprecated public androidx.wear.tiles.material.Chip.Builder setChipColors(androidx.wear.tiles.material.ChipColors);
+    method @Deprecated public androidx.wear.tiles.material.Chip.Builder setContentDescription(CharSequence);
+    method @Deprecated public androidx.wear.tiles.material.Chip.Builder setCustomContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.Chip.Builder setHorizontalAlignment(int);
+    method @Deprecated public androidx.wear.tiles.material.Chip.Builder setIconContent(String);
+    method @Deprecated public androidx.wear.tiles.material.Chip.Builder setPrimaryLabelContent(String);
+    method @Deprecated public androidx.wear.tiles.material.Chip.Builder setSecondaryLabelContent(String);
+    method @Deprecated public androidx.wear.tiles.material.Chip.Builder setWidth(androidx.wear.tiles.DimensionBuilders.ContainerDimension);
+    method @Deprecated public androidx.wear.tiles.material.Chip.Builder setWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  @Deprecated public class ChipColors {
+    ctor @Deprecated public ChipColors(androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp);
+    ctor @Deprecated public ChipColors(androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp);
+    ctor @Deprecated public ChipColors(@ColorInt int, @ColorInt int);
+    ctor @Deprecated public ChipColors(@ColorInt int, @ColorInt int, @ColorInt int, @ColorInt int);
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp getBackgroundColor();
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp getContentColor();
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp getIconColor();
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp getSecondaryContentColor();
+    method @Deprecated public static androidx.wear.tiles.material.ChipColors primaryChipColors(androidx.wear.tiles.material.Colors);
+    method @Deprecated public static androidx.wear.tiles.material.ChipColors secondaryChipColors(androidx.wear.tiles.material.Colors);
+  }
+
+  @Deprecated public class ChipDefaults {
+    field @Deprecated public static final androidx.wear.tiles.material.ChipColors COMPACT_PRIMARY_COLORS;
+    field @Deprecated public static final androidx.wear.tiles.material.ChipColors COMPACT_SECONDARY_COLORS;
+    field @Deprecated public static final androidx.wear.tiles.material.ChipColors PRIMARY_COLORS;
+    field @Deprecated public static final androidx.wear.tiles.material.ChipColors SECONDARY_COLORS;
+    field @Deprecated public static final androidx.wear.tiles.material.ChipColors TITLE_PRIMARY_COLORS;
+    field @Deprecated public static final androidx.wear.tiles.material.ChipColors TITLE_SECONDARY_COLORS;
+  }
+
+  @Deprecated public class CircularProgressIndicator implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public static androidx.wear.tiles.material.CircularProgressIndicator? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.ProgressIndicatorColors getCircularProgressIndicatorColors();
+    method @Deprecated public CharSequence? getContentDescription();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DegreesProp getEndAngle();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DegreesProp getProgress();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DegreesProp getStartAngle();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DpProp getStrokeWidth();
+  }
+
+  @Deprecated public static final class CircularProgressIndicator.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public CircularProgressIndicator.Builder();
+    method @Deprecated public androidx.wear.tiles.material.CircularProgressIndicator build();
+    method @Deprecated public androidx.wear.tiles.material.CircularProgressIndicator.Builder setCircularProgressIndicatorColors(androidx.wear.tiles.material.ProgressIndicatorColors);
+    method @Deprecated public androidx.wear.tiles.material.CircularProgressIndicator.Builder setContentDescription(CharSequence);
+    method @Deprecated public androidx.wear.tiles.material.CircularProgressIndicator.Builder setEndAngle(float);
+    method @Deprecated public androidx.wear.tiles.material.CircularProgressIndicator.Builder setProgress(@FloatRange(from=0, to=1) float);
+    method @Deprecated public androidx.wear.tiles.material.CircularProgressIndicator.Builder setStartAngle(float);
+    method @Deprecated public androidx.wear.tiles.material.CircularProgressIndicator.Builder setStrokeWidth(androidx.wear.tiles.DimensionBuilders.DpProp);
+    method @Deprecated public androidx.wear.tiles.material.CircularProgressIndicator.Builder setStrokeWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  @Deprecated public class Colors {
+    ctor @Deprecated public Colors(@ColorInt int, @ColorInt int, @ColorInt int, @ColorInt int);
+    method @Deprecated @ColorInt public int getOnPrimary();
+    method @Deprecated @ColorInt public int getOnSurface();
+    method @Deprecated @ColorInt public int getPrimary();
+    method @Deprecated @ColorInt public int getSurface();
+    field @Deprecated public static final androidx.wear.tiles.material.Colors DEFAULT;
+  }
+
+  @Deprecated public class CompactChip implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public static androidx.wear.tiles.material.CompactChip? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.ChipColors getChipColors();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Clickable getClickable();
+    method @Deprecated public String getText();
+  }
+
+  @Deprecated public static final class CompactChip.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public CompactChip.Builder(android.content.Context, String, androidx.wear.tiles.ModifiersBuilders.Clickable, androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public androidx.wear.tiles.material.CompactChip build();
+    method @Deprecated public androidx.wear.tiles.material.CompactChip.Builder setChipColors(androidx.wear.tiles.material.ChipColors);
+  }
+
+  @Deprecated public class ProgressIndicatorColors {
+    ctor @Deprecated public ProgressIndicatorColors(androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp);
+    ctor @Deprecated public ProgressIndicatorColors(@ColorInt int, @ColorInt int);
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp getIndicatorColor();
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp getTrackColor();
+    method @Deprecated public static androidx.wear.tiles.material.ProgressIndicatorColors progressIndicatorColors(androidx.wear.tiles.material.Colors);
+  }
+
+  @Deprecated public class ProgressIndicatorDefaults {
+    field @Deprecated public static final androidx.wear.tiles.material.ProgressIndicatorColors DEFAULT_COLORS;
+    field @Deprecated public static final androidx.wear.tiles.DimensionBuilders.DpProp DEFAULT_STROKE_WIDTH;
+    field @Deprecated public static final float GAP_END_ANGLE = 156.1f;
+    field @Deprecated public static final float GAP_START_ANGLE = -156.1f;
+  }
+
+  @Deprecated public class Text implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public static androidx.wear.tiles.material.Text? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp getColor();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontStyle getFontStyle();
+    method @Deprecated public float getLineHeight();
+    method @Deprecated public int getMaxLines();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers getModifiers();
+    method @Deprecated public int getMultilineAlignment();
+    method @Deprecated public int getOverflow();
+    method @Deprecated public String getText();
+    method @Deprecated public int getWeight();
+    method @Deprecated public boolean isItalic();
+    method @Deprecated public boolean isUnderline();
+  }
+
+  @Deprecated public static final class Text.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public Text.Builder(android.content.Context, String);
+    method @Deprecated public androidx.wear.tiles.material.Text build();
+    method @Deprecated public androidx.wear.tiles.material.Text.Builder setColor(androidx.wear.tiles.ColorBuilders.ColorProp);
+    method @Deprecated public androidx.wear.tiles.material.Text.Builder setItalic(boolean);
+    method @Deprecated public androidx.wear.tiles.material.Text.Builder setMaxLines(@IntRange(from=1) int);
+    method @Deprecated public androidx.wear.tiles.material.Text.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.Modifiers);
+    method @Deprecated public androidx.wear.tiles.material.Text.Builder setMultilineAlignment(int);
+    method @Deprecated public androidx.wear.tiles.material.Text.Builder setOverflow(int);
+    method @Deprecated public androidx.wear.tiles.material.Text.Builder setTypography(int);
+    method @Deprecated public androidx.wear.tiles.material.Text.Builder setUnderline(boolean);
+    method @Deprecated public androidx.wear.tiles.material.Text.Builder setWeight(int);
+  }
+
+  @Deprecated public class TitleChip implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public static androidx.wear.tiles.material.TitleChip? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.ChipColors getChipColors();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Clickable getClickable();
+    method @Deprecated public int getHorizontalAlignment();
+    method @Deprecated public String getText();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ContainerDimension getWidth();
+  }
+
+  @Deprecated public static final class TitleChip.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public TitleChip.Builder(android.content.Context, String, androidx.wear.tiles.ModifiersBuilders.Clickable, androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public androidx.wear.tiles.material.TitleChip build();
+    method @Deprecated public androidx.wear.tiles.material.TitleChip.Builder setChipColors(androidx.wear.tiles.material.ChipColors);
+    method @Deprecated public androidx.wear.tiles.material.TitleChip.Builder setHorizontalAlignment(int);
+    method @Deprecated public androidx.wear.tiles.material.TitleChip.Builder setWidth(androidx.wear.tiles.DimensionBuilders.ContainerDimension);
+    method @Deprecated public androidx.wear.tiles.material.TitleChip.Builder setWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  @Deprecated public class Typography {
+    field @Deprecated public static final int TYPOGRAPHY_BODY1 = 7; // 0x7
+    field @Deprecated public static final int TYPOGRAPHY_BODY2 = 8; // 0x8
+    field @Deprecated public static final int TYPOGRAPHY_BUTTON = 9; // 0x9
+    field @Deprecated public static final int TYPOGRAPHY_CAPTION1 = 10; // 0xa
+    field @Deprecated public static final int TYPOGRAPHY_CAPTION2 = 11; // 0xb
+    field @Deprecated public static final int TYPOGRAPHY_CAPTION3 = 12; // 0xc
+    field @Deprecated public static final int TYPOGRAPHY_DISPLAY1 = 1; // 0x1
+    field @Deprecated public static final int TYPOGRAPHY_DISPLAY2 = 2; // 0x2
+    field @Deprecated public static final int TYPOGRAPHY_DISPLAY3 = 3; // 0x3
+    field @Deprecated public static final int TYPOGRAPHY_TITLE1 = 4; // 0x4
+    field @Deprecated public static final int TYPOGRAPHY_TITLE2 = 5; // 0x5
+    field @Deprecated public static final int TYPOGRAPHY_TITLE3 = 6; // 0x6
+  }
+
+}
+
+package androidx.wear.tiles.material.layouts {
+
+  @Deprecated public class EdgeContentLayout implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public static androidx.wear.tiles.material.layouts.EdgeContentLayout? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getContent();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getEdgeContent();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getPrimaryLabelTextContent();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getSecondaryLabelTextContent();
+  }
+
+  @Deprecated public static final class EdgeContentLayout.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public EdgeContentLayout.Builder(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public androidx.wear.tiles.material.layouts.EdgeContentLayout build();
+    method @Deprecated public androidx.wear.tiles.material.layouts.EdgeContentLayout.Builder setContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.layouts.EdgeContentLayout.Builder setEdgeContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.layouts.EdgeContentLayout.Builder setPrimaryLabelTextContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.layouts.EdgeContentLayout.Builder setSecondaryLabelTextContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+  }
+
+  @Deprecated public class LayoutDefaults {
+    field @Deprecated public static final androidx.wear.tiles.DimensionBuilders.DpProp DEFAULT_VERTICAL_SPACER_HEIGHT;
+    field @Deprecated public static final float EDGE_CONTENT_LAYOUT_PADDING_ABOVE_MAIN_CONTENT_DP = 6.0f;
+    field @Deprecated public static final float EDGE_CONTENT_LAYOUT_PADDING_BELOW_MAIN_CONTENT_DP = 8.0f;
+    field @Deprecated public static final int MULTI_BUTTON_MAX_NUMBER = 7; // 0x7
+    field @Deprecated public static final androidx.wear.tiles.DimensionBuilders.DpProp MULTI_SLOT_LAYOUT_HORIZONTAL_SPACER_WIDTH;
+  }
+
+  @Deprecated public class MultiButtonLayout implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public static androidx.wear.tiles.material.layouts.MultiButtonLayout? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public java.util.List<androidx.wear.tiles.LayoutElementBuilders.LayoutElement!> getButtonContents();
+    method @Deprecated public int getFiveButtonDistribution();
+    field @Deprecated public static final int FIVE_BUTTON_DISTRIBUTION_BOTTOM_HEAVY = 2; // 0x2
+    field @Deprecated public static final int FIVE_BUTTON_DISTRIBUTION_TOP_HEAVY = 1; // 0x1
+  }
+
+  @Deprecated public static final class MultiButtonLayout.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public MultiButtonLayout.Builder();
+    method @Deprecated public androidx.wear.tiles.material.layouts.MultiButtonLayout.Builder addButtonContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.layouts.MultiButtonLayout build();
+    method @Deprecated public androidx.wear.tiles.material.layouts.MultiButtonLayout.Builder setFiveButtonDistribution(int);
+  }
+
+  @Deprecated public class MultiSlotLayout implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public static androidx.wear.tiles.material.layouts.MultiSlotLayout? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated @Dimension(unit=androidx.annotation.Dimension.DP) public float getHorizontalSpacerWidth();
+    method @Deprecated public java.util.List<androidx.wear.tiles.LayoutElementBuilders.LayoutElement!> getSlotContents();
+  }
+
+  @Deprecated public static final class MultiSlotLayout.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public MultiSlotLayout.Builder();
+    method @Deprecated public androidx.wear.tiles.material.layouts.MultiSlotLayout.Builder addSlotContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.layouts.MultiSlotLayout build();
+    method @Deprecated public androidx.wear.tiles.material.layouts.MultiSlotLayout.Builder setHorizontalSpacerWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  @Deprecated public class PrimaryLayout implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public static androidx.wear.tiles.material.layouts.PrimaryLayout? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getContent();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getPrimaryChipContent();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getPrimaryLabelTextContent();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getSecondaryLabelTextContent();
+    method @Deprecated @Dimension(unit=androidx.annotation.Dimension.DP) public float getVerticalSpacerHeight();
+  }
+
+  @Deprecated public static final class PrimaryLayout.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public PrimaryLayout.Builder(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public androidx.wear.tiles.material.layouts.PrimaryLayout build();
+    method @Deprecated public androidx.wear.tiles.material.layouts.PrimaryLayout.Builder setContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.layouts.PrimaryLayout.Builder setPrimaryChipContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.layouts.PrimaryLayout.Builder setPrimaryLabelTextContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.layouts.PrimaryLayout.Builder setSecondaryLabelTextContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.layouts.PrimaryLayout.Builder setVerticalSpacerHeight(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+}
+
diff --git a/wear/tiles/tiles-material/api/res-1.4.0-beta01.txt b/wear/tiles/tiles-material/api/res-1.4.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wear/tiles/tiles-material/api/res-1.4.0-beta01.txt
diff --git a/wear/tiles/tiles-material/api/restricted_1.4.0-beta01.txt b/wear/tiles/tiles-material/api/restricted_1.4.0-beta01.txt
new file mode 100644
index 0000000..85c110b
--- /dev/null
+++ b/wear/tiles/tiles-material/api/restricted_1.4.0-beta01.txt
@@ -0,0 +1,298 @@
+// Signature format: 4.0
+package androidx.wear.tiles.material {
+
+  @Deprecated public class Button implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public static androidx.wear.tiles.material.Button? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.ButtonColors getButtonColors();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Clickable getClickable();
+    method @Deprecated public CharSequence? getContentDescription();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getCustomContent();
+    method @Deprecated public String? getIconContent();
+    method @Deprecated public String? getImageContent();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ContainerDimension getSize();
+    method @Deprecated public String? getTextContent();
+  }
+
+  @Deprecated public static final class Button.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public Button.Builder(android.content.Context, androidx.wear.tiles.ModifiersBuilders.Clickable);
+    method @Deprecated public androidx.wear.tiles.material.Button build();
+    method @Deprecated public androidx.wear.tiles.material.Button.Builder setButtonColors(androidx.wear.tiles.material.ButtonColors);
+    method @Deprecated public androidx.wear.tiles.material.Button.Builder setContentDescription(CharSequence);
+    method @Deprecated public androidx.wear.tiles.material.Button.Builder setCustomContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.Button.Builder setIconContent(String);
+    method @Deprecated public androidx.wear.tiles.material.Button.Builder setIconContent(String, androidx.wear.tiles.DimensionBuilders.DpProp);
+    method @Deprecated public androidx.wear.tiles.material.Button.Builder setImageContent(String);
+    method @Deprecated public androidx.wear.tiles.material.Button.Builder setSize(androidx.wear.tiles.DimensionBuilders.DpProp);
+    method @Deprecated public androidx.wear.tiles.material.Button.Builder setSize(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method @Deprecated public androidx.wear.tiles.material.Button.Builder setTextContent(String);
+    method @Deprecated public androidx.wear.tiles.material.Button.Builder setTextContent(String, int);
+  }
+
+  @Deprecated public class ButtonColors {
+    ctor @Deprecated public ButtonColors(androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp);
+    ctor @Deprecated public ButtonColors(@ColorInt int, @ColorInt int);
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp getBackgroundColor();
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp getContentColor();
+    method @Deprecated public static androidx.wear.tiles.material.ButtonColors primaryButtonColors(androidx.wear.tiles.material.Colors);
+    method @Deprecated public static androidx.wear.tiles.material.ButtonColors secondaryButtonColors(androidx.wear.tiles.material.Colors);
+  }
+
+  @Deprecated public class ButtonDefaults {
+    method @Deprecated public static androidx.wear.tiles.DimensionBuilders.DpProp recommendedIconSize(androidx.wear.tiles.DimensionBuilders.DpProp);
+    method @Deprecated public static androidx.wear.tiles.DimensionBuilders.DpProp recommendedIconSize(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    field @Deprecated public static final androidx.wear.tiles.DimensionBuilders.DpProp DEFAULT_SIZE;
+    field @Deprecated public static final androidx.wear.tiles.DimensionBuilders.DpProp EXTRA_LARGE_SIZE;
+    field @Deprecated public static final androidx.wear.tiles.DimensionBuilders.DpProp LARGE_SIZE;
+    field @Deprecated public static final androidx.wear.tiles.material.ButtonColors PRIMARY_COLORS;
+    field @Deprecated public static final androidx.wear.tiles.material.ButtonColors SECONDARY_COLORS;
+  }
+
+  @Deprecated public class Chip implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public static androidx.wear.tiles.material.Chip? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.ChipColors getChipColors();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Clickable getClickable();
+    method @Deprecated public CharSequence? getContentDescription();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getCustomContent();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ContainerDimension getHeight();
+    method @Deprecated public int getHorizontalAlignment();
+    method @Deprecated public String? getIconContent();
+    method @Deprecated public String? getPrimaryLabelContent();
+    method @Deprecated public String? getSecondaryLabelContent();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ContainerDimension getWidth();
+  }
+
+  @Deprecated public static final class Chip.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public Chip.Builder(android.content.Context, androidx.wear.tiles.ModifiersBuilders.Clickable, androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public androidx.wear.tiles.material.Chip build();
+    method @Deprecated public androidx.wear.tiles.material.Chip.Builder setChipColors(androidx.wear.tiles.material.ChipColors);
+    method @Deprecated public androidx.wear.tiles.material.Chip.Builder setContentDescription(CharSequence);
+    method @Deprecated public androidx.wear.tiles.material.Chip.Builder setCustomContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.Chip.Builder setHorizontalAlignment(int);
+    method @Deprecated public androidx.wear.tiles.material.Chip.Builder setIconContent(String);
+    method @Deprecated public androidx.wear.tiles.material.Chip.Builder setPrimaryLabelContent(String);
+    method @Deprecated public androidx.wear.tiles.material.Chip.Builder setSecondaryLabelContent(String);
+    method @Deprecated public androidx.wear.tiles.material.Chip.Builder setWidth(androidx.wear.tiles.DimensionBuilders.ContainerDimension);
+    method @Deprecated public androidx.wear.tiles.material.Chip.Builder setWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  @Deprecated public class ChipColors {
+    ctor @Deprecated public ChipColors(androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp);
+    ctor @Deprecated public ChipColors(androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp);
+    ctor @Deprecated public ChipColors(@ColorInt int, @ColorInt int);
+    ctor @Deprecated public ChipColors(@ColorInt int, @ColorInt int, @ColorInt int, @ColorInt int);
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp getBackgroundColor();
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp getContentColor();
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp getIconColor();
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp getSecondaryContentColor();
+    method @Deprecated public static androidx.wear.tiles.material.ChipColors primaryChipColors(androidx.wear.tiles.material.Colors);
+    method @Deprecated public static androidx.wear.tiles.material.ChipColors secondaryChipColors(androidx.wear.tiles.material.Colors);
+  }
+
+  @Deprecated public class ChipDefaults {
+    field @Deprecated public static final androidx.wear.tiles.material.ChipColors COMPACT_PRIMARY_COLORS;
+    field @Deprecated public static final androidx.wear.tiles.material.ChipColors COMPACT_SECONDARY_COLORS;
+    field @Deprecated public static final androidx.wear.tiles.material.ChipColors PRIMARY_COLORS;
+    field @Deprecated public static final androidx.wear.tiles.material.ChipColors SECONDARY_COLORS;
+    field @Deprecated public static final androidx.wear.tiles.material.ChipColors TITLE_PRIMARY_COLORS;
+    field @Deprecated public static final androidx.wear.tiles.material.ChipColors TITLE_SECONDARY_COLORS;
+  }
+
+  @Deprecated public class CircularProgressIndicator implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public static androidx.wear.tiles.material.CircularProgressIndicator? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.ProgressIndicatorColors getCircularProgressIndicatorColors();
+    method @Deprecated public CharSequence? getContentDescription();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DegreesProp getEndAngle();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DegreesProp getProgress();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DegreesProp getStartAngle();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DpProp getStrokeWidth();
+  }
+
+  @Deprecated public static final class CircularProgressIndicator.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public CircularProgressIndicator.Builder();
+    method @Deprecated public androidx.wear.tiles.material.CircularProgressIndicator build();
+    method @Deprecated public androidx.wear.tiles.material.CircularProgressIndicator.Builder setCircularProgressIndicatorColors(androidx.wear.tiles.material.ProgressIndicatorColors);
+    method @Deprecated public androidx.wear.tiles.material.CircularProgressIndicator.Builder setContentDescription(CharSequence);
+    method @Deprecated public androidx.wear.tiles.material.CircularProgressIndicator.Builder setEndAngle(float);
+    method @Deprecated public androidx.wear.tiles.material.CircularProgressIndicator.Builder setProgress(@FloatRange(from=0, to=1) float);
+    method @Deprecated public androidx.wear.tiles.material.CircularProgressIndicator.Builder setStartAngle(float);
+    method @Deprecated public androidx.wear.tiles.material.CircularProgressIndicator.Builder setStrokeWidth(androidx.wear.tiles.DimensionBuilders.DpProp);
+    method @Deprecated public androidx.wear.tiles.material.CircularProgressIndicator.Builder setStrokeWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  @Deprecated public class Colors {
+    ctor @Deprecated public Colors(@ColorInt int, @ColorInt int, @ColorInt int, @ColorInt int);
+    method @Deprecated @ColorInt public int getOnPrimary();
+    method @Deprecated @ColorInt public int getOnSurface();
+    method @Deprecated @ColorInt public int getPrimary();
+    method @Deprecated @ColorInt public int getSurface();
+    field @Deprecated public static final androidx.wear.tiles.material.Colors DEFAULT;
+  }
+
+  @Deprecated public class CompactChip implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public static androidx.wear.tiles.material.CompactChip? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.ChipColors getChipColors();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Clickable getClickable();
+    method @Deprecated public String getText();
+  }
+
+  @Deprecated public static final class CompactChip.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public CompactChip.Builder(android.content.Context, String, androidx.wear.tiles.ModifiersBuilders.Clickable, androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public androidx.wear.tiles.material.CompactChip build();
+    method @Deprecated public androidx.wear.tiles.material.CompactChip.Builder setChipColors(androidx.wear.tiles.material.ChipColors);
+  }
+
+  @Deprecated public class ProgressIndicatorColors {
+    ctor @Deprecated public ProgressIndicatorColors(androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp);
+    ctor @Deprecated public ProgressIndicatorColors(@ColorInt int, @ColorInt int);
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp getIndicatorColor();
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp getTrackColor();
+    method @Deprecated public static androidx.wear.tiles.material.ProgressIndicatorColors progressIndicatorColors(androidx.wear.tiles.material.Colors);
+  }
+
+  @Deprecated public class ProgressIndicatorDefaults {
+    field @Deprecated public static final androidx.wear.tiles.material.ProgressIndicatorColors DEFAULT_COLORS;
+    field @Deprecated public static final androidx.wear.tiles.DimensionBuilders.DpProp DEFAULT_STROKE_WIDTH;
+    field @Deprecated public static final float GAP_END_ANGLE = 156.1f;
+    field @Deprecated public static final float GAP_START_ANGLE = -156.1f;
+  }
+
+  @Deprecated public class Text implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public static androidx.wear.tiles.material.Text? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp getColor();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontStyle getFontStyle();
+    method @Deprecated public float getLineHeight();
+    method @Deprecated public int getMaxLines();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers getModifiers();
+    method @Deprecated public int getMultilineAlignment();
+    method @Deprecated public int getOverflow();
+    method @Deprecated public String getText();
+    method @Deprecated public int getWeight();
+    method @Deprecated public boolean isItalic();
+    method @Deprecated public boolean isUnderline();
+  }
+
+  @Deprecated public static final class Text.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public Text.Builder(android.content.Context, String);
+    method @Deprecated public androidx.wear.tiles.material.Text build();
+    method @Deprecated public androidx.wear.tiles.material.Text.Builder setColor(androidx.wear.tiles.ColorBuilders.ColorProp);
+    method @Deprecated public androidx.wear.tiles.material.Text.Builder setItalic(boolean);
+    method @Deprecated public androidx.wear.tiles.material.Text.Builder setMaxLines(@IntRange(from=1) int);
+    method @Deprecated public androidx.wear.tiles.material.Text.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.Modifiers);
+    method @Deprecated public androidx.wear.tiles.material.Text.Builder setMultilineAlignment(int);
+    method @Deprecated public androidx.wear.tiles.material.Text.Builder setOverflow(int);
+    method @Deprecated public androidx.wear.tiles.material.Text.Builder setTypography(int);
+    method @Deprecated public androidx.wear.tiles.material.Text.Builder setUnderline(boolean);
+    method @Deprecated public androidx.wear.tiles.material.Text.Builder setWeight(int);
+  }
+
+  @Deprecated public class TitleChip implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public static androidx.wear.tiles.material.TitleChip? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.ChipColors getChipColors();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Clickable getClickable();
+    method @Deprecated public int getHorizontalAlignment();
+    method @Deprecated public String getText();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ContainerDimension getWidth();
+  }
+
+  @Deprecated public static final class TitleChip.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public TitleChip.Builder(android.content.Context, String, androidx.wear.tiles.ModifiersBuilders.Clickable, androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public androidx.wear.tiles.material.TitleChip build();
+    method @Deprecated public androidx.wear.tiles.material.TitleChip.Builder setChipColors(androidx.wear.tiles.material.ChipColors);
+    method @Deprecated public androidx.wear.tiles.material.TitleChip.Builder setHorizontalAlignment(int);
+    method @Deprecated public androidx.wear.tiles.material.TitleChip.Builder setWidth(androidx.wear.tiles.DimensionBuilders.ContainerDimension);
+    method @Deprecated public androidx.wear.tiles.material.TitleChip.Builder setWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  @Deprecated public class Typography {
+    field @Deprecated public static final int TYPOGRAPHY_BODY1 = 7; // 0x7
+    field @Deprecated public static final int TYPOGRAPHY_BODY2 = 8; // 0x8
+    field @Deprecated public static final int TYPOGRAPHY_BUTTON = 9; // 0x9
+    field @Deprecated public static final int TYPOGRAPHY_CAPTION1 = 10; // 0xa
+    field @Deprecated public static final int TYPOGRAPHY_CAPTION2 = 11; // 0xb
+    field @Deprecated public static final int TYPOGRAPHY_CAPTION3 = 12; // 0xc
+    field @Deprecated public static final int TYPOGRAPHY_DISPLAY1 = 1; // 0x1
+    field @Deprecated public static final int TYPOGRAPHY_DISPLAY2 = 2; // 0x2
+    field @Deprecated public static final int TYPOGRAPHY_DISPLAY3 = 3; // 0x3
+    field @Deprecated public static final int TYPOGRAPHY_TITLE1 = 4; // 0x4
+    field @Deprecated public static final int TYPOGRAPHY_TITLE2 = 5; // 0x5
+    field @Deprecated public static final int TYPOGRAPHY_TITLE3 = 6; // 0x6
+  }
+
+}
+
+package androidx.wear.tiles.material.layouts {
+
+  @Deprecated public class EdgeContentLayout implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public static androidx.wear.tiles.material.layouts.EdgeContentLayout? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getContent();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getEdgeContent();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getPrimaryLabelTextContent();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getSecondaryLabelTextContent();
+  }
+
+  @Deprecated public static final class EdgeContentLayout.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public EdgeContentLayout.Builder(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public androidx.wear.tiles.material.layouts.EdgeContentLayout build();
+    method @Deprecated public androidx.wear.tiles.material.layouts.EdgeContentLayout.Builder setContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.layouts.EdgeContentLayout.Builder setEdgeContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.layouts.EdgeContentLayout.Builder setPrimaryLabelTextContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.layouts.EdgeContentLayout.Builder setSecondaryLabelTextContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+  }
+
+  @Deprecated public class LayoutDefaults {
+    field @Deprecated public static final androidx.wear.tiles.DimensionBuilders.DpProp DEFAULT_VERTICAL_SPACER_HEIGHT;
+    field @Deprecated public static final float EDGE_CONTENT_LAYOUT_PADDING_ABOVE_MAIN_CONTENT_DP = 6.0f;
+    field @Deprecated public static final float EDGE_CONTENT_LAYOUT_PADDING_BELOW_MAIN_CONTENT_DP = 8.0f;
+    field @Deprecated public static final int MULTI_BUTTON_MAX_NUMBER = 7; // 0x7
+    field @Deprecated public static final androidx.wear.tiles.DimensionBuilders.DpProp MULTI_SLOT_LAYOUT_HORIZONTAL_SPACER_WIDTH;
+  }
+
+  @Deprecated public class MultiButtonLayout implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public static androidx.wear.tiles.material.layouts.MultiButtonLayout? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public java.util.List<androidx.wear.tiles.LayoutElementBuilders.LayoutElement!> getButtonContents();
+    method @Deprecated public int getFiveButtonDistribution();
+    field @Deprecated public static final int FIVE_BUTTON_DISTRIBUTION_BOTTOM_HEAVY = 2; // 0x2
+    field @Deprecated public static final int FIVE_BUTTON_DISTRIBUTION_TOP_HEAVY = 1; // 0x1
+  }
+
+  @Deprecated public static final class MultiButtonLayout.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public MultiButtonLayout.Builder();
+    method @Deprecated public androidx.wear.tiles.material.layouts.MultiButtonLayout.Builder addButtonContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.layouts.MultiButtonLayout build();
+    method @Deprecated public androidx.wear.tiles.material.layouts.MultiButtonLayout.Builder setFiveButtonDistribution(int);
+  }
+
+  @Deprecated public class MultiSlotLayout implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public static androidx.wear.tiles.material.layouts.MultiSlotLayout? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated @Dimension(unit=androidx.annotation.Dimension.DP) public float getHorizontalSpacerWidth();
+    method @Deprecated public java.util.List<androidx.wear.tiles.LayoutElementBuilders.LayoutElement!> getSlotContents();
+  }
+
+  @Deprecated public static final class MultiSlotLayout.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public MultiSlotLayout.Builder();
+    method @Deprecated public androidx.wear.tiles.material.layouts.MultiSlotLayout.Builder addSlotContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.layouts.MultiSlotLayout build();
+    method @Deprecated public androidx.wear.tiles.material.layouts.MultiSlotLayout.Builder setHorizontalSpacerWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  @Deprecated public class PrimaryLayout implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public static androidx.wear.tiles.material.layouts.PrimaryLayout? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getContent();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getPrimaryChipContent();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getPrimaryLabelTextContent();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getSecondaryLabelTextContent();
+    method @Deprecated @Dimension(unit=androidx.annotation.Dimension.DP) public float getVerticalSpacerHeight();
+  }
+
+  @Deprecated public static final class PrimaryLayout.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public PrimaryLayout.Builder(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public androidx.wear.tiles.material.layouts.PrimaryLayout build();
+    method @Deprecated public androidx.wear.tiles.material.layouts.PrimaryLayout.Builder setContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.layouts.PrimaryLayout.Builder setPrimaryChipContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.layouts.PrimaryLayout.Builder setPrimaryLabelTextContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.layouts.PrimaryLayout.Builder setSecondaryLabelTextContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.material.layouts.PrimaryLayout.Builder setVerticalSpacerHeight(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+}
+
diff --git a/wear/tiles/tiles-renderer/api/1.4.0-beta01.txt b/wear/tiles/tiles-renderer/api/1.4.0-beta01.txt
new file mode 100644
index 0000000..ac732cf
--- /dev/null
+++ b/wear/tiles/tiles-renderer/api/1.4.0-beta01.txt
@@ -0,0 +1,105 @@
+// Signature format: 4.0
+package androidx.wear.tiles.client {
+
+  public interface TileClient {
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Integer!> requestApiVersion();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.wear.tiles.ResourceBuilders.Resources!> requestResources(androidx.wear.tiles.RequestBuilders.ResourcesRequest);
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.wear.tiles.TileBuilders.Tile!> requestTile(androidx.wear.tiles.RequestBuilders.TileRequest);
+    method public default com.google.common.util.concurrent.ListenableFuture<androidx.wear.protolayout.ResourceBuilders.Resources!> requestTileResourcesAsync(androidx.wear.tiles.RequestBuilders.ResourcesRequest);
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> sendOnTileAddedEvent();
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> sendOnTileEnterEvent();
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> sendOnTileLeaveEvent();
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> sendOnTileRemovedEvent();
+  }
+
+}
+
+package androidx.wear.tiles.connection {
+
+  public final class DefaultTileClient implements androidx.wear.tiles.client.TileClient {
+    ctor public DefaultTileClient(android.content.Context context, android.content.ComponentName componentName, java.util.concurrent.Executor executor);
+    ctor public DefaultTileClient(android.content.Context context, android.content.ComponentName componentName, kotlinx.coroutines.CoroutineScope coroutineScope, kotlinx.coroutines.CoroutineDispatcher coroutineDispatcher);
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Integer> requestApiVersion();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.wear.tiles.ResourceBuilders.Resources> requestResources(androidx.wear.tiles.RequestBuilders.ResourcesRequest requestParams);
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.wear.tiles.TileBuilders.Tile> requestTile(androidx.wear.tiles.RequestBuilders.TileRequest requestParams);
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void?> sendOnTileAddedEvent();
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void?> sendOnTileEnterEvent();
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void?> sendOnTileLeaveEvent();
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void?> sendOnTileRemovedEvent();
+  }
+
+}
+
+package androidx.wear.tiles.manager {
+
+  public final class TileUiClient implements java.lang.AutoCloseable {
+    ctor public TileUiClient(android.content.Context context, android.content.ComponentName component, android.view.ViewGroup parentView);
+    method @MainThread public void close();
+    method @MainThread public void connect();
+  }
+
+}
+
+package androidx.wear.tiles.renderer {
+
+  public final class TileRenderer {
+    ctor @Deprecated public TileRenderer(android.content.Context, androidx.wear.tiles.LayoutElementBuilders.Layout, androidx.wear.tiles.ResourceBuilders.Resources, java.util.concurrent.Executor, androidx.wear.tiles.renderer.TileRenderer.LoadActionListener);
+    ctor @Deprecated public TileRenderer(android.content.Context, androidx.wear.tiles.LayoutElementBuilders.Layout, @StyleRes int, androidx.wear.tiles.ResourceBuilders.Resources, java.util.concurrent.Executor, androidx.wear.tiles.renderer.TileRenderer.LoadActionListener);
+    ctor public TileRenderer(android.content.Context, java.util.concurrent.Executor, java.util.function.Consumer<androidx.wear.protolayout.StateBuilders.State!>);
+    method public java.util.concurrent.Executor getLoadActionExecutor();
+    method public java.util.function.Consumer<androidx.wear.protolayout.StateBuilders.State!> getLoadActionListener();
+    method public java.util.Map<androidx.wear.protolayout.expression.pipeline.PlatformDataProvider!,java.util.Set<androidx.wear.protolayout.expression.PlatformDataKey<? extends java.lang.Object!>!>!> getPlatformDataProviders();
+    method public int getTilesTheme();
+    method public android.content.Context getUiContext();
+    method @Deprecated public android.view.View? inflate(android.view.ViewGroup);
+    method public com.google.common.util.concurrent.ListenableFuture<android.view.View!> inflateAsync(androidx.wear.protolayout.LayoutElementBuilders.Layout, androidx.wear.protolayout.ResourceBuilders.Resources, android.view.ViewGroup);
+    method public void setState(java.util.Map<androidx.wear.protolayout.expression.AppDataKey<? extends java.lang.Object!>!,androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<? extends java.lang.Object!>!>);
+  }
+
+  public static final class TileRenderer.Builder {
+    ctor public TileRenderer.Builder(android.content.Context, java.util.concurrent.Executor, java.util.function.Consumer<androidx.wear.protolayout.StateBuilders.State!>);
+    method public androidx.wear.tiles.renderer.TileRenderer.Builder addPlatformDataProvider(androidx.wear.protolayout.expression.pipeline.PlatformDataProvider, androidx.wear.protolayout.expression.PlatformDataKey<? extends java.lang.Object!>!...);
+    method public androidx.wear.tiles.renderer.TileRenderer build();
+    method public androidx.wear.tiles.renderer.TileRenderer.Builder setTilesTheme(@StyleRes int);
+  }
+
+  @Deprecated public static interface TileRenderer.LoadActionListener {
+    method @Deprecated public void onClick(androidx.wear.tiles.StateBuilders.State);
+  }
+
+}
+
+package androidx.wear.tiles.timeline {
+
+  public final class TilesTimelineCache {
+    ctor public TilesTimelineCache(androidx.wear.protolayout.TimelineBuilders.Timeline);
+    ctor @Deprecated public TilesTimelineCache(androidx.wear.tiles.TimelineBuilders.Timeline);
+    method @MainThread public androidx.wear.protolayout.TimelineBuilders.TimelineEntry? findClosestTileTimelineEntry(long);
+    method @Deprecated @MainThread public androidx.wear.tiles.TimelineBuilders.TimelineEntry? findClosestTimelineEntry(long);
+    method @MainThread public long findCurrentTimelineEntryExpiry(androidx.wear.protolayout.TimelineBuilders.TimelineEntry, long);
+    method @Deprecated @MainThread public long findCurrentTimelineEntryExpiry(androidx.wear.tiles.TimelineBuilders.TimelineEntry, long);
+    method @MainThread public androidx.wear.protolayout.TimelineBuilders.TimelineEntry? findTileTimelineEntryForTime(long);
+    method @Deprecated @MainThread public androidx.wear.tiles.TimelineBuilders.TimelineEntry? findTimelineEntryForTime(long);
+  }
+
+  public class TilesTimelineManager implements java.lang.AutoCloseable {
+    ctor public TilesTimelineManager(android.app.AlarmManager, androidx.wear.tiles.timeline.TilesTimelineManager.Clock, androidx.wear.protolayout.TimelineBuilders.Timeline, int, java.util.concurrent.Executor, androidx.wear.tiles.timeline.TilesTimelineManager.LayoutUpdateListener);
+    ctor @Deprecated public TilesTimelineManager(android.app.AlarmManager, androidx.wear.tiles.timeline.TilesTimelineManager.Clock, androidx.wear.tiles.TimelineBuilders.Timeline, int, java.util.concurrent.Executor, androidx.wear.tiles.timeline.TilesTimelineManager.Listener);
+    method public void close();
+    method public void init();
+  }
+
+  public static interface TilesTimelineManager.Clock {
+    method public long getCurrentTimeMillis();
+  }
+
+  public static interface TilesTimelineManager.LayoutUpdateListener {
+    method public void onLayoutUpdate(int, androidx.wear.protolayout.LayoutElementBuilders.Layout);
+  }
+
+  @Deprecated public static interface TilesTimelineManager.Listener {
+    method @Deprecated public void onLayoutUpdate(int, androidx.wear.tiles.LayoutElementBuilders.Layout);
+  }
+
+}
+
diff --git a/wear/tiles/tiles-renderer/api/current.ignore b/wear/tiles/tiles-renderer/api/current.ignore
new file mode 100644
index 0000000..fbb89c1
--- /dev/null
+++ b/wear/tiles/tiles-renderer/api/current.ignore
@@ -0,0 +1,3 @@
+// Baseline format: 1.0
+InvalidNullConversion: androidx.wear.tiles.renderer.TileRenderer#setState(java.util.Map<androidx.wear.protolayout.expression.AppDataKey<?>,androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<?>>) parameter #0:
+    Attempted to remove nullability from java.lang.Object (was NONNULL) in parameter arg1 in androidx.wear.tiles.renderer.TileRenderer.setState(java.util.Map<androidx.wear.protolayout.expression.AppDataKey<?>,androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<?>> arg1)
diff --git a/wear/tiles/tiles-renderer/api/res-1.4.0-beta01.txt b/wear/tiles/tiles-renderer/api/res-1.4.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wear/tiles/tiles-renderer/api/res-1.4.0-beta01.txt
diff --git a/wear/tiles/tiles-renderer/api/restricted_1.4.0-beta01.txt b/wear/tiles/tiles-renderer/api/restricted_1.4.0-beta01.txt
new file mode 100644
index 0000000..ac732cf
--- /dev/null
+++ b/wear/tiles/tiles-renderer/api/restricted_1.4.0-beta01.txt
@@ -0,0 +1,105 @@
+// Signature format: 4.0
+package androidx.wear.tiles.client {
+
+  public interface TileClient {
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Integer!> requestApiVersion();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.wear.tiles.ResourceBuilders.Resources!> requestResources(androidx.wear.tiles.RequestBuilders.ResourcesRequest);
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.wear.tiles.TileBuilders.Tile!> requestTile(androidx.wear.tiles.RequestBuilders.TileRequest);
+    method public default com.google.common.util.concurrent.ListenableFuture<androidx.wear.protolayout.ResourceBuilders.Resources!> requestTileResourcesAsync(androidx.wear.tiles.RequestBuilders.ResourcesRequest);
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> sendOnTileAddedEvent();
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> sendOnTileEnterEvent();
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> sendOnTileLeaveEvent();
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> sendOnTileRemovedEvent();
+  }
+
+}
+
+package androidx.wear.tiles.connection {
+
+  public final class DefaultTileClient implements androidx.wear.tiles.client.TileClient {
+    ctor public DefaultTileClient(android.content.Context context, android.content.ComponentName componentName, java.util.concurrent.Executor executor);
+    ctor public DefaultTileClient(android.content.Context context, android.content.ComponentName componentName, kotlinx.coroutines.CoroutineScope coroutineScope, kotlinx.coroutines.CoroutineDispatcher coroutineDispatcher);
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Integer> requestApiVersion();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.wear.tiles.ResourceBuilders.Resources> requestResources(androidx.wear.tiles.RequestBuilders.ResourcesRequest requestParams);
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.wear.tiles.TileBuilders.Tile> requestTile(androidx.wear.tiles.RequestBuilders.TileRequest requestParams);
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void?> sendOnTileAddedEvent();
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void?> sendOnTileEnterEvent();
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void?> sendOnTileLeaveEvent();
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void?> sendOnTileRemovedEvent();
+  }
+
+}
+
+package androidx.wear.tiles.manager {
+
+  public final class TileUiClient implements java.lang.AutoCloseable {
+    ctor public TileUiClient(android.content.Context context, android.content.ComponentName component, android.view.ViewGroup parentView);
+    method @MainThread public void close();
+    method @MainThread public void connect();
+  }
+
+}
+
+package androidx.wear.tiles.renderer {
+
+  public final class TileRenderer {
+    ctor @Deprecated public TileRenderer(android.content.Context, androidx.wear.tiles.LayoutElementBuilders.Layout, androidx.wear.tiles.ResourceBuilders.Resources, java.util.concurrent.Executor, androidx.wear.tiles.renderer.TileRenderer.LoadActionListener);
+    ctor @Deprecated public TileRenderer(android.content.Context, androidx.wear.tiles.LayoutElementBuilders.Layout, @StyleRes int, androidx.wear.tiles.ResourceBuilders.Resources, java.util.concurrent.Executor, androidx.wear.tiles.renderer.TileRenderer.LoadActionListener);
+    ctor public TileRenderer(android.content.Context, java.util.concurrent.Executor, java.util.function.Consumer<androidx.wear.protolayout.StateBuilders.State!>);
+    method public java.util.concurrent.Executor getLoadActionExecutor();
+    method public java.util.function.Consumer<androidx.wear.protolayout.StateBuilders.State!> getLoadActionListener();
+    method public java.util.Map<androidx.wear.protolayout.expression.pipeline.PlatformDataProvider!,java.util.Set<androidx.wear.protolayout.expression.PlatformDataKey<? extends java.lang.Object!>!>!> getPlatformDataProviders();
+    method public int getTilesTheme();
+    method public android.content.Context getUiContext();
+    method @Deprecated public android.view.View? inflate(android.view.ViewGroup);
+    method public com.google.common.util.concurrent.ListenableFuture<android.view.View!> inflateAsync(androidx.wear.protolayout.LayoutElementBuilders.Layout, androidx.wear.protolayout.ResourceBuilders.Resources, android.view.ViewGroup);
+    method public void setState(java.util.Map<androidx.wear.protolayout.expression.AppDataKey<? extends java.lang.Object!>!,androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<? extends java.lang.Object!>!>);
+  }
+
+  public static final class TileRenderer.Builder {
+    ctor public TileRenderer.Builder(android.content.Context, java.util.concurrent.Executor, java.util.function.Consumer<androidx.wear.protolayout.StateBuilders.State!>);
+    method public androidx.wear.tiles.renderer.TileRenderer.Builder addPlatformDataProvider(androidx.wear.protolayout.expression.pipeline.PlatformDataProvider, androidx.wear.protolayout.expression.PlatformDataKey<? extends java.lang.Object!>!...);
+    method public androidx.wear.tiles.renderer.TileRenderer build();
+    method public androidx.wear.tiles.renderer.TileRenderer.Builder setTilesTheme(@StyleRes int);
+  }
+
+  @Deprecated public static interface TileRenderer.LoadActionListener {
+    method @Deprecated public void onClick(androidx.wear.tiles.StateBuilders.State);
+  }
+
+}
+
+package androidx.wear.tiles.timeline {
+
+  public final class TilesTimelineCache {
+    ctor public TilesTimelineCache(androidx.wear.protolayout.TimelineBuilders.Timeline);
+    ctor @Deprecated public TilesTimelineCache(androidx.wear.tiles.TimelineBuilders.Timeline);
+    method @MainThread public androidx.wear.protolayout.TimelineBuilders.TimelineEntry? findClosestTileTimelineEntry(long);
+    method @Deprecated @MainThread public androidx.wear.tiles.TimelineBuilders.TimelineEntry? findClosestTimelineEntry(long);
+    method @MainThread public long findCurrentTimelineEntryExpiry(androidx.wear.protolayout.TimelineBuilders.TimelineEntry, long);
+    method @Deprecated @MainThread public long findCurrentTimelineEntryExpiry(androidx.wear.tiles.TimelineBuilders.TimelineEntry, long);
+    method @MainThread public androidx.wear.protolayout.TimelineBuilders.TimelineEntry? findTileTimelineEntryForTime(long);
+    method @Deprecated @MainThread public androidx.wear.tiles.TimelineBuilders.TimelineEntry? findTimelineEntryForTime(long);
+  }
+
+  public class TilesTimelineManager implements java.lang.AutoCloseable {
+    ctor public TilesTimelineManager(android.app.AlarmManager, androidx.wear.tiles.timeline.TilesTimelineManager.Clock, androidx.wear.protolayout.TimelineBuilders.Timeline, int, java.util.concurrent.Executor, androidx.wear.tiles.timeline.TilesTimelineManager.LayoutUpdateListener);
+    ctor @Deprecated public TilesTimelineManager(android.app.AlarmManager, androidx.wear.tiles.timeline.TilesTimelineManager.Clock, androidx.wear.tiles.TimelineBuilders.Timeline, int, java.util.concurrent.Executor, androidx.wear.tiles.timeline.TilesTimelineManager.Listener);
+    method public void close();
+    method public void init();
+  }
+
+  public static interface TilesTimelineManager.Clock {
+    method public long getCurrentTimeMillis();
+  }
+
+  public static interface TilesTimelineManager.LayoutUpdateListener {
+    method public void onLayoutUpdate(int, androidx.wear.protolayout.LayoutElementBuilders.Layout);
+  }
+
+  @Deprecated public static interface TilesTimelineManager.Listener {
+    method @Deprecated public void onLayoutUpdate(int, androidx.wear.tiles.LayoutElementBuilders.Layout);
+  }
+
+}
+
diff --git a/wear/tiles/tiles-renderer/api/restricted_current.ignore b/wear/tiles/tiles-renderer/api/restricted_current.ignore
new file mode 100644
index 0000000..fbb89c1
--- /dev/null
+++ b/wear/tiles/tiles-renderer/api/restricted_current.ignore
@@ -0,0 +1,3 @@
+// Baseline format: 1.0
+InvalidNullConversion: androidx.wear.tiles.renderer.TileRenderer#setState(java.util.Map<androidx.wear.protolayout.expression.AppDataKey<?>,androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<?>>) parameter #0:
+    Attempted to remove nullability from java.lang.Object (was NONNULL) in parameter arg1 in androidx.wear.tiles.renderer.TileRenderer.setState(java.util.Map<androidx.wear.protolayout.expression.AppDataKey<?>,androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<?>> arg1)
diff --git a/wear/tiles/tiles-testing/api/1.4.0-beta01.txt b/wear/tiles/tiles-testing/api/1.4.0-beta01.txt
new file mode 100644
index 0000000..ae007dd
--- /dev/null
+++ b/wear/tiles/tiles-testing/api/1.4.0-beta01.txt
@@ -0,0 +1,17 @@
+// Signature format: 4.0
+package androidx.wear.tiles.testing {
+
+  public final class TestTileClient<T extends androidx.wear.tiles.TileService> implements androidx.wear.tiles.client.TileClient {
+    ctor public TestTileClient(T service, java.util.concurrent.Executor executor);
+    ctor public TestTileClient(T service, kotlinx.coroutines.CoroutineScope coroutineScope, kotlinx.coroutines.CoroutineDispatcher coroutineDispatcher);
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Integer> requestApiVersion();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.wear.tiles.ResourceBuilders.Resources> requestResources(androidx.wear.tiles.RequestBuilders.ResourcesRequest requestParams);
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.wear.tiles.TileBuilders.Tile> requestTile(androidx.wear.tiles.RequestBuilders.TileRequest requestParams);
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void?> sendOnTileAddedEvent();
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void?> sendOnTileEnterEvent();
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void?> sendOnTileLeaveEvent();
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void?> sendOnTileRemovedEvent();
+  }
+
+}
+
diff --git a/wear/tiles/tiles-testing/api/res-1.4.0-beta01.txt b/wear/tiles/tiles-testing/api/res-1.4.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wear/tiles/tiles-testing/api/res-1.4.0-beta01.txt
diff --git a/wear/tiles/tiles-testing/api/restricted_1.4.0-beta01.txt b/wear/tiles/tiles-testing/api/restricted_1.4.0-beta01.txt
new file mode 100644
index 0000000..ae007dd
--- /dev/null
+++ b/wear/tiles/tiles-testing/api/restricted_1.4.0-beta01.txt
@@ -0,0 +1,17 @@
+// Signature format: 4.0
+package androidx.wear.tiles.testing {
+
+  public final class TestTileClient<T extends androidx.wear.tiles.TileService> implements androidx.wear.tiles.client.TileClient {
+    ctor public TestTileClient(T service, java.util.concurrent.Executor executor);
+    ctor public TestTileClient(T service, kotlinx.coroutines.CoroutineScope coroutineScope, kotlinx.coroutines.CoroutineDispatcher coroutineDispatcher);
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Integer> requestApiVersion();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.wear.tiles.ResourceBuilders.Resources> requestResources(androidx.wear.tiles.RequestBuilders.ResourcesRequest requestParams);
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.wear.tiles.TileBuilders.Tile> requestTile(androidx.wear.tiles.RequestBuilders.TileRequest requestParams);
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void?> sendOnTileAddedEvent();
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void?> sendOnTileEnterEvent();
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void?> sendOnTileLeaveEvent();
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void?> sendOnTileRemovedEvent();
+  }
+
+}
+
diff --git a/wear/tiles/tiles-tooling-preview/api/1.4.0-beta01.txt b/wear/tiles/tiles-tooling-preview/api/1.4.0-beta01.txt
new file mode 100644
index 0000000..1b22f9e
--- /dev/null
+++ b/wear/tiles/tiles-tooling-preview/api/1.4.0-beta01.txt
@@ -0,0 +1,40 @@
+// Signature format: 4.0
+package androidx.wear.tiles.tooling.preview {
+
+  @kotlin.annotation.MustBeDocumented @kotlin.annotation.Repeatable @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.ANNOTATION_CLASS, kotlin.annotation.AnnotationTarget.FUNCTION}) public @interface Preview {
+    method public abstract String device() default androidx.wear.tooling.preview.devices.WearDevices.SMALL_ROUND;
+    method public abstract float fontScale() default 1.0;
+    method public abstract String group() default "";
+    method public abstract String locale() default "";
+    method public abstract String name() default "";
+    property public abstract String device;
+    property public abstract float fontScale;
+    property public abstract String group;
+    property public abstract String locale;
+    property public abstract String name;
+  }
+
+  @kotlin.annotation.MustBeDocumented @kotlin.annotation.Repeatable @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.ANNOTATION_CLASS, kotlin.annotation.AnnotationTarget.FUNCTION}) public static @interface Preview.Container {
+    method public abstract androidx.wear.tiles.tooling.preview.Preview[] value();
+  }
+
+  public final class TilePreviewData {
+    ctor public TilePreviewData(optional kotlin.jvm.functions.Function1<? super androidx.wear.tiles.RequestBuilders.ResourcesRequest,androidx.wear.protolayout.ResourceBuilders.Resources> onTileResourceRequest, optional androidx.wear.protolayout.expression.PlatformDataValues? platformDataValues, kotlin.jvm.functions.Function1<? super androidx.wear.tiles.RequestBuilders.TileRequest,androidx.wear.tiles.TileBuilders.Tile> onTileRequest);
+    ctor public TilePreviewData(optional kotlin.jvm.functions.Function1<? super androidx.wear.tiles.RequestBuilders.ResourcesRequest,androidx.wear.protolayout.ResourceBuilders.Resources> onTileResourceRequest, kotlin.jvm.functions.Function1<? super androidx.wear.tiles.RequestBuilders.TileRequest,androidx.wear.tiles.TileBuilders.Tile> onTileRequest);
+    ctor public TilePreviewData(kotlin.jvm.functions.Function1<? super androidx.wear.tiles.RequestBuilders.TileRequest,androidx.wear.tiles.TileBuilders.Tile> onTileRequest);
+    method public kotlin.jvm.functions.Function1<androidx.wear.tiles.RequestBuilders.TileRequest,androidx.wear.tiles.TileBuilders.Tile> getOnTileRequest();
+    method public kotlin.jvm.functions.Function1<androidx.wear.tiles.RequestBuilders.ResourcesRequest,androidx.wear.protolayout.ResourceBuilders.Resources> getOnTileResourceRequest();
+    method public androidx.wear.protolayout.expression.PlatformDataValues? getPlatformDataValues();
+    property public final kotlin.jvm.functions.Function1<androidx.wear.tiles.RequestBuilders.TileRequest,androidx.wear.tiles.TileBuilders.Tile> onTileRequest;
+    property public final kotlin.jvm.functions.Function1<androidx.wear.tiles.RequestBuilders.ResourcesRequest,androidx.wear.protolayout.ResourceBuilders.Resources> onTileResourceRequest;
+    property public final androidx.wear.protolayout.expression.PlatformDataValues? platformDataValues;
+  }
+
+  public final class TilePreviewHelper {
+    method public static androidx.wear.tiles.TileBuilders.Tile.Builder singleTimelineEntryTileBuilder(androidx.wear.protolayout.LayoutElementBuilders.Layout layout);
+    method public static androidx.wear.tiles.TileBuilders.Tile.Builder singleTimelineEntryTileBuilder(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement layoutElement);
+    field public static final androidx.wear.tiles.tooling.preview.TilePreviewHelper INSTANCE;
+  }
+
+}
+
diff --git a/wear/tiles/tiles-tooling-preview/api/res-1.4.0-beta01.txt b/wear/tiles/tiles-tooling-preview/api/res-1.4.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wear/tiles/tiles-tooling-preview/api/res-1.4.0-beta01.txt
diff --git a/wear/tiles/tiles-tooling-preview/api/restricted_1.4.0-beta01.txt b/wear/tiles/tiles-tooling-preview/api/restricted_1.4.0-beta01.txt
new file mode 100644
index 0000000..1b22f9e
--- /dev/null
+++ b/wear/tiles/tiles-tooling-preview/api/restricted_1.4.0-beta01.txt
@@ -0,0 +1,40 @@
+// Signature format: 4.0
+package androidx.wear.tiles.tooling.preview {
+
+  @kotlin.annotation.MustBeDocumented @kotlin.annotation.Repeatable @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.ANNOTATION_CLASS, kotlin.annotation.AnnotationTarget.FUNCTION}) public @interface Preview {
+    method public abstract String device() default androidx.wear.tooling.preview.devices.WearDevices.SMALL_ROUND;
+    method public abstract float fontScale() default 1.0;
+    method public abstract String group() default "";
+    method public abstract String locale() default "";
+    method public abstract String name() default "";
+    property public abstract String device;
+    property public abstract float fontScale;
+    property public abstract String group;
+    property public abstract String locale;
+    property public abstract String name;
+  }
+
+  @kotlin.annotation.MustBeDocumented @kotlin.annotation.Repeatable @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.ANNOTATION_CLASS, kotlin.annotation.AnnotationTarget.FUNCTION}) public static @interface Preview.Container {
+    method public abstract androidx.wear.tiles.tooling.preview.Preview[] value();
+  }
+
+  public final class TilePreviewData {
+    ctor public TilePreviewData(optional kotlin.jvm.functions.Function1<? super androidx.wear.tiles.RequestBuilders.ResourcesRequest,androidx.wear.protolayout.ResourceBuilders.Resources> onTileResourceRequest, optional androidx.wear.protolayout.expression.PlatformDataValues? platformDataValues, kotlin.jvm.functions.Function1<? super androidx.wear.tiles.RequestBuilders.TileRequest,androidx.wear.tiles.TileBuilders.Tile> onTileRequest);
+    ctor public TilePreviewData(optional kotlin.jvm.functions.Function1<? super androidx.wear.tiles.RequestBuilders.ResourcesRequest,androidx.wear.protolayout.ResourceBuilders.Resources> onTileResourceRequest, kotlin.jvm.functions.Function1<? super androidx.wear.tiles.RequestBuilders.TileRequest,androidx.wear.tiles.TileBuilders.Tile> onTileRequest);
+    ctor public TilePreviewData(kotlin.jvm.functions.Function1<? super androidx.wear.tiles.RequestBuilders.TileRequest,androidx.wear.tiles.TileBuilders.Tile> onTileRequest);
+    method public kotlin.jvm.functions.Function1<androidx.wear.tiles.RequestBuilders.TileRequest,androidx.wear.tiles.TileBuilders.Tile> getOnTileRequest();
+    method public kotlin.jvm.functions.Function1<androidx.wear.tiles.RequestBuilders.ResourcesRequest,androidx.wear.protolayout.ResourceBuilders.Resources> getOnTileResourceRequest();
+    method public androidx.wear.protolayout.expression.PlatformDataValues? getPlatformDataValues();
+    property public final kotlin.jvm.functions.Function1<androidx.wear.tiles.RequestBuilders.TileRequest,androidx.wear.tiles.TileBuilders.Tile> onTileRequest;
+    property public final kotlin.jvm.functions.Function1<androidx.wear.tiles.RequestBuilders.ResourcesRequest,androidx.wear.protolayout.ResourceBuilders.Resources> onTileResourceRequest;
+    property public final androidx.wear.protolayout.expression.PlatformDataValues? platformDataValues;
+  }
+
+  public final class TilePreviewHelper {
+    method public static androidx.wear.tiles.TileBuilders.Tile.Builder singleTimelineEntryTileBuilder(androidx.wear.protolayout.LayoutElementBuilders.Layout layout);
+    method public static androidx.wear.tiles.TileBuilders.Tile.Builder singleTimelineEntryTileBuilder(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement layoutElement);
+    field public static final androidx.wear.tiles.tooling.preview.TilePreviewHelper INSTANCE;
+  }
+
+}
+
diff --git a/wear/tiles/tiles-tooling/api/1.4.0-beta01.txt b/wear/tiles/tiles-tooling/api/1.4.0-beta01.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/wear/tiles/tiles-tooling/api/1.4.0-beta01.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/wear/tiles/tiles-tooling/api/res-1.4.0-beta01.txt b/wear/tiles/tiles-tooling/api/res-1.4.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wear/tiles/tiles-tooling/api/res-1.4.0-beta01.txt
diff --git a/wear/tiles/tiles-tooling/api/restricted_1.4.0-beta01.txt b/wear/tiles/tiles-tooling/api/restricted_1.4.0-beta01.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/wear/tiles/tiles-tooling/api/restricted_1.4.0-beta01.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/wear/tiles/tiles/api/1.4.0-beta01.txt b/wear/tiles/tiles/api/1.4.0-beta01.txt
new file mode 100644
index 0000000..7cd96a0
--- /dev/null
+++ b/wear/tiles/tiles/api/1.4.0-beta01.txt
@@ -0,0 +1,1150 @@
+// Signature format: 4.0
+package androidx.wear.tiles {
+
+  @Deprecated public final class ActionBuilders {
+    method @Deprecated public static androidx.wear.tiles.ActionBuilders.AndroidBooleanExtra booleanExtra(boolean);
+    method @Deprecated public static androidx.wear.tiles.ActionBuilders.AndroidDoubleExtra doubleExtra(double);
+    method @Deprecated public static androidx.wear.tiles.ActionBuilders.AndroidIntExtra intExtra(int);
+    method @Deprecated public static androidx.wear.tiles.ActionBuilders.AndroidLongExtra longExtra(long);
+    method @Deprecated public static androidx.wear.tiles.ActionBuilders.AndroidStringExtra stringExtra(String);
+  }
+
+  @Deprecated public static interface ActionBuilders.Action {
+  }
+
+  @Deprecated public static interface ActionBuilders.Action.Builder {
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.Action build();
+  }
+
+  @Deprecated public static final class ActionBuilders.AndroidActivity {
+    method @Deprecated public String getClassName();
+    method @Deprecated public java.util.Map<java.lang.String!,androidx.wear.tiles.ActionBuilders.AndroidExtra!> getKeyToExtraMapping();
+    method @Deprecated public String getPackageName();
+  }
+
+  @Deprecated public static final class ActionBuilders.AndroidActivity.Builder {
+    ctor @Deprecated public ActionBuilders.AndroidActivity.Builder();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidActivity.Builder addKeyToExtraMapping(String, androidx.wear.tiles.ActionBuilders.AndroidExtra);
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidActivity build();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidActivity.Builder setClassName(String);
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidActivity.Builder setPackageName(String);
+  }
+
+  @Deprecated public static final class ActionBuilders.AndroidBooleanExtra implements androidx.wear.tiles.ActionBuilders.AndroidExtra {
+    method @Deprecated public boolean getValue();
+  }
+
+  @Deprecated public static final class ActionBuilders.AndroidBooleanExtra.Builder implements androidx.wear.tiles.ActionBuilders.AndroidExtra.Builder {
+    ctor @Deprecated public ActionBuilders.AndroidBooleanExtra.Builder();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidBooleanExtra build();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidBooleanExtra.Builder setValue(boolean);
+  }
+
+  @Deprecated public static final class ActionBuilders.AndroidDoubleExtra implements androidx.wear.tiles.ActionBuilders.AndroidExtra {
+    method @Deprecated public double getValue();
+  }
+
+  @Deprecated public static final class ActionBuilders.AndroidDoubleExtra.Builder implements androidx.wear.tiles.ActionBuilders.AndroidExtra.Builder {
+    ctor @Deprecated public ActionBuilders.AndroidDoubleExtra.Builder();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidDoubleExtra build();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidDoubleExtra.Builder setValue(double);
+  }
+
+  @Deprecated public static interface ActionBuilders.AndroidExtra {
+  }
+
+  @Deprecated public static interface ActionBuilders.AndroidExtra.Builder {
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidExtra build();
+  }
+
+  @Deprecated public static final class ActionBuilders.AndroidIntExtra implements androidx.wear.tiles.ActionBuilders.AndroidExtra {
+    method @Deprecated public int getValue();
+  }
+
+  @Deprecated public static final class ActionBuilders.AndroidIntExtra.Builder implements androidx.wear.tiles.ActionBuilders.AndroidExtra.Builder {
+    ctor @Deprecated public ActionBuilders.AndroidIntExtra.Builder();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidIntExtra build();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidIntExtra.Builder setValue(int);
+  }
+
+  @Deprecated public static final class ActionBuilders.AndroidLongExtra implements androidx.wear.tiles.ActionBuilders.AndroidExtra {
+    method @Deprecated public long getValue();
+  }
+
+  @Deprecated public static final class ActionBuilders.AndroidLongExtra.Builder implements androidx.wear.tiles.ActionBuilders.AndroidExtra.Builder {
+    ctor @Deprecated public ActionBuilders.AndroidLongExtra.Builder();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidLongExtra build();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidLongExtra.Builder setValue(long);
+  }
+
+  @Deprecated public static final class ActionBuilders.AndroidStringExtra implements androidx.wear.tiles.ActionBuilders.AndroidExtra {
+    method @Deprecated public String getValue();
+  }
+
+  @Deprecated public static final class ActionBuilders.AndroidStringExtra.Builder implements androidx.wear.tiles.ActionBuilders.AndroidExtra.Builder {
+    ctor @Deprecated public ActionBuilders.AndroidStringExtra.Builder();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidStringExtra build();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidStringExtra.Builder setValue(String);
+  }
+
+  @Deprecated public static final class ActionBuilders.LaunchAction implements androidx.wear.tiles.ActionBuilders.Action {
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidActivity? getAndroidActivity();
+  }
+
+  @Deprecated public static final class ActionBuilders.LaunchAction.Builder implements androidx.wear.tiles.ActionBuilders.Action.Builder {
+    ctor @Deprecated public ActionBuilders.LaunchAction.Builder();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.LaunchAction build();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.LaunchAction.Builder setAndroidActivity(androidx.wear.tiles.ActionBuilders.AndroidActivity);
+  }
+
+  @Deprecated public static final class ActionBuilders.LoadAction implements androidx.wear.tiles.ActionBuilders.Action {
+    method @Deprecated public androidx.wear.tiles.StateBuilders.State? getRequestState();
+  }
+
+  @Deprecated public static final class ActionBuilders.LoadAction.Builder implements androidx.wear.tiles.ActionBuilders.Action.Builder {
+    ctor @Deprecated public ActionBuilders.LoadAction.Builder();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.LoadAction build();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.LoadAction.Builder setRequestState(androidx.wear.tiles.StateBuilders.State);
+  }
+
+  public final class ActiveTileIdentifier {
+    ctor public ActiveTileIdentifier(android.content.ComponentName, int);
+    method public android.content.ComponentName getComponentName();
+    method public int getInstanceId();
+  }
+
+  @Deprecated public final class ColorBuilders {
+    method @Deprecated public static androidx.wear.tiles.ColorBuilders.ColorProp argb(@ColorInt int);
+  }
+
+  @Deprecated public static final class ColorBuilders.ColorProp {
+    method @Deprecated @ColorInt public int getArgb();
+  }
+
+  @Deprecated public static final class ColorBuilders.ColorProp.Builder {
+    ctor @Deprecated public ColorBuilders.ColorProp.Builder();
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp build();
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp.Builder setArgb(@ColorInt int);
+  }
+
+  @Deprecated public final class DeviceParametersBuilders {
+    field @Deprecated public static final int DEVICE_PLATFORM_UNDEFINED = 0; // 0x0
+    field @Deprecated public static final int DEVICE_PLATFORM_WEAR_OS = 1; // 0x1
+    field @Deprecated public static final int SCREEN_SHAPE_RECT = 2; // 0x2
+    field @Deprecated public static final int SCREEN_SHAPE_ROUND = 1; // 0x1
+    field @Deprecated public static final int SCREEN_SHAPE_UNDEFINED = 0; // 0x0
+  }
+
+  @Deprecated public static final class DeviceParametersBuilders.DeviceParameters {
+    method @Deprecated public int getDevicePlatform();
+    method @Deprecated @FloatRange(from=0.0, fromInclusive=false, toInclusive=false) public float getScreenDensity();
+    method @Deprecated @Dimension(unit=androidx.annotation.Dimension.DP) public int getScreenHeightDp();
+    method @Deprecated public int getScreenShape();
+    method @Deprecated @Dimension(unit=androidx.annotation.Dimension.DP) public int getScreenWidthDp();
+  }
+
+  @Deprecated public static final class DeviceParametersBuilders.DeviceParameters.Builder {
+    ctor @Deprecated public DeviceParametersBuilders.DeviceParameters.Builder();
+    method @Deprecated public androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters build();
+    method @Deprecated public androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters.Builder setDevicePlatform(int);
+    method @Deprecated public androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters.Builder setScreenDensity(@FloatRange(from=0.0, fromInclusive=false, toInclusive=false) float);
+    method @Deprecated public androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters.Builder setScreenHeightDp(@Dimension(unit=androidx.annotation.Dimension.DP) int);
+    method @Deprecated public androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters.Builder setScreenShape(int);
+    method @Deprecated public androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters.Builder setScreenWidthDp(@Dimension(unit=androidx.annotation.Dimension.DP) int);
+  }
+
+  @Deprecated public final class DimensionBuilders {
+    method @Deprecated public static androidx.wear.tiles.DimensionBuilders.DegreesProp degrees(float);
+    method @Deprecated public static androidx.wear.tiles.DimensionBuilders.DpProp dp(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method @Deprecated public static androidx.wear.tiles.DimensionBuilders.EmProp em(float);
+    method @Deprecated public static androidx.wear.tiles.DimensionBuilders.EmProp em(int);
+    method @Deprecated public static androidx.wear.tiles.DimensionBuilders.ExpandedDimensionProp expand();
+    method @Deprecated public static androidx.wear.tiles.DimensionBuilders.SpProp sp(@Dimension(unit=androidx.annotation.Dimension.SP) float);
+    method @Deprecated public static androidx.wear.tiles.DimensionBuilders.WrappedDimensionProp wrap();
+  }
+
+  @Deprecated public static interface DimensionBuilders.ContainerDimension {
+  }
+
+  @Deprecated public static interface DimensionBuilders.ContainerDimension.Builder {
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ContainerDimension build();
+  }
+
+  @Deprecated public static final class DimensionBuilders.DegreesProp {
+    method @Deprecated public float getValue();
+  }
+
+  @Deprecated public static final class DimensionBuilders.DegreesProp.Builder {
+    ctor @Deprecated public DimensionBuilders.DegreesProp.Builder();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DegreesProp build();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DegreesProp.Builder setValue(float);
+  }
+
+  @Deprecated public static final class DimensionBuilders.DpProp implements androidx.wear.tiles.DimensionBuilders.ContainerDimension androidx.wear.tiles.DimensionBuilders.ImageDimension androidx.wear.tiles.DimensionBuilders.SpacerDimension {
+    method @Deprecated @Dimension(unit=androidx.annotation.Dimension.DP) public float getValue();
+  }
+
+  @Deprecated public static final class DimensionBuilders.DpProp.Builder implements androidx.wear.tiles.DimensionBuilders.ContainerDimension.Builder androidx.wear.tiles.DimensionBuilders.ImageDimension.Builder androidx.wear.tiles.DimensionBuilders.SpacerDimension.Builder {
+    ctor @Deprecated public DimensionBuilders.DpProp.Builder();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DpProp build();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DpProp.Builder setValue(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  @Deprecated public static final class DimensionBuilders.EmProp {
+    method @Deprecated public float getValue();
+  }
+
+  @Deprecated public static final class DimensionBuilders.EmProp.Builder {
+    ctor @Deprecated public DimensionBuilders.EmProp.Builder();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.EmProp build();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.EmProp.Builder setValue(float);
+  }
+
+  @Deprecated public static final class DimensionBuilders.ExpandedDimensionProp implements androidx.wear.tiles.DimensionBuilders.ContainerDimension androidx.wear.tiles.DimensionBuilders.ImageDimension {
+  }
+
+  @Deprecated public static final class DimensionBuilders.ExpandedDimensionProp.Builder implements androidx.wear.tiles.DimensionBuilders.ContainerDimension.Builder androidx.wear.tiles.DimensionBuilders.ImageDimension.Builder {
+    ctor @Deprecated public DimensionBuilders.ExpandedDimensionProp.Builder();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ExpandedDimensionProp build();
+  }
+
+  @Deprecated public static interface DimensionBuilders.ImageDimension {
+  }
+
+  @Deprecated public static interface DimensionBuilders.ImageDimension.Builder {
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ImageDimension build();
+  }
+
+  @Deprecated public static final class DimensionBuilders.ProportionalDimensionProp implements androidx.wear.tiles.DimensionBuilders.ImageDimension {
+    method @Deprecated @IntRange(from=0) public int getAspectRatioHeight();
+    method @Deprecated @IntRange(from=0) public int getAspectRatioWidth();
+  }
+
+  @Deprecated public static final class DimensionBuilders.ProportionalDimensionProp.Builder implements androidx.wear.tiles.DimensionBuilders.ImageDimension.Builder {
+    ctor @Deprecated public DimensionBuilders.ProportionalDimensionProp.Builder();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ProportionalDimensionProp build();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ProportionalDimensionProp.Builder setAspectRatioHeight(@IntRange(from=0) int);
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ProportionalDimensionProp.Builder setAspectRatioWidth(@IntRange(from=0) int);
+  }
+
+  @Deprecated public static final class DimensionBuilders.SpProp {
+    method @Deprecated @Dimension(unit=androidx.annotation.Dimension.SP) public float getValue();
+  }
+
+  @Deprecated public static final class DimensionBuilders.SpProp.Builder {
+    ctor @Deprecated public DimensionBuilders.SpProp.Builder();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.SpProp build();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.SpProp.Builder setValue(@Dimension(unit=androidx.annotation.Dimension.SP) float);
+  }
+
+  @Deprecated public static interface DimensionBuilders.SpacerDimension {
+  }
+
+  @Deprecated public static interface DimensionBuilders.SpacerDimension.Builder {
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.SpacerDimension build();
+  }
+
+  @Deprecated public static final class DimensionBuilders.WrappedDimensionProp implements androidx.wear.tiles.DimensionBuilders.ContainerDimension {
+  }
+
+  @Deprecated public static final class DimensionBuilders.WrappedDimensionProp.Builder implements androidx.wear.tiles.DimensionBuilders.ContainerDimension.Builder {
+    ctor @Deprecated public DimensionBuilders.WrappedDimensionProp.Builder();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.WrappedDimensionProp build();
+  }
+
+  public final class EventBuilders {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class EventBuilders.TileAddEvent {
+    method public int getTileId();
+  }
+
+  public static final class EventBuilders.TileAddEvent.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public EventBuilders.TileAddEvent.Builder();
+    method public androidx.wear.tiles.EventBuilders.TileAddEvent build();
+    method public androidx.wear.tiles.EventBuilders.TileAddEvent.Builder setTileId(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class EventBuilders.TileEnterEvent {
+    method public int getTileId();
+  }
+
+  public static final class EventBuilders.TileEnterEvent.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public EventBuilders.TileEnterEvent.Builder();
+    method public androidx.wear.tiles.EventBuilders.TileEnterEvent build();
+    method public androidx.wear.tiles.EventBuilders.TileEnterEvent.Builder setTileId(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static final class EventBuilders.TileInteractionEvent {
+    method public int getEventType();
+    method public int getTileId();
+    method public java.time.Instant getTimestamp();
+    field public static final int ENTER = 1; // 0x1
+    field public static final int LEAVE = 2; // 0x2
+    field public static final int UNKNOWN = 0; // 0x0
+  }
+
+  public static final class EventBuilders.TileInteractionEvent.Builder {
+    ctor public EventBuilders.TileInteractionEvent.Builder(int, int);
+    method public androidx.wear.tiles.EventBuilders.TileInteractionEvent build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.tiles.EventBuilders.TileInteractionEvent.Builder setTimestamp(java.time.Instant);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class EventBuilders.TileLeaveEvent {
+    method public int getTileId();
+  }
+
+  public static final class EventBuilders.TileLeaveEvent.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public EventBuilders.TileLeaveEvent.Builder();
+    method public androidx.wear.tiles.EventBuilders.TileLeaveEvent build();
+    method public androidx.wear.tiles.EventBuilders.TileLeaveEvent.Builder setTileId(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class EventBuilders.TileRemoveEvent {
+    method public int getTileId();
+  }
+
+  public static final class EventBuilders.TileRemoveEvent.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public EventBuilders.TileRemoveEvent.Builder();
+    method public androidx.wear.tiles.EventBuilders.TileRemoveEvent build();
+    method public androidx.wear.tiles.EventBuilders.TileRemoveEvent.Builder setTileId(int);
+  }
+
+  @Deprecated public final class LayoutElementBuilders {
+    field @Deprecated public static final int ARC_ANCHOR_CENTER = 2; // 0x2
+    field @Deprecated public static final int ARC_ANCHOR_END = 3; // 0x3
+    field @Deprecated public static final int ARC_ANCHOR_START = 1; // 0x1
+    field @Deprecated public static final int ARC_ANCHOR_UNDEFINED = 0; // 0x0
+    field @Deprecated public static final int CONTENT_SCALE_MODE_CROP = 2; // 0x2
+    field @Deprecated public static final int CONTENT_SCALE_MODE_FILL_BOUNDS = 3; // 0x3
+    field @Deprecated public static final int CONTENT_SCALE_MODE_FIT = 1; // 0x1
+    field @Deprecated public static final int CONTENT_SCALE_MODE_UNDEFINED = 0; // 0x0
+    field @Deprecated public static final int FONT_VARIANT_BODY = 2; // 0x2
+    field @Deprecated public static final int FONT_VARIANT_TITLE = 1; // 0x1
+    field @Deprecated public static final int FONT_VARIANT_UNDEFINED = 0; // 0x0
+    field @Deprecated public static final int FONT_WEIGHT_BOLD = 700; // 0x2bc
+    field @Deprecated @SuppressCompatibility @androidx.wear.tiles.TilesExperimental public static final int FONT_WEIGHT_MEDIUM = 500; // 0x1f4
+    field @Deprecated public static final int FONT_WEIGHT_NORMAL = 400; // 0x190
+    field @Deprecated public static final int FONT_WEIGHT_UNDEFINED = 0; // 0x0
+    field @Deprecated public static final int HORIZONTAL_ALIGN_CENTER = 2; // 0x2
+    field @Deprecated public static final int HORIZONTAL_ALIGN_END = 5; // 0x5
+    field @Deprecated public static final int HORIZONTAL_ALIGN_LEFT = 1; // 0x1
+    field @Deprecated public static final int HORIZONTAL_ALIGN_RIGHT = 3; // 0x3
+    field @Deprecated public static final int HORIZONTAL_ALIGN_START = 4; // 0x4
+    field @Deprecated public static final int HORIZONTAL_ALIGN_UNDEFINED = 0; // 0x0
+    field @Deprecated public static final int SPAN_VERTICAL_ALIGN_BOTTOM = 1; // 0x1
+    field @Deprecated public static final int SPAN_VERTICAL_ALIGN_TEXT_BASELINE = 2; // 0x2
+    field @Deprecated public static final int SPAN_VERTICAL_ALIGN_UNDEFINED = 0; // 0x0
+    field @Deprecated public static final int TEXT_ALIGN_CENTER = 2; // 0x2
+    field @Deprecated public static final int TEXT_ALIGN_END = 3; // 0x3
+    field @Deprecated public static final int TEXT_ALIGN_START = 1; // 0x1
+    field @Deprecated public static final int TEXT_ALIGN_UNDEFINED = 0; // 0x0
+    field @Deprecated public static final int TEXT_OVERFLOW_ELLIPSIZE_END = 2; // 0x2
+    field @Deprecated public static final int TEXT_OVERFLOW_TRUNCATE = 1; // 0x1
+    field @Deprecated public static final int TEXT_OVERFLOW_UNDEFINED = 0; // 0x0
+    field @Deprecated public static final int VERTICAL_ALIGN_BOTTOM = 3; // 0x3
+    field @Deprecated public static final int VERTICAL_ALIGN_CENTER = 2; // 0x2
+    field @Deprecated public static final int VERTICAL_ALIGN_TOP = 1; // 0x1
+    field @Deprecated public static final int VERTICAL_ALIGN_UNDEFINED = 0; // 0x0
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Arc implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DegreesProp? getAnchorAngle();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcAnchorTypeProp? getAnchorType();
+    method @Deprecated public java.util.List<androidx.wear.tiles.LayoutElementBuilders.ArcLayoutElement!> getContents();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers? getModifiers();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.VerticalAlignmentProp? getVerticalAlign();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Arc.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public LayoutElementBuilders.Arc.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Arc.Builder addContent(androidx.wear.tiles.LayoutElementBuilders.ArcLayoutElement);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Arc build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Arc.Builder setAnchorAngle(androidx.wear.tiles.DimensionBuilders.DegreesProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Arc.Builder setAnchorType(androidx.wear.tiles.LayoutElementBuilders.ArcAnchorTypeProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Arc.Builder setAnchorType(int);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Arc.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.Modifiers);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Arc.Builder setVerticalAlign(androidx.wear.tiles.LayoutElementBuilders.VerticalAlignmentProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Arc.Builder setVerticalAlign(int);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.ArcAdapter implements androidx.wear.tiles.LayoutElementBuilders.ArcLayoutElement {
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getContent();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.BoolProp? getRotateContents();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.ArcAdapter.Builder implements androidx.wear.tiles.LayoutElementBuilders.ArcLayoutElement.Builder {
+    ctor @Deprecated public LayoutElementBuilders.ArcAdapter.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcAdapter build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcAdapter.Builder setContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcAdapter.Builder setRotateContents(androidx.wear.tiles.TypeBuilders.BoolProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcAdapter.Builder setRotateContents(boolean);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.ArcAnchorTypeProp {
+    method @Deprecated public int getValue();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.ArcAnchorTypeProp.Builder {
+    ctor @Deprecated public LayoutElementBuilders.ArcAnchorTypeProp.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcAnchorTypeProp build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcAnchorTypeProp.Builder setValue(int);
+  }
+
+  @Deprecated public static interface LayoutElementBuilders.ArcLayoutElement {
+  }
+
+  @Deprecated public static interface LayoutElementBuilders.ArcLayoutElement.Builder {
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcLayoutElement build();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.ArcLine implements androidx.wear.tiles.LayoutElementBuilders.ArcLayoutElement {
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp? getColor();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DegreesProp? getLength();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.ArcModifiers? getModifiers();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DpProp? getThickness();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.ArcLine.Builder implements androidx.wear.tiles.LayoutElementBuilders.ArcLayoutElement.Builder {
+    ctor @Deprecated public LayoutElementBuilders.ArcLine.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcLine build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcLine.Builder setColor(androidx.wear.tiles.ColorBuilders.ColorProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcLine.Builder setLength(androidx.wear.tiles.DimensionBuilders.DegreesProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcLine.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.ArcModifiers);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcLine.Builder setThickness(androidx.wear.tiles.DimensionBuilders.DpProp);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.ArcSpacer implements androidx.wear.tiles.LayoutElementBuilders.ArcLayoutElement {
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DegreesProp? getLength();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.ArcModifiers? getModifiers();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DpProp? getThickness();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.ArcSpacer.Builder implements androidx.wear.tiles.LayoutElementBuilders.ArcLayoutElement.Builder {
+    ctor @Deprecated public LayoutElementBuilders.ArcSpacer.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcSpacer build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcSpacer.Builder setLength(androidx.wear.tiles.DimensionBuilders.DegreesProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcSpacer.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.ArcModifiers);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcSpacer.Builder setThickness(androidx.wear.tiles.DimensionBuilders.DpProp);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.ArcText implements androidx.wear.tiles.LayoutElementBuilders.ArcLayoutElement {
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontStyle? getFontStyle();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.ArcModifiers? getModifiers();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.StringProp? getText();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.ArcText.Builder implements androidx.wear.tiles.LayoutElementBuilders.ArcLayoutElement.Builder {
+    ctor @Deprecated public LayoutElementBuilders.ArcText.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcText build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcText.Builder setFontStyle(androidx.wear.tiles.LayoutElementBuilders.FontStyle);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcText.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.ArcModifiers);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcText.Builder setText(androidx.wear.tiles.TypeBuilders.StringProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcText.Builder setText(String);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Box implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public java.util.List<androidx.wear.tiles.LayoutElementBuilders.LayoutElement!> getContents();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ContainerDimension? getHeight();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.HorizontalAlignmentProp? getHorizontalAlignment();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers? getModifiers();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.VerticalAlignmentProp? getVerticalAlignment();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ContainerDimension? getWidth();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Box.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public LayoutElementBuilders.Box.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Box.Builder addContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Box build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Box.Builder setHeight(androidx.wear.tiles.DimensionBuilders.ContainerDimension);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Box.Builder setHorizontalAlignment(androidx.wear.tiles.LayoutElementBuilders.HorizontalAlignmentProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Box.Builder setHorizontalAlignment(int);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Box.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.Modifiers);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Box.Builder setVerticalAlignment(androidx.wear.tiles.LayoutElementBuilders.VerticalAlignmentProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Box.Builder setVerticalAlignment(int);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Box.Builder setWidth(androidx.wear.tiles.DimensionBuilders.ContainerDimension);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.ColorFilter {
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp? getTint();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.ColorFilter.Builder {
+    ctor @Deprecated public LayoutElementBuilders.ColorFilter.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ColorFilter build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ColorFilter.Builder setTint(androidx.wear.tiles.ColorBuilders.ColorProp);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Column implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public java.util.List<androidx.wear.tiles.LayoutElementBuilders.LayoutElement!> getContents();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ContainerDimension? getHeight();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.HorizontalAlignmentProp? getHorizontalAlignment();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers? getModifiers();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ContainerDimension? getWidth();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Column.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public LayoutElementBuilders.Column.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Column.Builder addContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Column build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Column.Builder setHeight(androidx.wear.tiles.DimensionBuilders.ContainerDimension);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Column.Builder setHorizontalAlignment(androidx.wear.tiles.LayoutElementBuilders.HorizontalAlignmentProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Column.Builder setHorizontalAlignment(int);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Column.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.Modifiers);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Column.Builder setWidth(androidx.wear.tiles.DimensionBuilders.ContainerDimension);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.ContentScaleModeProp {
+    method @Deprecated public int getValue();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.ContentScaleModeProp.Builder {
+    ctor @Deprecated public LayoutElementBuilders.ContentScaleModeProp.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ContentScaleModeProp build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ContentScaleModeProp.Builder setValue(int);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.FontStyle {
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp? getColor();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.BoolProp? getItalic();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.EmProp? getLetterSpacing();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.SpProp? getSize();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.BoolProp? getUnderline();
+    method @Deprecated @SuppressCompatibility @androidx.wear.tiles.TilesExperimental public androidx.wear.tiles.LayoutElementBuilders.FontVariantProp? getVariant();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontWeightProp? getWeight();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.FontStyle.Builder {
+    ctor @Deprecated public LayoutElementBuilders.FontStyle.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontStyle build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder setColor(androidx.wear.tiles.ColorBuilders.ColorProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder setItalic(androidx.wear.tiles.TypeBuilders.BoolProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder setItalic(boolean);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder setLetterSpacing(androidx.wear.tiles.DimensionBuilders.EmProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder setSize(androidx.wear.tiles.DimensionBuilders.SpProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder setUnderline(androidx.wear.tiles.TypeBuilders.BoolProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder setUnderline(boolean);
+    method @Deprecated @SuppressCompatibility @androidx.wear.tiles.TilesExperimental public androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder setVariant(androidx.wear.tiles.LayoutElementBuilders.FontVariantProp);
+    method @Deprecated @SuppressCompatibility @androidx.wear.tiles.TilesExperimental public androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder setVariant(int);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder setWeight(androidx.wear.tiles.LayoutElementBuilders.FontWeightProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder setWeight(int);
+  }
+
+  @Deprecated public static class LayoutElementBuilders.FontStyles {
+    method @Deprecated public static androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder body1(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder body2(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder button(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder caption1(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder caption2(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder display1(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder display2(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder display3(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder title1(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder title2(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder title3(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+  }
+
+  @Deprecated @SuppressCompatibility @androidx.wear.tiles.TilesExperimental public static final class LayoutElementBuilders.FontVariantProp {
+    method @Deprecated public int getValue();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.FontVariantProp.Builder {
+    ctor @Deprecated public LayoutElementBuilders.FontVariantProp.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontVariantProp build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontVariantProp.Builder setValue(int);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.FontWeightProp {
+    method @Deprecated public int getValue();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.FontWeightProp.Builder {
+    ctor @Deprecated public LayoutElementBuilders.FontWeightProp.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontWeightProp build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontWeightProp.Builder setValue(int);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.HorizontalAlignmentProp {
+    method @Deprecated public int getValue();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.HorizontalAlignmentProp.Builder {
+    ctor @Deprecated public LayoutElementBuilders.HorizontalAlignmentProp.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.HorizontalAlignmentProp build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.HorizontalAlignmentProp.Builder setValue(int);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Image implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ColorFilter? getColorFilter();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ContentScaleModeProp? getContentScaleMode();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ImageDimension? getHeight();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers? getModifiers();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.StringProp? getResourceId();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ImageDimension? getWidth();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Image.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public LayoutElementBuilders.Image.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Image build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Image.Builder setColorFilter(androidx.wear.tiles.LayoutElementBuilders.ColorFilter);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Image.Builder setContentScaleMode(androidx.wear.tiles.LayoutElementBuilders.ContentScaleModeProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Image.Builder setContentScaleMode(int);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Image.Builder setHeight(androidx.wear.tiles.DimensionBuilders.ImageDimension);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Image.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.Modifiers);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Image.Builder setResourceId(androidx.wear.tiles.TypeBuilders.StringProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Image.Builder setResourceId(String);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Image.Builder setWidth(androidx.wear.tiles.DimensionBuilders.ImageDimension);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Layout {
+    method @Deprecated @SuppressCompatibility @androidx.wear.tiles.TilesExperimental public static androidx.wear.tiles.LayoutElementBuilders.Layout? fromByteArray(byte[]);
+    method @Deprecated public static androidx.wear.tiles.LayoutElementBuilders.Layout fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getRoot();
+    method @Deprecated @SuppressCompatibility @androidx.wear.tiles.TilesExperimental public byte[] toByteArray();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Layout.Builder {
+    ctor @Deprecated public LayoutElementBuilders.Layout.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Layout build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Layout.Builder setRoot(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+  }
+
+  @Deprecated public static interface LayoutElementBuilders.LayoutElement {
+  }
+
+  @Deprecated public static interface LayoutElementBuilders.LayoutElement.Builder {
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.LayoutElement build();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Row implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public java.util.List<androidx.wear.tiles.LayoutElementBuilders.LayoutElement!> getContents();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ContainerDimension? getHeight();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers? getModifiers();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.VerticalAlignmentProp? getVerticalAlignment();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ContainerDimension? getWidth();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Row.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public LayoutElementBuilders.Row.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Row.Builder addContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Row build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Row.Builder setHeight(androidx.wear.tiles.DimensionBuilders.ContainerDimension);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Row.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.Modifiers);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Row.Builder setVerticalAlignment(androidx.wear.tiles.LayoutElementBuilders.VerticalAlignmentProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Row.Builder setVerticalAlignment(int);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Row.Builder setWidth(androidx.wear.tiles.DimensionBuilders.ContainerDimension);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Spacer implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.SpacerDimension? getHeight();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers? getModifiers();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.SpacerDimension? getWidth();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Spacer.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public LayoutElementBuilders.Spacer.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Spacer build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Spacer.Builder setHeight(androidx.wear.tiles.DimensionBuilders.SpacerDimension);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Spacer.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.Modifiers);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Spacer.Builder setWidth(androidx.wear.tiles.DimensionBuilders.SpacerDimension);
+  }
+
+  @Deprecated public static interface LayoutElementBuilders.Span {
+  }
+
+  @Deprecated public static interface LayoutElementBuilders.Span.Builder {
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Span build();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.SpanImage implements androidx.wear.tiles.LayoutElementBuilders.Span {
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanVerticalAlignmentProp? getAlignment();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DpProp? getHeight();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.SpanModifiers? getModifiers();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.StringProp? getResourceId();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DpProp? getWidth();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.SpanImage.Builder implements androidx.wear.tiles.LayoutElementBuilders.Span.Builder {
+    ctor @Deprecated public LayoutElementBuilders.SpanImage.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanImage build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanImage.Builder setAlignment(androidx.wear.tiles.LayoutElementBuilders.SpanVerticalAlignmentProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanImage.Builder setAlignment(int);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanImage.Builder setHeight(androidx.wear.tiles.DimensionBuilders.DpProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanImage.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.SpanModifiers);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanImage.Builder setResourceId(androidx.wear.tiles.TypeBuilders.StringProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanImage.Builder setResourceId(String);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanImage.Builder setWidth(androidx.wear.tiles.DimensionBuilders.DpProp);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.SpanText implements androidx.wear.tiles.LayoutElementBuilders.Span {
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontStyle? getFontStyle();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.SpanModifiers? getModifiers();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.StringProp? getText();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.SpanText.Builder implements androidx.wear.tiles.LayoutElementBuilders.Span.Builder {
+    ctor @Deprecated public LayoutElementBuilders.SpanText.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanText build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanText.Builder setFontStyle(androidx.wear.tiles.LayoutElementBuilders.FontStyle);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanText.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.SpanModifiers);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanText.Builder setText(androidx.wear.tiles.TypeBuilders.StringProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanText.Builder setText(String);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.SpanVerticalAlignmentProp {
+    method @Deprecated public int getValue();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.SpanVerticalAlignmentProp.Builder {
+    ctor @Deprecated public LayoutElementBuilders.SpanVerticalAlignmentProp.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanVerticalAlignmentProp build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanVerticalAlignmentProp.Builder setValue(int);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Spannable implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.SpProp? getLineHeight();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.Int32Prop? getMaxLines();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers? getModifiers();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.HorizontalAlignmentProp? getMultilineAlignment();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.TextOverflowProp? getOverflow();
+    method @Deprecated public java.util.List<androidx.wear.tiles.LayoutElementBuilders.Span!> getSpans();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Spannable.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public LayoutElementBuilders.Spannable.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Spannable.Builder addSpan(androidx.wear.tiles.LayoutElementBuilders.Span);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Spannable build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Spannable.Builder setLineHeight(androidx.wear.tiles.DimensionBuilders.SpProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Spannable.Builder setMaxLines(androidx.wear.tiles.TypeBuilders.Int32Prop);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Spannable.Builder setMaxLines(@IntRange(from=1) int);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Spannable.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.Modifiers);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Spannable.Builder setMultilineAlignment(androidx.wear.tiles.LayoutElementBuilders.HorizontalAlignmentProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Spannable.Builder setMultilineAlignment(int);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Spannable.Builder setOverflow(androidx.wear.tiles.LayoutElementBuilders.TextOverflowProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Spannable.Builder setOverflow(int);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Text implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontStyle? getFontStyle();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.SpProp? getLineHeight();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.Int32Prop? getMaxLines();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers? getModifiers();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.TextAlignmentProp? getMultilineAlignment();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.TextOverflowProp? getOverflow();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.StringProp? getText();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Text.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public LayoutElementBuilders.Text.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Text build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Text.Builder setFontStyle(androidx.wear.tiles.LayoutElementBuilders.FontStyle);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Text.Builder setLineHeight(androidx.wear.tiles.DimensionBuilders.SpProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Text.Builder setMaxLines(androidx.wear.tiles.TypeBuilders.Int32Prop);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Text.Builder setMaxLines(@IntRange(from=1) int);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Text.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.Modifiers);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Text.Builder setMultilineAlignment(androidx.wear.tiles.LayoutElementBuilders.TextAlignmentProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Text.Builder setMultilineAlignment(int);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Text.Builder setOverflow(androidx.wear.tiles.LayoutElementBuilders.TextOverflowProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Text.Builder setOverflow(int);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Text.Builder setText(androidx.wear.tiles.TypeBuilders.StringProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Text.Builder setText(String);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.TextAlignmentProp {
+    method @Deprecated public int getValue();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.TextAlignmentProp.Builder {
+    ctor @Deprecated public LayoutElementBuilders.TextAlignmentProp.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.TextAlignmentProp build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.TextAlignmentProp.Builder setValue(int);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.TextOverflowProp {
+    method @Deprecated public int getValue();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.TextOverflowProp.Builder {
+    ctor @Deprecated public LayoutElementBuilders.TextOverflowProp.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.TextOverflowProp build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.TextOverflowProp.Builder setValue(int);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.VerticalAlignmentProp {
+    method @Deprecated public int getValue();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.VerticalAlignmentProp.Builder {
+    ctor @Deprecated public LayoutElementBuilders.VerticalAlignmentProp.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.VerticalAlignmentProp build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.VerticalAlignmentProp.Builder setValue(int);
+  }
+
+  @Deprecated public final class ModifiersBuilders {
+  }
+
+  @Deprecated public static final class ModifiersBuilders.ArcModifiers {
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Clickable? getClickable();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Semantics? getSemantics();
+  }
+
+  @Deprecated public static final class ModifiersBuilders.ArcModifiers.Builder {
+    ctor @Deprecated public ModifiersBuilders.ArcModifiers.Builder();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.ArcModifiers build();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.ArcModifiers.Builder setClickable(androidx.wear.tiles.ModifiersBuilders.Clickable);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.ArcModifiers.Builder setSemantics(androidx.wear.tiles.ModifiersBuilders.Semantics);
+  }
+
+  @Deprecated public static final class ModifiersBuilders.Background {
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp? getColor();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Corner? getCorner();
+  }
+
+  @Deprecated public static final class ModifiersBuilders.Background.Builder {
+    ctor @Deprecated public ModifiersBuilders.Background.Builder();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Background build();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Background.Builder setColor(androidx.wear.tiles.ColorBuilders.ColorProp);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Background.Builder setCorner(androidx.wear.tiles.ModifiersBuilders.Corner);
+  }
+
+  @Deprecated public static final class ModifiersBuilders.Border {
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp? getColor();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DpProp? getWidth();
+  }
+
+  @Deprecated public static final class ModifiersBuilders.Border.Builder {
+    ctor @Deprecated public ModifiersBuilders.Border.Builder();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Border build();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Border.Builder setColor(androidx.wear.tiles.ColorBuilders.ColorProp);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Border.Builder setWidth(androidx.wear.tiles.DimensionBuilders.DpProp);
+  }
+
+  @Deprecated public static final class ModifiersBuilders.Clickable {
+    method @Deprecated public String getId();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.Action? getOnClick();
+  }
+
+  @Deprecated public static final class ModifiersBuilders.Clickable.Builder {
+    ctor @Deprecated public ModifiersBuilders.Clickable.Builder();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Clickable build();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Clickable.Builder setId(String);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Clickable.Builder setOnClick(androidx.wear.tiles.ActionBuilders.Action);
+  }
+
+  @Deprecated public static final class ModifiersBuilders.Corner {
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DpProp? getRadius();
+  }
+
+  @Deprecated public static final class ModifiersBuilders.Corner.Builder {
+    ctor @Deprecated public ModifiersBuilders.Corner.Builder();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Corner build();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Corner.Builder setRadius(androidx.wear.tiles.DimensionBuilders.DpProp);
+  }
+
+  @Deprecated public static final class ModifiersBuilders.ElementMetadata {
+    method @Deprecated public byte[] getTagData();
+  }
+
+  @Deprecated public static final class ModifiersBuilders.ElementMetadata.Builder {
+    ctor @Deprecated public ModifiersBuilders.ElementMetadata.Builder();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.ElementMetadata build();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.ElementMetadata.Builder setTagData(byte[]);
+  }
+
+  @Deprecated public static final class ModifiersBuilders.Modifiers {
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Background? getBackground();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Border? getBorder();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Clickable? getClickable();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.ElementMetadata? getMetadata();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Padding? getPadding();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Semantics? getSemantics();
+  }
+
+  @Deprecated public static final class ModifiersBuilders.Modifiers.Builder {
+    ctor @Deprecated public ModifiersBuilders.Modifiers.Builder();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers build();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers.Builder setBackground(androidx.wear.tiles.ModifiersBuilders.Background);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers.Builder setBorder(androidx.wear.tiles.ModifiersBuilders.Border);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers.Builder setClickable(androidx.wear.tiles.ModifiersBuilders.Clickable);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers.Builder setMetadata(androidx.wear.tiles.ModifiersBuilders.ElementMetadata);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers.Builder setPadding(androidx.wear.tiles.ModifiersBuilders.Padding);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers.Builder setSemantics(androidx.wear.tiles.ModifiersBuilders.Semantics);
+  }
+
+  @Deprecated public static final class ModifiersBuilders.Padding {
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DpProp? getBottom();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DpProp? getEnd();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.BoolProp? getRtlAware();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DpProp? getStart();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DpProp? getTop();
+  }
+
+  @Deprecated public static final class ModifiersBuilders.Padding.Builder {
+    ctor @Deprecated public ModifiersBuilders.Padding.Builder();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Padding build();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Padding.Builder setAll(androidx.wear.tiles.DimensionBuilders.DpProp);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Padding.Builder setBottom(androidx.wear.tiles.DimensionBuilders.DpProp);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Padding.Builder setEnd(androidx.wear.tiles.DimensionBuilders.DpProp);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Padding.Builder setRtlAware(androidx.wear.tiles.TypeBuilders.BoolProp);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Padding.Builder setRtlAware(boolean);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Padding.Builder setStart(androidx.wear.tiles.DimensionBuilders.DpProp);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Padding.Builder setTop(androidx.wear.tiles.DimensionBuilders.DpProp);
+  }
+
+  @Deprecated public static final class ModifiersBuilders.Semantics {
+    method @Deprecated public String getContentDescription();
+  }
+
+  @Deprecated public static final class ModifiersBuilders.Semantics.Builder {
+    ctor @Deprecated public ModifiersBuilders.Semantics.Builder();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Semantics build();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Semantics.Builder setContentDescription(String);
+  }
+
+  @Deprecated public static final class ModifiersBuilders.SpanModifiers {
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Clickable? getClickable();
+  }
+
+  @Deprecated public static final class ModifiersBuilders.SpanModifiers.Builder {
+    ctor @Deprecated public ModifiersBuilders.SpanModifiers.Builder();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.SpanModifiers build();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.SpanModifiers.Builder setClickable(androidx.wear.tiles.ModifiersBuilders.Clickable);
+  }
+
+  public final class RequestBuilders {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class RequestBuilders.ResourcesRequest {
+    method public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters getDeviceConfiguration();
+    method @Deprecated public androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters? getDeviceParameters();
+    method public java.util.List<java.lang.String!> getResourceIds();
+    method public int getTileId();
+    method public String getVersion();
+  }
+
+  public static final class RequestBuilders.ResourcesRequest.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public RequestBuilders.ResourcesRequest.Builder();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.tiles.RequestBuilders.ResourcesRequest.Builder addResourceId(String);
+    method public androidx.wear.tiles.RequestBuilders.ResourcesRequest build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.tiles.RequestBuilders.ResourcesRequest.Builder setDeviceConfiguration(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public androidx.wear.tiles.RequestBuilders.ResourcesRequest.Builder setDeviceParameters(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.tiles.RequestBuilders.ResourcesRequest.Builder setTileId(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.tiles.RequestBuilders.ResourcesRequest.Builder setVersion(String);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class RequestBuilders.TileRequest {
+    method public androidx.wear.protolayout.StateBuilders.State getCurrentState();
+    method public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters getDeviceConfiguration();
+    method @Deprecated public androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters? getDeviceParameters();
+    method @Deprecated public androidx.wear.tiles.StateBuilders.State? getState();
+    method public int getTileId();
+  }
+
+  public static final class RequestBuilders.TileRequest.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public RequestBuilders.TileRequest.Builder();
+    method public androidx.wear.tiles.RequestBuilders.TileRequest build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.tiles.RequestBuilders.TileRequest.Builder setCurrentState(androidx.wear.protolayout.StateBuilders.State);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.tiles.RequestBuilders.TileRequest.Builder setDeviceConfiguration(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public androidx.wear.tiles.RequestBuilders.TileRequest.Builder setDeviceParameters(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public androidx.wear.tiles.RequestBuilders.TileRequest.Builder setState(androidx.wear.tiles.StateBuilders.State);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.tiles.RequestBuilders.TileRequest.Builder setTileId(int);
+  }
+
+  @Deprecated public final class ResourceBuilders {
+    field @Deprecated public static final int IMAGE_FORMAT_RGB_565 = 1; // 0x1
+    field @Deprecated public static final int IMAGE_FORMAT_UNDEFINED = 0; // 0x0
+  }
+
+  @Deprecated public static final class ResourceBuilders.AndroidImageResourceByResId {
+    method @Deprecated @DrawableRes public int getResourceId();
+  }
+
+  @Deprecated public static final class ResourceBuilders.AndroidImageResourceByResId.Builder {
+    ctor @Deprecated public ResourceBuilders.AndroidImageResourceByResId.Builder();
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.AndroidImageResourceByResId build();
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.AndroidImageResourceByResId.Builder setResourceId(@DrawableRes int);
+  }
+
+  @Deprecated public static final class ResourceBuilders.ImageResource {
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.AndroidImageResourceByResId? getAndroidResourceByResId();
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.InlineImageResource? getInlineResource();
+  }
+
+  @Deprecated public static final class ResourceBuilders.ImageResource.Builder {
+    ctor @Deprecated public ResourceBuilders.ImageResource.Builder();
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.ImageResource build();
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.ImageResource.Builder setAndroidResourceByResId(androidx.wear.tiles.ResourceBuilders.AndroidImageResourceByResId);
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.ImageResource.Builder setInlineResource(androidx.wear.tiles.ResourceBuilders.InlineImageResource);
+  }
+
+  @Deprecated public static final class ResourceBuilders.InlineImageResource {
+    method @Deprecated public byte[] getData();
+    method @Deprecated public int getFormat();
+    method @Deprecated @Dimension(unit=androidx.annotation.Dimension.PX) public int getHeightPx();
+    method @Deprecated @Dimension(unit=androidx.annotation.Dimension.PX) public int getWidthPx();
+  }
+
+  @Deprecated public static final class ResourceBuilders.InlineImageResource.Builder {
+    ctor @Deprecated public ResourceBuilders.InlineImageResource.Builder();
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.InlineImageResource build();
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.InlineImageResource.Builder setData(byte[]);
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.InlineImageResource.Builder setFormat(int);
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.InlineImageResource.Builder setHeightPx(@Dimension(unit=androidx.annotation.Dimension.PX) int);
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.InlineImageResource.Builder setWidthPx(@Dimension(unit=androidx.annotation.Dimension.PX) int);
+  }
+
+  @Deprecated public static final class ResourceBuilders.Resources {
+    method @Deprecated @SuppressCompatibility @androidx.wear.tiles.TilesExperimental public static androidx.wear.tiles.ResourceBuilders.Resources? fromByteArray(byte[]);
+    method @Deprecated public java.util.Map<java.lang.String!,androidx.wear.tiles.ResourceBuilders.ImageResource!> getIdToImageMapping();
+    method @Deprecated public String getVersion();
+    method @Deprecated @SuppressCompatibility @androidx.wear.tiles.TilesExperimental public byte[] toByteArray();
+  }
+
+  @Deprecated public static final class ResourceBuilders.Resources.Builder {
+    ctor @Deprecated public ResourceBuilders.Resources.Builder();
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.Resources.Builder addIdToImageMapping(String, androidx.wear.tiles.ResourceBuilders.ImageResource);
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.Resources build();
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.Resources.Builder setVersion(String);
+  }
+
+  @Deprecated public final class StateBuilders {
+  }
+
+  @Deprecated public static final class StateBuilders.State {
+    method @Deprecated public String getLastClickableId();
+  }
+
+  @Deprecated public static final class StateBuilders.State.Builder {
+    ctor @Deprecated public StateBuilders.State.Builder();
+    method @Deprecated public androidx.wear.tiles.StateBuilders.State build();
+  }
+
+  public final class TileBuilders {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class TileBuilders.Tile {
+    method public long getFreshnessIntervalMillis();
+    method public String getResourcesVersion();
+    method public androidx.wear.protolayout.StateBuilders.State? getState();
+    method public androidx.wear.protolayout.TimelineBuilders.Timeline? getTileTimeline();
+    method @Deprecated public androidx.wear.tiles.TimelineBuilders.Timeline? getTimeline();
+  }
+
+  public static final class TileBuilders.Tile.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public TileBuilders.Tile.Builder();
+    method public androidx.wear.tiles.TileBuilders.Tile build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.tiles.TileBuilders.Tile.Builder setFreshnessIntervalMillis(long);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.tiles.TileBuilders.Tile.Builder setResourcesVersion(String);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.tiles.TileBuilders.Tile.Builder setState(androidx.wear.protolayout.StateBuilders.State);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.tiles.TileBuilders.Tile.Builder setTileTimeline(androidx.wear.protolayout.TimelineBuilders.Timeline);
+    method @Deprecated public androidx.wear.tiles.TileBuilders.Tile.Builder setTimeline(androidx.wear.tiles.TimelineBuilders.Timeline);
+  }
+
+  public abstract class TileService extends android.app.Service {
+    ctor public TileService();
+    method public static com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.wear.tiles.ActiveTileIdentifier!>!> getActiveTilesAsync(android.content.Context, java.util.concurrent.Executor);
+    method public static androidx.wear.tiles.TileUpdateRequester getUpdater(android.content.Context);
+    method public android.os.IBinder? onBind(android.content.Intent);
+    method @Deprecated @MainThread protected com.google.common.util.concurrent.ListenableFuture<androidx.wear.tiles.ResourceBuilders.Resources!> onResourcesRequest(androidx.wear.tiles.RequestBuilders.ResourcesRequest);
+    method @MainThread protected void onTileAddEvent(androidx.wear.tiles.EventBuilders.TileAddEvent);
+    method @MainThread protected void onTileEnterEvent(androidx.wear.tiles.EventBuilders.TileEnterEvent);
+    method @MainThread protected void onTileLeaveEvent(androidx.wear.tiles.EventBuilders.TileLeaveEvent);
+    method @MainThread protected void onTileRemoveEvent(androidx.wear.tiles.EventBuilders.TileRemoveEvent);
+    method @MainThread protected abstract com.google.common.util.concurrent.ListenableFuture<androidx.wear.tiles.TileBuilders.Tile!> onTileRequest(androidx.wear.tiles.RequestBuilders.TileRequest);
+    method @MainThread protected com.google.common.util.concurrent.ListenableFuture<androidx.wear.protolayout.ResourceBuilders.Resources!> onTileResourcesRequest(androidx.wear.tiles.RequestBuilders.ResourcesRequest);
+    field public static final String ACTION_BIND_TILE_PROVIDER = "androidx.wear.tiles.action.BIND_TILE_PROVIDER";
+    field public static final String EXTRA_CLICKABLE_ID = "androidx.wear.tiles.extra.CLICKABLE_ID";
+    field public static final String METADATA_PREVIEW_KEY = "androidx.wear.tiles.PREVIEW";
+  }
+
+  public interface TileUpdateRequester {
+    method public void requestUpdate(Class<? extends androidx.wear.tiles.TileService!>);
+  }
+
+  @SuppressCompatibility @RequiresOptIn(level=androidx.annotation.RequiresOptIn.Level.ERROR) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD}) public @interface TilesExperimental {
+  }
+
+  @Deprecated public final class TimelineBuilders {
+  }
+
+  @Deprecated public static final class TimelineBuilders.TimeInterval {
+    method @Deprecated public long getEndMillis();
+    method @Deprecated public long getStartMillis();
+  }
+
+  @Deprecated public static final class TimelineBuilders.TimeInterval.Builder {
+    ctor @Deprecated public TimelineBuilders.TimeInterval.Builder();
+    method @Deprecated public androidx.wear.tiles.TimelineBuilders.TimeInterval build();
+    method @Deprecated public androidx.wear.tiles.TimelineBuilders.TimeInterval.Builder setEndMillis(long);
+    method @Deprecated public androidx.wear.tiles.TimelineBuilders.TimeInterval.Builder setStartMillis(long);
+  }
+
+  @Deprecated public static final class TimelineBuilders.Timeline {
+    method @Deprecated public static androidx.wear.tiles.TimelineBuilders.Timeline fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public java.util.List<androidx.wear.tiles.TimelineBuilders.TimelineEntry!> getTimelineEntries();
+  }
+
+  @Deprecated public static final class TimelineBuilders.Timeline.Builder {
+    ctor @Deprecated public TimelineBuilders.Timeline.Builder();
+    method @Deprecated public androidx.wear.tiles.TimelineBuilders.Timeline.Builder addTimelineEntry(androidx.wear.tiles.TimelineBuilders.TimelineEntry);
+    method @Deprecated public androidx.wear.tiles.TimelineBuilders.Timeline build();
+  }
+
+  @Deprecated public static final class TimelineBuilders.TimelineEntry {
+    method @Deprecated public static androidx.wear.tiles.TimelineBuilders.TimelineEntry fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Layout? getLayout();
+    method @Deprecated public androidx.wear.tiles.TimelineBuilders.TimeInterval? getValidity();
+  }
+
+  @Deprecated public static final class TimelineBuilders.TimelineEntry.Builder {
+    ctor @Deprecated public TimelineBuilders.TimelineEntry.Builder();
+    method @Deprecated public androidx.wear.tiles.TimelineBuilders.TimelineEntry build();
+    method @Deprecated public androidx.wear.tiles.TimelineBuilders.TimelineEntry.Builder setLayout(androidx.wear.tiles.LayoutElementBuilders.Layout);
+    method @Deprecated public androidx.wear.tiles.TimelineBuilders.TimelineEntry.Builder setValidity(androidx.wear.tiles.TimelineBuilders.TimeInterval);
+  }
+
+  @Deprecated public final class TypeBuilders {
+  }
+
+  @Deprecated public static final class TypeBuilders.BoolProp {
+    method @Deprecated public boolean getValue();
+  }
+
+  @Deprecated public static final class TypeBuilders.BoolProp.Builder {
+    ctor @Deprecated public TypeBuilders.BoolProp.Builder();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.BoolProp build();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.BoolProp.Builder setValue(boolean);
+  }
+
+  @Deprecated public static final class TypeBuilders.FloatProp {
+    method @Deprecated public float getValue();
+  }
+
+  @Deprecated public static final class TypeBuilders.FloatProp.Builder {
+    ctor @Deprecated public TypeBuilders.FloatProp.Builder();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.FloatProp build();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.FloatProp.Builder setValue(float);
+  }
+
+  @Deprecated public static final class TypeBuilders.Int32Prop {
+    method @Deprecated public int getValue();
+  }
+
+  @Deprecated public static final class TypeBuilders.Int32Prop.Builder {
+    ctor @Deprecated public TypeBuilders.Int32Prop.Builder();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.Int32Prop build();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.Int32Prop.Builder setValue(int);
+  }
+
+  @Deprecated public static final class TypeBuilders.StringProp {
+    method @Deprecated public String getValue();
+  }
+
+  @Deprecated public static final class TypeBuilders.StringProp.Builder {
+    ctor @Deprecated public TypeBuilders.StringProp.Builder();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.StringProp build();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.StringProp.Builder setValue(String);
+  }
+
+}
+
diff --git a/wear/tiles/tiles/api/res-1.4.0-beta01.txt b/wear/tiles/tiles/api/res-1.4.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wear/tiles/tiles/api/res-1.4.0-beta01.txt
diff --git a/wear/tiles/tiles/api/restricted_1.4.0-beta01.txt b/wear/tiles/tiles/api/restricted_1.4.0-beta01.txt
new file mode 100644
index 0000000..7cd96a0
--- /dev/null
+++ b/wear/tiles/tiles/api/restricted_1.4.0-beta01.txt
@@ -0,0 +1,1150 @@
+// Signature format: 4.0
+package androidx.wear.tiles {
+
+  @Deprecated public final class ActionBuilders {
+    method @Deprecated public static androidx.wear.tiles.ActionBuilders.AndroidBooleanExtra booleanExtra(boolean);
+    method @Deprecated public static androidx.wear.tiles.ActionBuilders.AndroidDoubleExtra doubleExtra(double);
+    method @Deprecated public static androidx.wear.tiles.ActionBuilders.AndroidIntExtra intExtra(int);
+    method @Deprecated public static androidx.wear.tiles.ActionBuilders.AndroidLongExtra longExtra(long);
+    method @Deprecated public static androidx.wear.tiles.ActionBuilders.AndroidStringExtra stringExtra(String);
+  }
+
+  @Deprecated public static interface ActionBuilders.Action {
+  }
+
+  @Deprecated public static interface ActionBuilders.Action.Builder {
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.Action build();
+  }
+
+  @Deprecated public static final class ActionBuilders.AndroidActivity {
+    method @Deprecated public String getClassName();
+    method @Deprecated public java.util.Map<java.lang.String!,androidx.wear.tiles.ActionBuilders.AndroidExtra!> getKeyToExtraMapping();
+    method @Deprecated public String getPackageName();
+  }
+
+  @Deprecated public static final class ActionBuilders.AndroidActivity.Builder {
+    ctor @Deprecated public ActionBuilders.AndroidActivity.Builder();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidActivity.Builder addKeyToExtraMapping(String, androidx.wear.tiles.ActionBuilders.AndroidExtra);
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidActivity build();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidActivity.Builder setClassName(String);
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidActivity.Builder setPackageName(String);
+  }
+
+  @Deprecated public static final class ActionBuilders.AndroidBooleanExtra implements androidx.wear.tiles.ActionBuilders.AndroidExtra {
+    method @Deprecated public boolean getValue();
+  }
+
+  @Deprecated public static final class ActionBuilders.AndroidBooleanExtra.Builder implements androidx.wear.tiles.ActionBuilders.AndroidExtra.Builder {
+    ctor @Deprecated public ActionBuilders.AndroidBooleanExtra.Builder();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidBooleanExtra build();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidBooleanExtra.Builder setValue(boolean);
+  }
+
+  @Deprecated public static final class ActionBuilders.AndroidDoubleExtra implements androidx.wear.tiles.ActionBuilders.AndroidExtra {
+    method @Deprecated public double getValue();
+  }
+
+  @Deprecated public static final class ActionBuilders.AndroidDoubleExtra.Builder implements androidx.wear.tiles.ActionBuilders.AndroidExtra.Builder {
+    ctor @Deprecated public ActionBuilders.AndroidDoubleExtra.Builder();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidDoubleExtra build();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidDoubleExtra.Builder setValue(double);
+  }
+
+  @Deprecated public static interface ActionBuilders.AndroidExtra {
+  }
+
+  @Deprecated public static interface ActionBuilders.AndroidExtra.Builder {
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidExtra build();
+  }
+
+  @Deprecated public static final class ActionBuilders.AndroidIntExtra implements androidx.wear.tiles.ActionBuilders.AndroidExtra {
+    method @Deprecated public int getValue();
+  }
+
+  @Deprecated public static final class ActionBuilders.AndroidIntExtra.Builder implements androidx.wear.tiles.ActionBuilders.AndroidExtra.Builder {
+    ctor @Deprecated public ActionBuilders.AndroidIntExtra.Builder();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidIntExtra build();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidIntExtra.Builder setValue(int);
+  }
+
+  @Deprecated public static final class ActionBuilders.AndroidLongExtra implements androidx.wear.tiles.ActionBuilders.AndroidExtra {
+    method @Deprecated public long getValue();
+  }
+
+  @Deprecated public static final class ActionBuilders.AndroidLongExtra.Builder implements androidx.wear.tiles.ActionBuilders.AndroidExtra.Builder {
+    ctor @Deprecated public ActionBuilders.AndroidLongExtra.Builder();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidLongExtra build();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidLongExtra.Builder setValue(long);
+  }
+
+  @Deprecated public static final class ActionBuilders.AndroidStringExtra implements androidx.wear.tiles.ActionBuilders.AndroidExtra {
+    method @Deprecated public String getValue();
+  }
+
+  @Deprecated public static final class ActionBuilders.AndroidStringExtra.Builder implements androidx.wear.tiles.ActionBuilders.AndroidExtra.Builder {
+    ctor @Deprecated public ActionBuilders.AndroidStringExtra.Builder();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidStringExtra build();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidStringExtra.Builder setValue(String);
+  }
+
+  @Deprecated public static final class ActionBuilders.LaunchAction implements androidx.wear.tiles.ActionBuilders.Action {
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.AndroidActivity? getAndroidActivity();
+  }
+
+  @Deprecated public static final class ActionBuilders.LaunchAction.Builder implements androidx.wear.tiles.ActionBuilders.Action.Builder {
+    ctor @Deprecated public ActionBuilders.LaunchAction.Builder();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.LaunchAction build();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.LaunchAction.Builder setAndroidActivity(androidx.wear.tiles.ActionBuilders.AndroidActivity);
+  }
+
+  @Deprecated public static final class ActionBuilders.LoadAction implements androidx.wear.tiles.ActionBuilders.Action {
+    method @Deprecated public androidx.wear.tiles.StateBuilders.State? getRequestState();
+  }
+
+  @Deprecated public static final class ActionBuilders.LoadAction.Builder implements androidx.wear.tiles.ActionBuilders.Action.Builder {
+    ctor @Deprecated public ActionBuilders.LoadAction.Builder();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.LoadAction build();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.LoadAction.Builder setRequestState(androidx.wear.tiles.StateBuilders.State);
+  }
+
+  public final class ActiveTileIdentifier {
+    ctor public ActiveTileIdentifier(android.content.ComponentName, int);
+    method public android.content.ComponentName getComponentName();
+    method public int getInstanceId();
+  }
+
+  @Deprecated public final class ColorBuilders {
+    method @Deprecated public static androidx.wear.tiles.ColorBuilders.ColorProp argb(@ColorInt int);
+  }
+
+  @Deprecated public static final class ColorBuilders.ColorProp {
+    method @Deprecated @ColorInt public int getArgb();
+  }
+
+  @Deprecated public static final class ColorBuilders.ColorProp.Builder {
+    ctor @Deprecated public ColorBuilders.ColorProp.Builder();
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp build();
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp.Builder setArgb(@ColorInt int);
+  }
+
+  @Deprecated public final class DeviceParametersBuilders {
+    field @Deprecated public static final int DEVICE_PLATFORM_UNDEFINED = 0; // 0x0
+    field @Deprecated public static final int DEVICE_PLATFORM_WEAR_OS = 1; // 0x1
+    field @Deprecated public static final int SCREEN_SHAPE_RECT = 2; // 0x2
+    field @Deprecated public static final int SCREEN_SHAPE_ROUND = 1; // 0x1
+    field @Deprecated public static final int SCREEN_SHAPE_UNDEFINED = 0; // 0x0
+  }
+
+  @Deprecated public static final class DeviceParametersBuilders.DeviceParameters {
+    method @Deprecated public int getDevicePlatform();
+    method @Deprecated @FloatRange(from=0.0, fromInclusive=false, toInclusive=false) public float getScreenDensity();
+    method @Deprecated @Dimension(unit=androidx.annotation.Dimension.DP) public int getScreenHeightDp();
+    method @Deprecated public int getScreenShape();
+    method @Deprecated @Dimension(unit=androidx.annotation.Dimension.DP) public int getScreenWidthDp();
+  }
+
+  @Deprecated public static final class DeviceParametersBuilders.DeviceParameters.Builder {
+    ctor @Deprecated public DeviceParametersBuilders.DeviceParameters.Builder();
+    method @Deprecated public androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters build();
+    method @Deprecated public androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters.Builder setDevicePlatform(int);
+    method @Deprecated public androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters.Builder setScreenDensity(@FloatRange(from=0.0, fromInclusive=false, toInclusive=false) float);
+    method @Deprecated public androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters.Builder setScreenHeightDp(@Dimension(unit=androidx.annotation.Dimension.DP) int);
+    method @Deprecated public androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters.Builder setScreenShape(int);
+    method @Deprecated public androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters.Builder setScreenWidthDp(@Dimension(unit=androidx.annotation.Dimension.DP) int);
+  }
+
+  @Deprecated public final class DimensionBuilders {
+    method @Deprecated public static androidx.wear.tiles.DimensionBuilders.DegreesProp degrees(float);
+    method @Deprecated public static androidx.wear.tiles.DimensionBuilders.DpProp dp(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method @Deprecated public static androidx.wear.tiles.DimensionBuilders.EmProp em(float);
+    method @Deprecated public static androidx.wear.tiles.DimensionBuilders.EmProp em(int);
+    method @Deprecated public static androidx.wear.tiles.DimensionBuilders.ExpandedDimensionProp expand();
+    method @Deprecated public static androidx.wear.tiles.DimensionBuilders.SpProp sp(@Dimension(unit=androidx.annotation.Dimension.SP) float);
+    method @Deprecated public static androidx.wear.tiles.DimensionBuilders.WrappedDimensionProp wrap();
+  }
+
+  @Deprecated public static interface DimensionBuilders.ContainerDimension {
+  }
+
+  @Deprecated public static interface DimensionBuilders.ContainerDimension.Builder {
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ContainerDimension build();
+  }
+
+  @Deprecated public static final class DimensionBuilders.DegreesProp {
+    method @Deprecated public float getValue();
+  }
+
+  @Deprecated public static final class DimensionBuilders.DegreesProp.Builder {
+    ctor @Deprecated public DimensionBuilders.DegreesProp.Builder();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DegreesProp build();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DegreesProp.Builder setValue(float);
+  }
+
+  @Deprecated public static final class DimensionBuilders.DpProp implements androidx.wear.tiles.DimensionBuilders.ContainerDimension androidx.wear.tiles.DimensionBuilders.ImageDimension androidx.wear.tiles.DimensionBuilders.SpacerDimension {
+    method @Deprecated @Dimension(unit=androidx.annotation.Dimension.DP) public float getValue();
+  }
+
+  @Deprecated public static final class DimensionBuilders.DpProp.Builder implements androidx.wear.tiles.DimensionBuilders.ContainerDimension.Builder androidx.wear.tiles.DimensionBuilders.ImageDimension.Builder androidx.wear.tiles.DimensionBuilders.SpacerDimension.Builder {
+    ctor @Deprecated public DimensionBuilders.DpProp.Builder();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DpProp build();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DpProp.Builder setValue(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  }
+
+  @Deprecated public static final class DimensionBuilders.EmProp {
+    method @Deprecated public float getValue();
+  }
+
+  @Deprecated public static final class DimensionBuilders.EmProp.Builder {
+    ctor @Deprecated public DimensionBuilders.EmProp.Builder();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.EmProp build();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.EmProp.Builder setValue(float);
+  }
+
+  @Deprecated public static final class DimensionBuilders.ExpandedDimensionProp implements androidx.wear.tiles.DimensionBuilders.ContainerDimension androidx.wear.tiles.DimensionBuilders.ImageDimension {
+  }
+
+  @Deprecated public static final class DimensionBuilders.ExpandedDimensionProp.Builder implements androidx.wear.tiles.DimensionBuilders.ContainerDimension.Builder androidx.wear.tiles.DimensionBuilders.ImageDimension.Builder {
+    ctor @Deprecated public DimensionBuilders.ExpandedDimensionProp.Builder();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ExpandedDimensionProp build();
+  }
+
+  @Deprecated public static interface DimensionBuilders.ImageDimension {
+  }
+
+  @Deprecated public static interface DimensionBuilders.ImageDimension.Builder {
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ImageDimension build();
+  }
+
+  @Deprecated public static final class DimensionBuilders.ProportionalDimensionProp implements androidx.wear.tiles.DimensionBuilders.ImageDimension {
+    method @Deprecated @IntRange(from=0) public int getAspectRatioHeight();
+    method @Deprecated @IntRange(from=0) public int getAspectRatioWidth();
+  }
+
+  @Deprecated public static final class DimensionBuilders.ProportionalDimensionProp.Builder implements androidx.wear.tiles.DimensionBuilders.ImageDimension.Builder {
+    ctor @Deprecated public DimensionBuilders.ProportionalDimensionProp.Builder();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ProportionalDimensionProp build();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ProportionalDimensionProp.Builder setAspectRatioHeight(@IntRange(from=0) int);
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ProportionalDimensionProp.Builder setAspectRatioWidth(@IntRange(from=0) int);
+  }
+
+  @Deprecated public static final class DimensionBuilders.SpProp {
+    method @Deprecated @Dimension(unit=androidx.annotation.Dimension.SP) public float getValue();
+  }
+
+  @Deprecated public static final class DimensionBuilders.SpProp.Builder {
+    ctor @Deprecated public DimensionBuilders.SpProp.Builder();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.SpProp build();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.SpProp.Builder setValue(@Dimension(unit=androidx.annotation.Dimension.SP) float);
+  }
+
+  @Deprecated public static interface DimensionBuilders.SpacerDimension {
+  }
+
+  @Deprecated public static interface DimensionBuilders.SpacerDimension.Builder {
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.SpacerDimension build();
+  }
+
+  @Deprecated public static final class DimensionBuilders.WrappedDimensionProp implements androidx.wear.tiles.DimensionBuilders.ContainerDimension {
+  }
+
+  @Deprecated public static final class DimensionBuilders.WrappedDimensionProp.Builder implements androidx.wear.tiles.DimensionBuilders.ContainerDimension.Builder {
+    ctor @Deprecated public DimensionBuilders.WrappedDimensionProp.Builder();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.WrappedDimensionProp build();
+  }
+
+  public final class EventBuilders {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class EventBuilders.TileAddEvent {
+    method public int getTileId();
+  }
+
+  public static final class EventBuilders.TileAddEvent.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public EventBuilders.TileAddEvent.Builder();
+    method public androidx.wear.tiles.EventBuilders.TileAddEvent build();
+    method public androidx.wear.tiles.EventBuilders.TileAddEvent.Builder setTileId(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class EventBuilders.TileEnterEvent {
+    method public int getTileId();
+  }
+
+  public static final class EventBuilders.TileEnterEvent.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public EventBuilders.TileEnterEvent.Builder();
+    method public androidx.wear.tiles.EventBuilders.TileEnterEvent build();
+    method public androidx.wear.tiles.EventBuilders.TileEnterEvent.Builder setTileId(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public static final class EventBuilders.TileInteractionEvent {
+    method public int getEventType();
+    method public int getTileId();
+    method public java.time.Instant getTimestamp();
+    field public static final int ENTER = 1; // 0x1
+    field public static final int LEAVE = 2; // 0x2
+    field public static final int UNKNOWN = 0; // 0x0
+  }
+
+  public static final class EventBuilders.TileInteractionEvent.Builder {
+    ctor public EventBuilders.TileInteractionEvent.Builder(int, int);
+    method public androidx.wear.tiles.EventBuilders.TileInteractionEvent build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=400) public androidx.wear.tiles.EventBuilders.TileInteractionEvent.Builder setTimestamp(java.time.Instant);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class EventBuilders.TileLeaveEvent {
+    method public int getTileId();
+  }
+
+  public static final class EventBuilders.TileLeaveEvent.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public EventBuilders.TileLeaveEvent.Builder();
+    method public androidx.wear.tiles.EventBuilders.TileLeaveEvent build();
+    method public androidx.wear.tiles.EventBuilders.TileLeaveEvent.Builder setTileId(int);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class EventBuilders.TileRemoveEvent {
+    method public int getTileId();
+  }
+
+  public static final class EventBuilders.TileRemoveEvent.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public EventBuilders.TileRemoveEvent.Builder();
+    method public androidx.wear.tiles.EventBuilders.TileRemoveEvent build();
+    method public androidx.wear.tiles.EventBuilders.TileRemoveEvent.Builder setTileId(int);
+  }
+
+  @Deprecated public final class LayoutElementBuilders {
+    field @Deprecated public static final int ARC_ANCHOR_CENTER = 2; // 0x2
+    field @Deprecated public static final int ARC_ANCHOR_END = 3; // 0x3
+    field @Deprecated public static final int ARC_ANCHOR_START = 1; // 0x1
+    field @Deprecated public static final int ARC_ANCHOR_UNDEFINED = 0; // 0x0
+    field @Deprecated public static final int CONTENT_SCALE_MODE_CROP = 2; // 0x2
+    field @Deprecated public static final int CONTENT_SCALE_MODE_FILL_BOUNDS = 3; // 0x3
+    field @Deprecated public static final int CONTENT_SCALE_MODE_FIT = 1; // 0x1
+    field @Deprecated public static final int CONTENT_SCALE_MODE_UNDEFINED = 0; // 0x0
+    field @Deprecated public static final int FONT_VARIANT_BODY = 2; // 0x2
+    field @Deprecated public static final int FONT_VARIANT_TITLE = 1; // 0x1
+    field @Deprecated public static final int FONT_VARIANT_UNDEFINED = 0; // 0x0
+    field @Deprecated public static final int FONT_WEIGHT_BOLD = 700; // 0x2bc
+    field @Deprecated @SuppressCompatibility @androidx.wear.tiles.TilesExperimental public static final int FONT_WEIGHT_MEDIUM = 500; // 0x1f4
+    field @Deprecated public static final int FONT_WEIGHT_NORMAL = 400; // 0x190
+    field @Deprecated public static final int FONT_WEIGHT_UNDEFINED = 0; // 0x0
+    field @Deprecated public static final int HORIZONTAL_ALIGN_CENTER = 2; // 0x2
+    field @Deprecated public static final int HORIZONTAL_ALIGN_END = 5; // 0x5
+    field @Deprecated public static final int HORIZONTAL_ALIGN_LEFT = 1; // 0x1
+    field @Deprecated public static final int HORIZONTAL_ALIGN_RIGHT = 3; // 0x3
+    field @Deprecated public static final int HORIZONTAL_ALIGN_START = 4; // 0x4
+    field @Deprecated public static final int HORIZONTAL_ALIGN_UNDEFINED = 0; // 0x0
+    field @Deprecated public static final int SPAN_VERTICAL_ALIGN_BOTTOM = 1; // 0x1
+    field @Deprecated public static final int SPAN_VERTICAL_ALIGN_TEXT_BASELINE = 2; // 0x2
+    field @Deprecated public static final int SPAN_VERTICAL_ALIGN_UNDEFINED = 0; // 0x0
+    field @Deprecated public static final int TEXT_ALIGN_CENTER = 2; // 0x2
+    field @Deprecated public static final int TEXT_ALIGN_END = 3; // 0x3
+    field @Deprecated public static final int TEXT_ALIGN_START = 1; // 0x1
+    field @Deprecated public static final int TEXT_ALIGN_UNDEFINED = 0; // 0x0
+    field @Deprecated public static final int TEXT_OVERFLOW_ELLIPSIZE_END = 2; // 0x2
+    field @Deprecated public static final int TEXT_OVERFLOW_TRUNCATE = 1; // 0x1
+    field @Deprecated public static final int TEXT_OVERFLOW_UNDEFINED = 0; // 0x0
+    field @Deprecated public static final int VERTICAL_ALIGN_BOTTOM = 3; // 0x3
+    field @Deprecated public static final int VERTICAL_ALIGN_CENTER = 2; // 0x2
+    field @Deprecated public static final int VERTICAL_ALIGN_TOP = 1; // 0x1
+    field @Deprecated public static final int VERTICAL_ALIGN_UNDEFINED = 0; // 0x0
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Arc implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DegreesProp? getAnchorAngle();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcAnchorTypeProp? getAnchorType();
+    method @Deprecated public java.util.List<androidx.wear.tiles.LayoutElementBuilders.ArcLayoutElement!> getContents();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers? getModifiers();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.VerticalAlignmentProp? getVerticalAlign();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Arc.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public LayoutElementBuilders.Arc.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Arc.Builder addContent(androidx.wear.tiles.LayoutElementBuilders.ArcLayoutElement);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Arc build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Arc.Builder setAnchorAngle(androidx.wear.tiles.DimensionBuilders.DegreesProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Arc.Builder setAnchorType(androidx.wear.tiles.LayoutElementBuilders.ArcAnchorTypeProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Arc.Builder setAnchorType(int);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Arc.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.Modifiers);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Arc.Builder setVerticalAlign(androidx.wear.tiles.LayoutElementBuilders.VerticalAlignmentProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Arc.Builder setVerticalAlign(int);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.ArcAdapter implements androidx.wear.tiles.LayoutElementBuilders.ArcLayoutElement {
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getContent();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.BoolProp? getRotateContents();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.ArcAdapter.Builder implements androidx.wear.tiles.LayoutElementBuilders.ArcLayoutElement.Builder {
+    ctor @Deprecated public LayoutElementBuilders.ArcAdapter.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcAdapter build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcAdapter.Builder setContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcAdapter.Builder setRotateContents(androidx.wear.tiles.TypeBuilders.BoolProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcAdapter.Builder setRotateContents(boolean);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.ArcAnchorTypeProp {
+    method @Deprecated public int getValue();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.ArcAnchorTypeProp.Builder {
+    ctor @Deprecated public LayoutElementBuilders.ArcAnchorTypeProp.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcAnchorTypeProp build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcAnchorTypeProp.Builder setValue(int);
+  }
+
+  @Deprecated public static interface LayoutElementBuilders.ArcLayoutElement {
+  }
+
+  @Deprecated public static interface LayoutElementBuilders.ArcLayoutElement.Builder {
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcLayoutElement build();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.ArcLine implements androidx.wear.tiles.LayoutElementBuilders.ArcLayoutElement {
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp? getColor();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DegreesProp? getLength();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.ArcModifiers? getModifiers();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DpProp? getThickness();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.ArcLine.Builder implements androidx.wear.tiles.LayoutElementBuilders.ArcLayoutElement.Builder {
+    ctor @Deprecated public LayoutElementBuilders.ArcLine.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcLine build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcLine.Builder setColor(androidx.wear.tiles.ColorBuilders.ColorProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcLine.Builder setLength(androidx.wear.tiles.DimensionBuilders.DegreesProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcLine.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.ArcModifiers);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcLine.Builder setThickness(androidx.wear.tiles.DimensionBuilders.DpProp);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.ArcSpacer implements androidx.wear.tiles.LayoutElementBuilders.ArcLayoutElement {
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DegreesProp? getLength();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.ArcModifiers? getModifiers();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DpProp? getThickness();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.ArcSpacer.Builder implements androidx.wear.tiles.LayoutElementBuilders.ArcLayoutElement.Builder {
+    ctor @Deprecated public LayoutElementBuilders.ArcSpacer.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcSpacer build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcSpacer.Builder setLength(androidx.wear.tiles.DimensionBuilders.DegreesProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcSpacer.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.ArcModifiers);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcSpacer.Builder setThickness(androidx.wear.tiles.DimensionBuilders.DpProp);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.ArcText implements androidx.wear.tiles.LayoutElementBuilders.ArcLayoutElement {
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontStyle? getFontStyle();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.ArcModifiers? getModifiers();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.StringProp? getText();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.ArcText.Builder implements androidx.wear.tiles.LayoutElementBuilders.ArcLayoutElement.Builder {
+    ctor @Deprecated public LayoutElementBuilders.ArcText.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcText build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcText.Builder setFontStyle(androidx.wear.tiles.LayoutElementBuilders.FontStyle);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcText.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.ArcModifiers);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcText.Builder setText(androidx.wear.tiles.TypeBuilders.StringProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ArcText.Builder setText(String);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Box implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public java.util.List<androidx.wear.tiles.LayoutElementBuilders.LayoutElement!> getContents();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ContainerDimension? getHeight();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.HorizontalAlignmentProp? getHorizontalAlignment();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers? getModifiers();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.VerticalAlignmentProp? getVerticalAlignment();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ContainerDimension? getWidth();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Box.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public LayoutElementBuilders.Box.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Box.Builder addContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Box build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Box.Builder setHeight(androidx.wear.tiles.DimensionBuilders.ContainerDimension);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Box.Builder setHorizontalAlignment(androidx.wear.tiles.LayoutElementBuilders.HorizontalAlignmentProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Box.Builder setHorizontalAlignment(int);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Box.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.Modifiers);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Box.Builder setVerticalAlignment(androidx.wear.tiles.LayoutElementBuilders.VerticalAlignmentProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Box.Builder setVerticalAlignment(int);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Box.Builder setWidth(androidx.wear.tiles.DimensionBuilders.ContainerDimension);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.ColorFilter {
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp? getTint();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.ColorFilter.Builder {
+    ctor @Deprecated public LayoutElementBuilders.ColorFilter.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ColorFilter build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ColorFilter.Builder setTint(androidx.wear.tiles.ColorBuilders.ColorProp);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Column implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public java.util.List<androidx.wear.tiles.LayoutElementBuilders.LayoutElement!> getContents();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ContainerDimension? getHeight();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.HorizontalAlignmentProp? getHorizontalAlignment();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers? getModifiers();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ContainerDimension? getWidth();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Column.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public LayoutElementBuilders.Column.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Column.Builder addContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Column build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Column.Builder setHeight(androidx.wear.tiles.DimensionBuilders.ContainerDimension);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Column.Builder setHorizontalAlignment(androidx.wear.tiles.LayoutElementBuilders.HorizontalAlignmentProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Column.Builder setHorizontalAlignment(int);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Column.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.Modifiers);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Column.Builder setWidth(androidx.wear.tiles.DimensionBuilders.ContainerDimension);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.ContentScaleModeProp {
+    method @Deprecated public int getValue();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.ContentScaleModeProp.Builder {
+    ctor @Deprecated public LayoutElementBuilders.ContentScaleModeProp.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ContentScaleModeProp build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ContentScaleModeProp.Builder setValue(int);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.FontStyle {
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp? getColor();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.BoolProp? getItalic();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.EmProp? getLetterSpacing();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.SpProp? getSize();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.BoolProp? getUnderline();
+    method @Deprecated @SuppressCompatibility @androidx.wear.tiles.TilesExperimental public androidx.wear.tiles.LayoutElementBuilders.FontVariantProp? getVariant();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontWeightProp? getWeight();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.FontStyle.Builder {
+    ctor @Deprecated public LayoutElementBuilders.FontStyle.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontStyle build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder setColor(androidx.wear.tiles.ColorBuilders.ColorProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder setItalic(androidx.wear.tiles.TypeBuilders.BoolProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder setItalic(boolean);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder setLetterSpacing(androidx.wear.tiles.DimensionBuilders.EmProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder setSize(androidx.wear.tiles.DimensionBuilders.SpProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder setUnderline(androidx.wear.tiles.TypeBuilders.BoolProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder setUnderline(boolean);
+    method @Deprecated @SuppressCompatibility @androidx.wear.tiles.TilesExperimental public androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder setVariant(androidx.wear.tiles.LayoutElementBuilders.FontVariantProp);
+    method @Deprecated @SuppressCompatibility @androidx.wear.tiles.TilesExperimental public androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder setVariant(int);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder setWeight(androidx.wear.tiles.LayoutElementBuilders.FontWeightProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder setWeight(int);
+  }
+
+  @Deprecated public static class LayoutElementBuilders.FontStyles {
+    method @Deprecated public static androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder body1(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder body2(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder button(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder caption1(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder caption2(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder display1(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder display2(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder display3(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder title1(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder title2(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public static androidx.wear.tiles.LayoutElementBuilders.FontStyle.Builder title3(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+  }
+
+  @Deprecated @SuppressCompatibility @androidx.wear.tiles.TilesExperimental public static final class LayoutElementBuilders.FontVariantProp {
+    method @Deprecated public int getValue();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.FontVariantProp.Builder {
+    ctor @Deprecated public LayoutElementBuilders.FontVariantProp.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontVariantProp build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontVariantProp.Builder setValue(int);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.FontWeightProp {
+    method @Deprecated public int getValue();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.FontWeightProp.Builder {
+    ctor @Deprecated public LayoutElementBuilders.FontWeightProp.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontWeightProp build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontWeightProp.Builder setValue(int);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.HorizontalAlignmentProp {
+    method @Deprecated public int getValue();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.HorizontalAlignmentProp.Builder {
+    ctor @Deprecated public LayoutElementBuilders.HorizontalAlignmentProp.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.HorizontalAlignmentProp build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.HorizontalAlignmentProp.Builder setValue(int);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Image implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ColorFilter? getColorFilter();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.ContentScaleModeProp? getContentScaleMode();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ImageDimension? getHeight();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers? getModifiers();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.StringProp? getResourceId();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ImageDimension? getWidth();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Image.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public LayoutElementBuilders.Image.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Image build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Image.Builder setColorFilter(androidx.wear.tiles.LayoutElementBuilders.ColorFilter);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Image.Builder setContentScaleMode(androidx.wear.tiles.LayoutElementBuilders.ContentScaleModeProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Image.Builder setContentScaleMode(int);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Image.Builder setHeight(androidx.wear.tiles.DimensionBuilders.ImageDimension);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Image.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.Modifiers);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Image.Builder setResourceId(androidx.wear.tiles.TypeBuilders.StringProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Image.Builder setResourceId(String);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Image.Builder setWidth(androidx.wear.tiles.DimensionBuilders.ImageDimension);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Layout {
+    method @Deprecated @SuppressCompatibility @androidx.wear.tiles.TilesExperimental public static androidx.wear.tiles.LayoutElementBuilders.Layout? fromByteArray(byte[]);
+    method @Deprecated public static androidx.wear.tiles.LayoutElementBuilders.Layout fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getRoot();
+    method @Deprecated @SuppressCompatibility @androidx.wear.tiles.TilesExperimental public byte[] toByteArray();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Layout.Builder {
+    ctor @Deprecated public LayoutElementBuilders.Layout.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Layout build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Layout.Builder setRoot(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+  }
+
+  @Deprecated public static interface LayoutElementBuilders.LayoutElement {
+  }
+
+  @Deprecated public static interface LayoutElementBuilders.LayoutElement.Builder {
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.LayoutElement build();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Row implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public java.util.List<androidx.wear.tiles.LayoutElementBuilders.LayoutElement!> getContents();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ContainerDimension? getHeight();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers? getModifiers();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.VerticalAlignmentProp? getVerticalAlignment();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.ContainerDimension? getWidth();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Row.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public LayoutElementBuilders.Row.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Row.Builder addContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Row build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Row.Builder setHeight(androidx.wear.tiles.DimensionBuilders.ContainerDimension);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Row.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.Modifiers);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Row.Builder setVerticalAlignment(androidx.wear.tiles.LayoutElementBuilders.VerticalAlignmentProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Row.Builder setVerticalAlignment(int);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Row.Builder setWidth(androidx.wear.tiles.DimensionBuilders.ContainerDimension);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Spacer implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.SpacerDimension? getHeight();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers? getModifiers();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.SpacerDimension? getWidth();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Spacer.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public LayoutElementBuilders.Spacer.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Spacer build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Spacer.Builder setHeight(androidx.wear.tiles.DimensionBuilders.SpacerDimension);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Spacer.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.Modifiers);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Spacer.Builder setWidth(androidx.wear.tiles.DimensionBuilders.SpacerDimension);
+  }
+
+  @Deprecated public static interface LayoutElementBuilders.Span {
+  }
+
+  @Deprecated public static interface LayoutElementBuilders.Span.Builder {
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Span build();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.SpanImage implements androidx.wear.tiles.LayoutElementBuilders.Span {
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanVerticalAlignmentProp? getAlignment();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DpProp? getHeight();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.SpanModifiers? getModifiers();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.StringProp? getResourceId();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DpProp? getWidth();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.SpanImage.Builder implements androidx.wear.tiles.LayoutElementBuilders.Span.Builder {
+    ctor @Deprecated public LayoutElementBuilders.SpanImage.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanImage build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanImage.Builder setAlignment(androidx.wear.tiles.LayoutElementBuilders.SpanVerticalAlignmentProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanImage.Builder setAlignment(int);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanImage.Builder setHeight(androidx.wear.tiles.DimensionBuilders.DpProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanImage.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.SpanModifiers);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanImage.Builder setResourceId(androidx.wear.tiles.TypeBuilders.StringProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanImage.Builder setResourceId(String);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanImage.Builder setWidth(androidx.wear.tiles.DimensionBuilders.DpProp);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.SpanText implements androidx.wear.tiles.LayoutElementBuilders.Span {
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontStyle? getFontStyle();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.SpanModifiers? getModifiers();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.StringProp? getText();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.SpanText.Builder implements androidx.wear.tiles.LayoutElementBuilders.Span.Builder {
+    ctor @Deprecated public LayoutElementBuilders.SpanText.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanText build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanText.Builder setFontStyle(androidx.wear.tiles.LayoutElementBuilders.FontStyle);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanText.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.SpanModifiers);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanText.Builder setText(androidx.wear.tiles.TypeBuilders.StringProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanText.Builder setText(String);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.SpanVerticalAlignmentProp {
+    method @Deprecated public int getValue();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.SpanVerticalAlignmentProp.Builder {
+    ctor @Deprecated public LayoutElementBuilders.SpanVerticalAlignmentProp.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanVerticalAlignmentProp build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.SpanVerticalAlignmentProp.Builder setValue(int);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Spannable implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.SpProp? getLineHeight();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.Int32Prop? getMaxLines();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers? getModifiers();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.HorizontalAlignmentProp? getMultilineAlignment();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.TextOverflowProp? getOverflow();
+    method @Deprecated public java.util.List<androidx.wear.tiles.LayoutElementBuilders.Span!> getSpans();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Spannable.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public LayoutElementBuilders.Spannable.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Spannable.Builder addSpan(androidx.wear.tiles.LayoutElementBuilders.Span);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Spannable build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Spannable.Builder setLineHeight(androidx.wear.tiles.DimensionBuilders.SpProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Spannable.Builder setMaxLines(androidx.wear.tiles.TypeBuilders.Int32Prop);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Spannable.Builder setMaxLines(@IntRange(from=1) int);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Spannable.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.Modifiers);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Spannable.Builder setMultilineAlignment(androidx.wear.tiles.LayoutElementBuilders.HorizontalAlignmentProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Spannable.Builder setMultilineAlignment(int);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Spannable.Builder setOverflow(androidx.wear.tiles.LayoutElementBuilders.TextOverflowProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Spannable.Builder setOverflow(int);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Text implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.FontStyle? getFontStyle();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.SpProp? getLineHeight();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.Int32Prop? getMaxLines();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers? getModifiers();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.TextAlignmentProp? getMultilineAlignment();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.TextOverflowProp? getOverflow();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.StringProp? getText();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.Text.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
+    ctor @Deprecated public LayoutElementBuilders.Text.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Text build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Text.Builder setFontStyle(androidx.wear.tiles.LayoutElementBuilders.FontStyle);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Text.Builder setLineHeight(androidx.wear.tiles.DimensionBuilders.SpProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Text.Builder setMaxLines(androidx.wear.tiles.TypeBuilders.Int32Prop);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Text.Builder setMaxLines(@IntRange(from=1) int);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Text.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.Modifiers);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Text.Builder setMultilineAlignment(androidx.wear.tiles.LayoutElementBuilders.TextAlignmentProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Text.Builder setMultilineAlignment(int);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Text.Builder setOverflow(androidx.wear.tiles.LayoutElementBuilders.TextOverflowProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Text.Builder setOverflow(int);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Text.Builder setText(androidx.wear.tiles.TypeBuilders.StringProp);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Text.Builder setText(String);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.TextAlignmentProp {
+    method @Deprecated public int getValue();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.TextAlignmentProp.Builder {
+    ctor @Deprecated public LayoutElementBuilders.TextAlignmentProp.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.TextAlignmentProp build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.TextAlignmentProp.Builder setValue(int);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.TextOverflowProp {
+    method @Deprecated public int getValue();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.TextOverflowProp.Builder {
+    ctor @Deprecated public LayoutElementBuilders.TextOverflowProp.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.TextOverflowProp build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.TextOverflowProp.Builder setValue(int);
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.VerticalAlignmentProp {
+    method @Deprecated public int getValue();
+  }
+
+  @Deprecated public static final class LayoutElementBuilders.VerticalAlignmentProp.Builder {
+    ctor @Deprecated public LayoutElementBuilders.VerticalAlignmentProp.Builder();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.VerticalAlignmentProp build();
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.VerticalAlignmentProp.Builder setValue(int);
+  }
+
+  @Deprecated public final class ModifiersBuilders {
+  }
+
+  @Deprecated public static final class ModifiersBuilders.ArcModifiers {
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Clickable? getClickable();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Semantics? getSemantics();
+  }
+
+  @Deprecated public static final class ModifiersBuilders.ArcModifiers.Builder {
+    ctor @Deprecated public ModifiersBuilders.ArcModifiers.Builder();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.ArcModifiers build();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.ArcModifiers.Builder setClickable(androidx.wear.tiles.ModifiersBuilders.Clickable);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.ArcModifiers.Builder setSemantics(androidx.wear.tiles.ModifiersBuilders.Semantics);
+  }
+
+  @Deprecated public static final class ModifiersBuilders.Background {
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp? getColor();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Corner? getCorner();
+  }
+
+  @Deprecated public static final class ModifiersBuilders.Background.Builder {
+    ctor @Deprecated public ModifiersBuilders.Background.Builder();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Background build();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Background.Builder setColor(androidx.wear.tiles.ColorBuilders.ColorProp);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Background.Builder setCorner(androidx.wear.tiles.ModifiersBuilders.Corner);
+  }
+
+  @Deprecated public static final class ModifiersBuilders.Border {
+    method @Deprecated public androidx.wear.tiles.ColorBuilders.ColorProp? getColor();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DpProp? getWidth();
+  }
+
+  @Deprecated public static final class ModifiersBuilders.Border.Builder {
+    ctor @Deprecated public ModifiersBuilders.Border.Builder();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Border build();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Border.Builder setColor(androidx.wear.tiles.ColorBuilders.ColorProp);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Border.Builder setWidth(androidx.wear.tiles.DimensionBuilders.DpProp);
+  }
+
+  @Deprecated public static final class ModifiersBuilders.Clickable {
+    method @Deprecated public String getId();
+    method @Deprecated public androidx.wear.tiles.ActionBuilders.Action? getOnClick();
+  }
+
+  @Deprecated public static final class ModifiersBuilders.Clickable.Builder {
+    ctor @Deprecated public ModifiersBuilders.Clickable.Builder();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Clickable build();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Clickable.Builder setId(String);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Clickable.Builder setOnClick(androidx.wear.tiles.ActionBuilders.Action);
+  }
+
+  @Deprecated public static final class ModifiersBuilders.Corner {
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DpProp? getRadius();
+  }
+
+  @Deprecated public static final class ModifiersBuilders.Corner.Builder {
+    ctor @Deprecated public ModifiersBuilders.Corner.Builder();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Corner build();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Corner.Builder setRadius(androidx.wear.tiles.DimensionBuilders.DpProp);
+  }
+
+  @Deprecated public static final class ModifiersBuilders.ElementMetadata {
+    method @Deprecated public byte[] getTagData();
+  }
+
+  @Deprecated public static final class ModifiersBuilders.ElementMetadata.Builder {
+    ctor @Deprecated public ModifiersBuilders.ElementMetadata.Builder();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.ElementMetadata build();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.ElementMetadata.Builder setTagData(byte[]);
+  }
+
+  @Deprecated public static final class ModifiersBuilders.Modifiers {
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Background? getBackground();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Border? getBorder();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Clickable? getClickable();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.ElementMetadata? getMetadata();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Padding? getPadding();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Semantics? getSemantics();
+  }
+
+  @Deprecated public static final class ModifiersBuilders.Modifiers.Builder {
+    ctor @Deprecated public ModifiersBuilders.Modifiers.Builder();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers build();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers.Builder setBackground(androidx.wear.tiles.ModifiersBuilders.Background);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers.Builder setBorder(androidx.wear.tiles.ModifiersBuilders.Border);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers.Builder setClickable(androidx.wear.tiles.ModifiersBuilders.Clickable);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers.Builder setMetadata(androidx.wear.tiles.ModifiersBuilders.ElementMetadata);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers.Builder setPadding(androidx.wear.tiles.ModifiersBuilders.Padding);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Modifiers.Builder setSemantics(androidx.wear.tiles.ModifiersBuilders.Semantics);
+  }
+
+  @Deprecated public static final class ModifiersBuilders.Padding {
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DpProp? getBottom();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DpProp? getEnd();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.BoolProp? getRtlAware();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DpProp? getStart();
+    method @Deprecated public androidx.wear.tiles.DimensionBuilders.DpProp? getTop();
+  }
+
+  @Deprecated public static final class ModifiersBuilders.Padding.Builder {
+    ctor @Deprecated public ModifiersBuilders.Padding.Builder();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Padding build();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Padding.Builder setAll(androidx.wear.tiles.DimensionBuilders.DpProp);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Padding.Builder setBottom(androidx.wear.tiles.DimensionBuilders.DpProp);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Padding.Builder setEnd(androidx.wear.tiles.DimensionBuilders.DpProp);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Padding.Builder setRtlAware(androidx.wear.tiles.TypeBuilders.BoolProp);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Padding.Builder setRtlAware(boolean);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Padding.Builder setStart(androidx.wear.tiles.DimensionBuilders.DpProp);
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Padding.Builder setTop(androidx.wear.tiles.DimensionBuilders.DpProp);
+  }
+
+  @Deprecated public static final class ModifiersBuilders.Semantics {
+    method @Deprecated public String getContentDescription();
+  }
+
+  @Deprecated public static final class ModifiersBuilders.Semantics.Builder {
+    ctor @Deprecated public ModifiersBuilders.Semantics.Builder();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Semantics build();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Semantics.Builder setContentDescription(String);
+  }
+
+  @Deprecated public static final class ModifiersBuilders.SpanModifiers {
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.Clickable? getClickable();
+  }
+
+  @Deprecated public static final class ModifiersBuilders.SpanModifiers.Builder {
+    ctor @Deprecated public ModifiersBuilders.SpanModifiers.Builder();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.SpanModifiers build();
+    method @Deprecated public androidx.wear.tiles.ModifiersBuilders.SpanModifiers.Builder setClickable(androidx.wear.tiles.ModifiersBuilders.Clickable);
+  }
+
+  public final class RequestBuilders {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class RequestBuilders.ResourcesRequest {
+    method public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters getDeviceConfiguration();
+    method @Deprecated public androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters? getDeviceParameters();
+    method public java.util.List<java.lang.String!> getResourceIds();
+    method public int getTileId();
+    method public String getVersion();
+  }
+
+  public static final class RequestBuilders.ResourcesRequest.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public RequestBuilders.ResourcesRequest.Builder();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.tiles.RequestBuilders.ResourcesRequest.Builder addResourceId(String);
+    method public androidx.wear.tiles.RequestBuilders.ResourcesRequest build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.tiles.RequestBuilders.ResourcesRequest.Builder setDeviceConfiguration(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public androidx.wear.tiles.RequestBuilders.ResourcesRequest.Builder setDeviceParameters(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.tiles.RequestBuilders.ResourcesRequest.Builder setTileId(int);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.tiles.RequestBuilders.ResourcesRequest.Builder setVersion(String);
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class RequestBuilders.TileRequest {
+    method public androidx.wear.protolayout.StateBuilders.State getCurrentState();
+    method public androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters getDeviceConfiguration();
+    method @Deprecated public androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters? getDeviceParameters();
+    method @Deprecated public androidx.wear.tiles.StateBuilders.State? getState();
+    method public int getTileId();
+  }
+
+  public static final class RequestBuilders.TileRequest.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public RequestBuilders.TileRequest.Builder();
+    method public androidx.wear.tiles.RequestBuilders.TileRequest build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.tiles.RequestBuilders.TileRequest.Builder setCurrentState(androidx.wear.protolayout.StateBuilders.State);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.tiles.RequestBuilders.TileRequest.Builder setDeviceConfiguration(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public androidx.wear.tiles.RequestBuilders.TileRequest.Builder setDeviceParameters(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
+    method @Deprecated public androidx.wear.tiles.RequestBuilders.TileRequest.Builder setState(androidx.wear.tiles.StateBuilders.State);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.tiles.RequestBuilders.TileRequest.Builder setTileId(int);
+  }
+
+  @Deprecated public final class ResourceBuilders {
+    field @Deprecated public static final int IMAGE_FORMAT_RGB_565 = 1; // 0x1
+    field @Deprecated public static final int IMAGE_FORMAT_UNDEFINED = 0; // 0x0
+  }
+
+  @Deprecated public static final class ResourceBuilders.AndroidImageResourceByResId {
+    method @Deprecated @DrawableRes public int getResourceId();
+  }
+
+  @Deprecated public static final class ResourceBuilders.AndroidImageResourceByResId.Builder {
+    ctor @Deprecated public ResourceBuilders.AndroidImageResourceByResId.Builder();
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.AndroidImageResourceByResId build();
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.AndroidImageResourceByResId.Builder setResourceId(@DrawableRes int);
+  }
+
+  @Deprecated public static final class ResourceBuilders.ImageResource {
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.AndroidImageResourceByResId? getAndroidResourceByResId();
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.InlineImageResource? getInlineResource();
+  }
+
+  @Deprecated public static final class ResourceBuilders.ImageResource.Builder {
+    ctor @Deprecated public ResourceBuilders.ImageResource.Builder();
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.ImageResource build();
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.ImageResource.Builder setAndroidResourceByResId(androidx.wear.tiles.ResourceBuilders.AndroidImageResourceByResId);
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.ImageResource.Builder setInlineResource(androidx.wear.tiles.ResourceBuilders.InlineImageResource);
+  }
+
+  @Deprecated public static final class ResourceBuilders.InlineImageResource {
+    method @Deprecated public byte[] getData();
+    method @Deprecated public int getFormat();
+    method @Deprecated @Dimension(unit=androidx.annotation.Dimension.PX) public int getHeightPx();
+    method @Deprecated @Dimension(unit=androidx.annotation.Dimension.PX) public int getWidthPx();
+  }
+
+  @Deprecated public static final class ResourceBuilders.InlineImageResource.Builder {
+    ctor @Deprecated public ResourceBuilders.InlineImageResource.Builder();
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.InlineImageResource build();
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.InlineImageResource.Builder setData(byte[]);
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.InlineImageResource.Builder setFormat(int);
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.InlineImageResource.Builder setHeightPx(@Dimension(unit=androidx.annotation.Dimension.PX) int);
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.InlineImageResource.Builder setWidthPx(@Dimension(unit=androidx.annotation.Dimension.PX) int);
+  }
+
+  @Deprecated public static final class ResourceBuilders.Resources {
+    method @Deprecated @SuppressCompatibility @androidx.wear.tiles.TilesExperimental public static androidx.wear.tiles.ResourceBuilders.Resources? fromByteArray(byte[]);
+    method @Deprecated public java.util.Map<java.lang.String!,androidx.wear.tiles.ResourceBuilders.ImageResource!> getIdToImageMapping();
+    method @Deprecated public String getVersion();
+    method @Deprecated @SuppressCompatibility @androidx.wear.tiles.TilesExperimental public byte[] toByteArray();
+  }
+
+  @Deprecated public static final class ResourceBuilders.Resources.Builder {
+    ctor @Deprecated public ResourceBuilders.Resources.Builder();
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.Resources.Builder addIdToImageMapping(String, androidx.wear.tiles.ResourceBuilders.ImageResource);
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.Resources build();
+    method @Deprecated public androidx.wear.tiles.ResourceBuilders.Resources.Builder setVersion(String);
+  }
+
+  @Deprecated public final class StateBuilders {
+  }
+
+  @Deprecated public static final class StateBuilders.State {
+    method @Deprecated public String getLastClickableId();
+  }
+
+  @Deprecated public static final class StateBuilders.State.Builder {
+    ctor @Deprecated public StateBuilders.State.Builder();
+    method @Deprecated public androidx.wear.tiles.StateBuilders.State build();
+  }
+
+  public final class TileBuilders {
+  }
+
+  @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public static final class TileBuilders.Tile {
+    method public long getFreshnessIntervalMillis();
+    method public String getResourcesVersion();
+    method public androidx.wear.protolayout.StateBuilders.State? getState();
+    method public androidx.wear.protolayout.TimelineBuilders.Timeline? getTileTimeline();
+    method @Deprecated public androidx.wear.tiles.TimelineBuilders.Timeline? getTimeline();
+  }
+
+  public static final class TileBuilders.Tile.Builder {
+    ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public TileBuilders.Tile.Builder();
+    method public androidx.wear.tiles.TileBuilders.Tile build();
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.tiles.TileBuilders.Tile.Builder setFreshnessIntervalMillis(long);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.tiles.TileBuilders.Tile.Builder setResourcesVersion(String);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.tiles.TileBuilders.Tile.Builder setState(androidx.wear.protolayout.StateBuilders.State);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=0) public androidx.wear.tiles.TileBuilders.Tile.Builder setTileTimeline(androidx.wear.protolayout.TimelineBuilders.Timeline);
+    method @Deprecated public androidx.wear.tiles.TileBuilders.Tile.Builder setTimeline(androidx.wear.tiles.TimelineBuilders.Timeline);
+  }
+
+  public abstract class TileService extends android.app.Service {
+    ctor public TileService();
+    method public static com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.wear.tiles.ActiveTileIdentifier!>!> getActiveTilesAsync(android.content.Context, java.util.concurrent.Executor);
+    method public static androidx.wear.tiles.TileUpdateRequester getUpdater(android.content.Context);
+    method public android.os.IBinder? onBind(android.content.Intent);
+    method @Deprecated @MainThread protected com.google.common.util.concurrent.ListenableFuture<androidx.wear.tiles.ResourceBuilders.Resources!> onResourcesRequest(androidx.wear.tiles.RequestBuilders.ResourcesRequest);
+    method @MainThread protected void onTileAddEvent(androidx.wear.tiles.EventBuilders.TileAddEvent);
+    method @MainThread protected void onTileEnterEvent(androidx.wear.tiles.EventBuilders.TileEnterEvent);
+    method @MainThread protected void onTileLeaveEvent(androidx.wear.tiles.EventBuilders.TileLeaveEvent);
+    method @MainThread protected void onTileRemoveEvent(androidx.wear.tiles.EventBuilders.TileRemoveEvent);
+    method @MainThread protected abstract com.google.common.util.concurrent.ListenableFuture<androidx.wear.tiles.TileBuilders.Tile!> onTileRequest(androidx.wear.tiles.RequestBuilders.TileRequest);
+    method @MainThread protected com.google.common.util.concurrent.ListenableFuture<androidx.wear.protolayout.ResourceBuilders.Resources!> onTileResourcesRequest(androidx.wear.tiles.RequestBuilders.ResourcesRequest);
+    field public static final String ACTION_BIND_TILE_PROVIDER = "androidx.wear.tiles.action.BIND_TILE_PROVIDER";
+    field public static final String EXTRA_CLICKABLE_ID = "androidx.wear.tiles.extra.CLICKABLE_ID";
+    field public static final String METADATA_PREVIEW_KEY = "androidx.wear.tiles.PREVIEW";
+  }
+
+  public interface TileUpdateRequester {
+    method public void requestUpdate(Class<? extends androidx.wear.tiles.TileService!>);
+  }
+
+  @SuppressCompatibility @RequiresOptIn(level=androidx.annotation.RequiresOptIn.Level.ERROR) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD}) public @interface TilesExperimental {
+  }
+
+  @Deprecated public final class TimelineBuilders {
+  }
+
+  @Deprecated public static final class TimelineBuilders.TimeInterval {
+    method @Deprecated public long getEndMillis();
+    method @Deprecated public long getStartMillis();
+  }
+
+  @Deprecated public static final class TimelineBuilders.TimeInterval.Builder {
+    ctor @Deprecated public TimelineBuilders.TimeInterval.Builder();
+    method @Deprecated public androidx.wear.tiles.TimelineBuilders.TimeInterval build();
+    method @Deprecated public androidx.wear.tiles.TimelineBuilders.TimeInterval.Builder setEndMillis(long);
+    method @Deprecated public androidx.wear.tiles.TimelineBuilders.TimeInterval.Builder setStartMillis(long);
+  }
+
+  @Deprecated public static final class TimelineBuilders.Timeline {
+    method @Deprecated public static androidx.wear.tiles.TimelineBuilders.Timeline fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public java.util.List<androidx.wear.tiles.TimelineBuilders.TimelineEntry!> getTimelineEntries();
+  }
+
+  @Deprecated public static final class TimelineBuilders.Timeline.Builder {
+    ctor @Deprecated public TimelineBuilders.Timeline.Builder();
+    method @Deprecated public androidx.wear.tiles.TimelineBuilders.Timeline.Builder addTimelineEntry(androidx.wear.tiles.TimelineBuilders.TimelineEntry);
+    method @Deprecated public androidx.wear.tiles.TimelineBuilders.Timeline build();
+  }
+
+  @Deprecated public static final class TimelineBuilders.TimelineEntry {
+    method @Deprecated public static androidx.wear.tiles.TimelineBuilders.TimelineEntry fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+    method @Deprecated public androidx.wear.tiles.LayoutElementBuilders.Layout? getLayout();
+    method @Deprecated public androidx.wear.tiles.TimelineBuilders.TimeInterval? getValidity();
+  }
+
+  @Deprecated public static final class TimelineBuilders.TimelineEntry.Builder {
+    ctor @Deprecated public TimelineBuilders.TimelineEntry.Builder();
+    method @Deprecated public androidx.wear.tiles.TimelineBuilders.TimelineEntry build();
+    method @Deprecated public androidx.wear.tiles.TimelineBuilders.TimelineEntry.Builder setLayout(androidx.wear.tiles.LayoutElementBuilders.Layout);
+    method @Deprecated public androidx.wear.tiles.TimelineBuilders.TimelineEntry.Builder setValidity(androidx.wear.tiles.TimelineBuilders.TimeInterval);
+  }
+
+  @Deprecated public final class TypeBuilders {
+  }
+
+  @Deprecated public static final class TypeBuilders.BoolProp {
+    method @Deprecated public boolean getValue();
+  }
+
+  @Deprecated public static final class TypeBuilders.BoolProp.Builder {
+    ctor @Deprecated public TypeBuilders.BoolProp.Builder();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.BoolProp build();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.BoolProp.Builder setValue(boolean);
+  }
+
+  @Deprecated public static final class TypeBuilders.FloatProp {
+    method @Deprecated public float getValue();
+  }
+
+  @Deprecated public static final class TypeBuilders.FloatProp.Builder {
+    ctor @Deprecated public TypeBuilders.FloatProp.Builder();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.FloatProp build();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.FloatProp.Builder setValue(float);
+  }
+
+  @Deprecated public static final class TypeBuilders.Int32Prop {
+    method @Deprecated public int getValue();
+  }
+
+  @Deprecated public static final class TypeBuilders.Int32Prop.Builder {
+    ctor @Deprecated public TypeBuilders.Int32Prop.Builder();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.Int32Prop build();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.Int32Prop.Builder setValue(int);
+  }
+
+  @Deprecated public static final class TypeBuilders.StringProp {
+    method @Deprecated public String getValue();
+  }
+
+  @Deprecated public static final class TypeBuilders.StringProp.Builder {
+    ctor @Deprecated public TypeBuilders.StringProp.Builder();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.StringProp build();
+    method @Deprecated public androidx.wear.tiles.TypeBuilders.StringProp.Builder setValue(String);
+  }
+
+}
+
diff --git a/wear/tiles/tiles/src/main/java/androidx/wear/tiles/DiskAccessAllowedPrefs.java b/wear/tiles/tiles/src/main/java/androidx/wear/tiles/DiskAccessAllowedPrefs.java
new file mode 100644
index 0000000..7928651
--- /dev/null
+++ b/wear/tiles/tiles/src/main/java/androidx/wear/tiles/DiskAccessAllowedPrefs.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.tiles;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.StrictMode;
+import android.os.StrictMode.ThreadPolicy;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+
+import java.util.Map;
+
+/** Get versions of shared prefs that ignore strict mode and allows disk reads and writes. */
+@RestrictTo(Scope.LIBRARY_GROUP)
+final class DiskAccessAllowedPrefs {
+
+    @NonNull private final SharedPreferences preferences;
+
+    private DiskAccessAllowedPrefs(@NonNull SharedPreferences preferences) {
+        this.preferences = preferences;
+    }
+
+    /**
+     * Returns a simplified version of {@link SharedPreferences} wrapped to ignore disk read and
+     * write StrictMode violations.
+     */
+    @Nullable
+    static DiskAccessAllowedPrefs wrap(@NonNull Context context, @NonNull String name) {
+        ThreadPolicy policy = StrictMode.allowThreadDiskReads();
+        try {
+            SharedPreferences sharedPref = context.getSharedPreferences(name, Context.MODE_PRIVATE);
+            return sharedPref != null ? new DiskAccessAllowedPrefs(sharedPref) : null;
+        } finally {
+            StrictMode.setThreadPolicy(policy);
+        }
+    }
+
+    @Nullable
+    Map<String, ?> getAll() {
+        ThreadPolicy policy = StrictMode.allowThreadDiskReads();
+        try {
+            return preferences.getAll();
+        } finally {
+            StrictMode.setThreadPolicy(policy);
+        }
+    }
+
+    long getLong(@NonNull String key, long defValue) {
+        ThreadPolicy policy = StrictMode.allowThreadDiskReads();
+        try {
+            return preferences.getLong(key, defValue);
+        } finally {
+            StrictMode.setThreadPolicy(policy);
+        }
+    }
+
+    void putLong(@NonNull String key, long value) {
+        ThreadPolicy policy = StrictMode.allowThreadDiskWrites();
+        try {
+            preferences.edit().putLong(key, value).apply();
+        } finally {
+            StrictMode.setThreadPolicy(policy);
+        }
+    }
+
+    boolean contains(@NonNull String key) {
+        ThreadPolicy policy = StrictMode.allowThreadDiskReads();
+        try {
+            return preferences.contains(key);
+        } finally {
+            StrictMode.setThreadPolicy(policy);
+        }
+    }
+
+    void remove(@NonNull String key) {
+        ThreadPolicy policy = StrictMode.allowThreadDiskWrites();
+        try {
+            preferences.edit().remove(key).apply();
+        } finally {
+            StrictMode.setThreadPolicy(policy);
+        }
+    }
+}
diff --git a/wear/tiles/tiles/src/main/java/androidx/wear/tiles/TileService.java b/wear/tiles/tiles/src/main/java/androidx/wear/tiles/TileService.java
index 9c90ec8f..36a655c 100644
--- a/wear/tiles/tiles/src/main/java/androidx/wear/tiles/TileService.java
+++ b/wear/tiles/tiles/src/main/java/androidx/wear/tiles/TileService.java
@@ -20,14 +20,12 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.content.SharedPreferences;
 import android.content.pm.PackageManager;
 import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.OutcomeReceiver;
 import android.os.RemoteException;
-import android.os.StrictMode;
 import android.util.Log;
 
 import androidx.annotation.DoNotInline;
@@ -284,17 +282,17 @@
      * changed by the time the result is received. {@link TileService#onTileAddEvent} and {@link
      * TileService#onTileRemoveEvent} should be used instead for live updates.
      *
-     * Compatibility behavior:
-     * <p>On SDKs older than U, this method is a best-effort to match platform behavior, but may
-     * not always return all tiles present in the carousel. The possibly omitted tiles being the
+     * <p>Compatibility behavior:
+     *
+     * <p>On SDKs older than U, this method is a best-effort to match platform behavior, but may not
+     * always return all tiles present in the carousel. The possibly omitted tiles being the
      * pre-installed tiles, all tiles if the user has cleared the app data, or the tiles a user
      * hasn't visited in the last 60 days, while tiles removed by an app update may be shown as
      * active for 60 days afterwards.
      *
      * @param context The application context.
      * @param executor The executor on which methods should be invoked. To dispatch events through
-     *     the main thread of your application, you can use {@link
-     *     Context#getMainExecutor()}.
+     *     the main thread of your application, you can use {@link Context#getMainExecutor()}.
      * @return A list of {@link ActiveTileIdentifier} for the tiles belonging to the passed {@code
      *     context} present in the carousel, or a value based on platform-specific fallback
      *     behavior.
@@ -304,8 +302,8 @@
             @NonNull Context context, @NonNull Executor executor) {
         if (useWearSdkImpl(context)
                 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
-            return Api34Impl.getActiveTilesAsync(Sdk.getWearManager(context, TilesManager.class),
-                    executor);
+            return Api34Impl.getActiveTilesAsync(
+                    Sdk.getWearManager(context, TilesManager.class), executor);
         }
         return getActiveTilesAsyncLegacy(context, executor, sTimeSourceClock);
     }
@@ -692,17 +690,18 @@
                 @NonNull TilesManager tilesManager, @NonNull Executor executor) {
             return CallbackToFutureAdapter.getFuture(
                     completer -> {
-                        tilesManager.getActiveTiles(executor,
+                        tilesManager.getActiveTiles(
+                                executor,
                                 new OutcomeReceiver<List<TileInstance>, Exception>() {
                                     @Override
                                     public void onResult(List<TileInstance> tileInstanceList) {
-                                        completer.set(tileInstanceToActiveTileIdentifier(
-                                                tileInstanceList));
+                                        completer.set(
+                                                tileInstanceToActiveTileIdentifier(
+                                                        tileInstanceList));
                                     }
 
                                     @Override
-                                    public void onError(
-                                            @NonNull Exception error) {
+                                    public void onError(@NonNull Exception error) {
                                         completer.setException(error.getCause());
                                     }
                                 });
@@ -713,10 +712,12 @@
 
     private static List<ActiveTileIdentifier> tileInstanceToActiveTileIdentifier(
             @NonNull List<TileInstance> tileInstanceList) {
-        return tileInstanceList.stream().map(
-                i -> new ActiveTileIdentifier(i.getTileProvider().getComponentName(),
-                        i.getId())).collect(
-                Collectors.toList());
+        return tileInstanceList.stream()
+                .map(
+                        i ->
+                                new ActiveTileIdentifier(
+                                        i.getTileProvider().getComponentName(), i.getId()))
+                .collect(Collectors.toList());
     }
 
     /**
@@ -732,16 +733,15 @@
     private void markTileAsActiveLegacy(int tileId) {
         if (!useWearSdkImpl(this)) {
             ComponentName componentName = new ComponentName(this, this.getClass().getName());
-            SharedPreferences sharedPref = getActiveTilesSharedPrefLegacy(this);
+            DiskAccessAllowedPrefs sharedPref = getActiveTilesSharedPrefLegacy(this);
             cleanupActiveTilesSharedPrefLegacy(sharedPref, getTimeSourceClock());
             String key = new ActiveTileIdentifier(componentName, tileId).flattenToString();
             if (sharedPref.contains(key)
-                    && !timestampNeedsUpdateLegacy(sharedPref.getLong(key, -1L),
-                    getTimeSourceClock())) {
+                    && !timestampNeedsUpdateLegacy(
+                            sharedPref.getLong(key, -1L), getTimeSourceClock())) {
                 return;
             }
-            sharedPref.edit().putLong(key,
-                    getTimeSourceClock().getCurrentTimestampMillis()).apply();
+            sharedPref.putLong(key, getTimeSourceClock().getCurrentTimestampMillis());
         }
     }
 
@@ -754,15 +754,15 @@
      */
     private void markTileAsInactiveLegacy(int tileId) {
         if (!useWearSdkImpl(this)) {
-            SharedPreferences sharedPref = getActiveTilesSharedPrefLegacy(this);
+            DiskAccessAllowedPrefs sharedPref = getActiveTilesSharedPrefLegacy(this);
             String key =
-                    new ActiveTileIdentifier(new ComponentName(this, this.getClass().getName()),
-                            tileId)
+                    new ActiveTileIdentifier(
+                                    new ComponentName(this, this.getClass().getName()), tileId)
                             .flattenToString();
             if (!sharedPref.contains(key)) {
                 return;
             }
-            sharedPref.edit().remove(key).apply();
+            sharedPref.remove(key);
         }
     }
 
@@ -777,23 +777,17 @@
      * SharedPreferences are read.
      */
     private static void cleanupActiveTilesSharedPrefLegacy(
-            @NonNull SharedPreferences activeTilesSharedPref,
+            @NonNull DiskAccessAllowedPrefs activeTilesSharedPref,
             @NonNull TimeSourceClock timeSourceClock) {
-        StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
-        try {
-            for (String key : activeTilesSharedPref.getAll().keySet()) {
-                if (isTileInactiveLegacy(activeTilesSharedPref.getLong(key, -1L),
-                        timeSourceClock)) {
-                    activeTilesSharedPref.edit().remove(key).apply();
-                }
+        for (String key : activeTilesSharedPref.getAll().keySet()) {
+            if (isTileInactiveLegacy(activeTilesSharedPref.getLong(key, -1L), timeSourceClock)) {
+                activeTilesSharedPref.remove(key);
             }
-        } finally {
-            StrictMode.setThreadPolicy(oldPolicy);
         }
     }
 
     private static ListenableFuture<List<ActiveTileIdentifier>> readActiveTilesSharedPrefLegacy(
-            @NonNull SharedPreferences activeTilesSharedPref,
+            @NonNull DiskAccessAllowedPrefs activeTilesSharedPref,
             @NonNull String packageName,
             @NonNull Executor executor,
             @NonNull TimeSourceClock timeSourceClock) {
@@ -832,13 +826,8 @@
                 });
     }
 
-    private static SharedPreferences getActiveTilesSharedPrefLegacy(@NonNull Context context) {
-        StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
-        try {
-            return context.getSharedPreferences(ACTIVE_TILES_SHARED_PREF_NAME, MODE_PRIVATE);
-        } finally {
-            StrictMode.setThreadPolicy(oldPolicy);
-        }
+    private static DiskAccessAllowedPrefs getActiveTilesSharedPrefLegacy(@NonNull Context context) {
+        return DiskAccessAllowedPrefs.wrap(context, ACTIVE_TILES_SHARED_PREF_NAME);
     }
 
     /**
diff --git a/wear/watchface/watchface-complications-data-source-ktx/api/current.ignore b/wear/watchface/watchface-complications-data-source-ktx/api/current.ignore
new file mode 100644
index 0000000..ba1c315d
--- /dev/null
+++ b/wear/watchface/watchface-complications-data-source-ktx/api/current.ignore
@@ -0,0 +1,5 @@
+// Baseline format: 1.0
+InvalidNullConversion: androidx.wear.watchface.complications.datasource.SuspendingComplicationDataSourceService#onComplicationRequest(androidx.wear.watchface.complications.datasource.ComplicationRequest, kotlin.coroutines.Continuation<? super androidx.wear.watchface.complications.data.ComplicationData>) parameter #1:
+    Attempted to change nullability of androidx.wear.watchface.complications.data.ComplicationData (from NONNULL to NULLABLE) in parameter arg2 in androidx.wear.watchface.complications.datasource.SuspendingComplicationDataSourceService.onComplicationRequest(androidx.wear.watchface.complications.datasource.ComplicationRequest request, kotlin.coroutines.Continuation<? super androidx.wear.watchface.complications.data.ComplicationData> arg2)
+InvalidNullConversion: androidx.wear.watchface.complications.datasource.SuspendingTimelineComplicationDataSourceService#onComplicationRequest(androidx.wear.watchface.complications.datasource.ComplicationRequest, kotlin.coroutines.Continuation<? super androidx.wear.watchface.complications.datasource.ComplicationDataTimeline>) parameter #1:
+    Attempted to change nullability of androidx.wear.watchface.complications.datasource.ComplicationDataTimeline (from NONNULL to NULLABLE) in parameter arg2 in androidx.wear.watchface.complications.datasource.SuspendingTimelineComplicationDataSourceService.onComplicationRequest(androidx.wear.watchface.complications.datasource.ComplicationRequest request, kotlin.coroutines.Continuation<? super androidx.wear.watchface.complications.datasource.ComplicationDataTimeline> arg2)
diff --git a/wear/watchface/watchface-complications-data-source-ktx/api/restricted_current.ignore b/wear/watchface/watchface-complications-data-source-ktx/api/restricted_current.ignore
new file mode 100644
index 0000000..ba1c315d
--- /dev/null
+++ b/wear/watchface/watchface-complications-data-source-ktx/api/restricted_current.ignore
@@ -0,0 +1,5 @@
+// Baseline format: 1.0
+InvalidNullConversion: androidx.wear.watchface.complications.datasource.SuspendingComplicationDataSourceService#onComplicationRequest(androidx.wear.watchface.complications.datasource.ComplicationRequest, kotlin.coroutines.Continuation<? super androidx.wear.watchface.complications.data.ComplicationData>) parameter #1:
+    Attempted to change nullability of androidx.wear.watchface.complications.data.ComplicationData (from NONNULL to NULLABLE) in parameter arg2 in androidx.wear.watchface.complications.datasource.SuspendingComplicationDataSourceService.onComplicationRequest(androidx.wear.watchface.complications.datasource.ComplicationRequest request, kotlin.coroutines.Continuation<? super androidx.wear.watchface.complications.data.ComplicationData> arg2)
+InvalidNullConversion: androidx.wear.watchface.complications.datasource.SuspendingTimelineComplicationDataSourceService#onComplicationRequest(androidx.wear.watchface.complications.datasource.ComplicationRequest, kotlin.coroutines.Continuation<? super androidx.wear.watchface.complications.datasource.ComplicationDataTimeline>) parameter #1:
+    Attempted to change nullability of androidx.wear.watchface.complications.datasource.ComplicationDataTimeline (from NONNULL to NULLABLE) in parameter arg2 in androidx.wear.watchface.complications.datasource.SuspendingTimelineComplicationDataSourceService.onComplicationRequest(androidx.wear.watchface.complications.datasource.ComplicationRequest request, kotlin.coroutines.Continuation<? super androidx.wear.watchface.complications.datasource.ComplicationDataTimeline> arg2)
diff --git a/wear/watchface/watchface-complications-data/src/main/java/android/support/wearable/complications/ComplicationText.java b/wear/watchface/watchface-complications-data/src/main/java/android/support/wearable/complications/ComplicationText.java
index 75c7eb1..4043d36 100644
--- a/wear/watchface/watchface-complications-data/src/main/java/android/support/wearable/complications/ComplicationText.java
+++ b/wear/watchface/watchface-complications-data/src/main/java/android/support/wearable/complications/ComplicationText.java
@@ -586,7 +586,7 @@
     }
 
     /** Returns true if the text has a time-dependent component. */
-    boolean isTimeDependent() {
+    public boolean isTimeDependent() {
         return mTimeDependentText != null;
     }
 
diff --git a/wear/watchface/watchface-complications-data/src/main/java/android/support/wearable/complications/TimeDifferenceText.java b/wear/watchface/watchface-complications-data/src/main/java/android/support/wearable/complications/TimeDifferenceText.java
index 2433407..c2ac4fd 100644
--- a/wear/watchface/watchface-complications-data/src/main/java/android/support/wearable/complications/TimeDifferenceText.java
+++ b/wear/watchface/watchface-complications-data/src/main/java/android/support/wearable/complications/TimeDifferenceText.java
@@ -204,22 +204,22 @@
     }
 
     /** Returns the start of the reference period, as milliseconds since epoch. */
-    long getReferencePeriodStart() {
+    public long getReferencePeriodStart() {
         return mReferencePeriodStart;
     }
 
     /** Returns the end of the reference period, as milliseconds since epoch. */
-    long getReferencePeriodEnd() {
+    public long getReferencePeriodEnd() {
         return mReferencePeriodEnd;
     }
 
     /** Returns the style to be used when formatting the text. */
-    int getStyle() {
+    public int getStyle() {
         return mStyle;
     }
 
     /** Returns true if text for "now" should be shown when within the reference period. */
-    boolean shouldShowNowText() {
+    public boolean shouldShowNowText() {
         return mShowNowText;
     }
 
diff --git a/wear/watchface/watchface-editor-guava/api/current.ignore b/wear/watchface/watchface-editor-guava/api/current.ignore
new file mode 100644
index 0000000..57f7f57
--- /dev/null
+++ b/wear/watchface/watchface-editor-guava/api/current.ignore
@@ -0,0 +1,11 @@
+// Baseline format: 1.0
+InvalidNullConversion: androidx.wear.watchface.editor.ListenableEditorSession#complicationsDataSourceInfo:
+    Attempted to change nullability of androidx.wear.watchface.complications.ComplicationDataSourceInfo (from NONNULL to NULLABLE) in property ListenableEditorSession.complicationsDataSourceInfo
+InvalidNullConversion: androidx.wear.watchface.editor.ListenableEditorSession#getComplicationsDataSourceInfo():
+    Attempted to change nullability of androidx.wear.watchface.complications.ComplicationDataSourceInfo (from NONNULL to NULLABLE) in method androidx.wear.watchface.editor.ListenableEditorSession.getComplicationsDataSourceInfo()
+InvalidNullConversion: androidx.wear.watchface.editor.ListenableEditorSession#listenableCreateOnWatchEditorSession(androidx.activity.ComponentActivity):
+    Attempted to change nullability of androidx.wear.watchface.editor.ListenableEditorSession (from NONNULL to NULLABLE) in method androidx.wear.watchface.editor.ListenableEditorSession.listenableCreateOnWatchEditorSession(androidx.activity.ComponentActivity)
+InvalidNullConversion: androidx.wear.watchface.editor.ListenableEditorSession#listenableOpenComplicationDataSourceChooser(int):
+    Attempted to change nullability of androidx.wear.watchface.editor.ChosenComplicationDataSource (from NONNULL to NULLABLE) in method androidx.wear.watchface.editor.ListenableEditorSession.listenableOpenComplicationDataSourceChooser(int)
+InvalidNullConversion: androidx.wear.watchface.editor.ListenableEditorSession.Companion#listenableCreateOnWatchEditorSession(androidx.activity.ComponentActivity):
+    Attempted to change nullability of androidx.wear.watchface.editor.ListenableEditorSession (from NONNULL to NULLABLE) in method androidx.wear.watchface.editor.ListenableEditorSession.Companion.listenableCreateOnWatchEditorSession(androidx.activity.ComponentActivity)
diff --git a/wear/watchface/watchface-editor-guava/api/restricted_current.ignore b/wear/watchface/watchface-editor-guava/api/restricted_current.ignore
new file mode 100644
index 0000000..57f7f57
--- /dev/null
+++ b/wear/watchface/watchface-editor-guava/api/restricted_current.ignore
@@ -0,0 +1,11 @@
+// Baseline format: 1.0
+InvalidNullConversion: androidx.wear.watchface.editor.ListenableEditorSession#complicationsDataSourceInfo:
+    Attempted to change nullability of androidx.wear.watchface.complications.ComplicationDataSourceInfo (from NONNULL to NULLABLE) in property ListenableEditorSession.complicationsDataSourceInfo
+InvalidNullConversion: androidx.wear.watchface.editor.ListenableEditorSession#getComplicationsDataSourceInfo():
+    Attempted to change nullability of androidx.wear.watchface.complications.ComplicationDataSourceInfo (from NONNULL to NULLABLE) in method androidx.wear.watchface.editor.ListenableEditorSession.getComplicationsDataSourceInfo()
+InvalidNullConversion: androidx.wear.watchface.editor.ListenableEditorSession#listenableCreateOnWatchEditorSession(androidx.activity.ComponentActivity):
+    Attempted to change nullability of androidx.wear.watchface.editor.ListenableEditorSession (from NONNULL to NULLABLE) in method androidx.wear.watchface.editor.ListenableEditorSession.listenableCreateOnWatchEditorSession(androidx.activity.ComponentActivity)
+InvalidNullConversion: androidx.wear.watchface.editor.ListenableEditorSession#listenableOpenComplicationDataSourceChooser(int):
+    Attempted to change nullability of androidx.wear.watchface.editor.ChosenComplicationDataSource (from NONNULL to NULLABLE) in method androidx.wear.watchface.editor.ListenableEditorSession.listenableOpenComplicationDataSourceChooser(int)
+InvalidNullConversion: androidx.wear.watchface.editor.ListenableEditorSession.Companion#listenableCreateOnWatchEditorSession(androidx.activity.ComponentActivity):
+    Attempted to change nullability of androidx.wear.watchface.editor.ListenableEditorSession (from NONNULL to NULLABLE) in method androidx.wear.watchface.editor.ListenableEditorSession.Companion.listenableCreateOnWatchEditorSession(androidx.activity.ComponentActivity)
diff --git a/wear/watchface/watchface-editor/api/current.ignore b/wear/watchface/watchface-editor/api/current.ignore
new file mode 100644
index 0000000..be1df3d
--- /dev/null
+++ b/wear/watchface/watchface-editor/api/current.ignore
@@ -0,0 +1,5 @@
+// Baseline format: 1.0
+InvalidNullConversion: androidx.wear.watchface.editor.EditorSession#complicationsDataSourceInfo:
+    Attempted to change nullability of androidx.wear.watchface.complications.ComplicationDataSourceInfo (from NONNULL to NULLABLE) in property EditorSession.complicationsDataSourceInfo
+InvalidNullConversion: androidx.wear.watchface.editor.EditorSession#getComplicationsDataSourceInfo():
+    Attempted to change nullability of androidx.wear.watchface.complications.ComplicationDataSourceInfo (from NONNULL to NULLABLE) in method androidx.wear.watchface.editor.EditorSession.getComplicationsDataSourceInfo()
diff --git a/wear/watchface/watchface-editor/api/restricted_current.ignore b/wear/watchface/watchface-editor/api/restricted_current.ignore
new file mode 100644
index 0000000..be1df3d
--- /dev/null
+++ b/wear/watchface/watchface-editor/api/restricted_current.ignore
@@ -0,0 +1,5 @@
+// Baseline format: 1.0
+InvalidNullConversion: androidx.wear.watchface.editor.EditorSession#complicationsDataSourceInfo:
+    Attempted to change nullability of androidx.wear.watchface.complications.ComplicationDataSourceInfo (from NONNULL to NULLABLE) in property EditorSession.complicationsDataSourceInfo
+InvalidNullConversion: androidx.wear.watchface.editor.EditorSession#getComplicationsDataSourceInfo():
+    Attempted to change nullability of androidx.wear.watchface.complications.ComplicationDataSourceInfo (from NONNULL to NULLABLE) in method androidx.wear.watchface.editor.EditorSession.getComplicationsDataSourceInfo()
diff --git a/wear/watchface/watchface-editor/src/androidTest/java/androidx/wear/watchface/editor/EditorSessionTest.kt b/wear/watchface/watchface-editor/src/androidTest/java/androidx/wear/watchface/editor/EditorSessionTest.kt
index 519311f..ce6bb61 100644
--- a/wear/watchface/watchface-editor/src/androidTest/java/androidx/wear/watchface/editor/EditorSessionTest.kt
+++ b/wear/watchface/watchface-editor/src/androidTest/java/androidx/wear/watchface/editor/EditorSessionTest.kt
@@ -676,7 +676,10 @@
                     lastOverrideComplications = slotIdToComplicationData
                 }
 
-                override fun clearComplicationSlotAfterEditing(slotId: Int) {}
+                override fun clearComplicationSlotAfterEditing(
+                    slotId: Int,
+                    previewData: ComplicationData
+                ) {}
 
                 override fun dontClearAnyComplicationSlotsAfterEditing() {}
             }
diff --git a/wear/watchface/watchface-editor/src/main/java/androidx/wear/watchface/editor/EditorSession.kt b/wear/watchface/watchface-editor/src/main/java/androidx/wear/watchface/editor/EditorSession.kt
index 21ce97f..73de55c 100644
--- a/wear/watchface/watchface-editor/src/main/java/androidx/wear/watchface/editor/EditorSession.kt
+++ b/wear/watchface/watchface-editor/src/main/java/androidx/wear/watchface/editor/EditorSession.kt
@@ -606,15 +606,15 @@
                     getPreviewData(
                         complicationDataSourceInfoRetriever,
                         complicationDataSourceChooserResult.dataSourceInfo
-                    )
+                    ) ?: EmptyComplicationData()
 
                 // Emit an updated complicationPreviewDataMap.
                 complicationsPreviewData.value =
                     HashMap(complicationsPreviewData.value).apply {
-                        this[complicationSlotId] = previewData ?: EmptyComplicationData()
+                        this[complicationSlotId] = previewData
                     }
 
-                onComplicationDataSourceForSlotSelected(complicationSlotId)
+                onComplicationDataSourceForSlotSelected(complicationSlotId, previewData)
 
                 return ChosenComplicationDataSource(
                     complicationSlotId,
@@ -806,7 +806,7 @@
     protected open val showComplicationRationaleDialogIntent: Intent? = null
 
     /** Called when the user has selected a complication for a slot. */
-    open fun onComplicationDataSourceForSlotSelected(slotId: Int) {}
+    open fun onComplicationDataSourceForSlotSelected(slotId: Int, previewData: ComplicationData) {}
 }
 
 /**
@@ -1030,8 +1030,11 @@
         return editorDelegate.complicationSlotsManager.getComplicationSlotAt(x, y)?.id
     }
 
-    override fun onComplicationDataSourceForSlotSelected(slotId: Int) {
-        editorDelegate.clearComplicationSlotAfterEditing(slotId)
+    override fun onComplicationDataSourceForSlotSelected(
+        slotId: Int,
+        previewData: ComplicationData
+    ) {
+        editorDelegate.clearComplicationSlotAfterEditing(slotId, previewData)
     }
 }
 
diff --git a/wear/watchface/watchface/api/current.ignore b/wear/watchface/watchface/api/current.ignore
new file mode 100644
index 0000000..39c9387
--- /dev/null
+++ b/wear/watchface/watchface/api/current.ignore
@@ -0,0 +1,17 @@
+// Baseline format: 1.0
+InvalidNullConversion: androidx.wear.watchface.WatchState#getInterruptionFilter():
+    Attempted to change nullability of java.lang.Integer (from NONNULL to NULLABLE) in method androidx.wear.watchface.WatchState.getInterruptionFilter()
+InvalidNullConversion: androidx.wear.watchface.WatchState#interruptionFilter:
+    Attempted to change nullability of java.lang.Integer (from NONNULL to NULLABLE) in property WatchState.interruptionFilter
+InvalidNullConversion: androidx.wear.watchface.WatchState#isAmbient:
+    Attempted to change nullability of java.lang.Boolean (from NONNULL to NULLABLE) in property WatchState.isAmbient
+InvalidNullConversion: androidx.wear.watchface.WatchState#isAmbient():
+    Attempted to change nullability of java.lang.Boolean (from NONNULL to NULLABLE) in method androidx.wear.watchface.WatchState.isAmbient()
+InvalidNullConversion: androidx.wear.watchface.WatchState#isBatteryLowAndNotCharging:
+    Attempted to change nullability of java.lang.Boolean (from NONNULL to NULLABLE) in property WatchState.isBatteryLowAndNotCharging
+InvalidNullConversion: androidx.wear.watchface.WatchState#isBatteryLowAndNotCharging():
+    Attempted to change nullability of java.lang.Boolean (from NONNULL to NULLABLE) in method androidx.wear.watchface.WatchState.isBatteryLowAndNotCharging()
+InvalidNullConversion: androidx.wear.watchface.WatchState#isVisible:
+    Attempted to change nullability of java.lang.Boolean (from NONNULL to NULLABLE) in property WatchState.isVisible
+InvalidNullConversion: androidx.wear.watchface.WatchState#isVisible():
+    Attempted to change nullability of java.lang.Boolean (from NONNULL to NULLABLE) in method androidx.wear.watchface.WatchState.isVisible()
diff --git a/wear/watchface/watchface/api/restricted_current.ignore b/wear/watchface/watchface/api/restricted_current.ignore
new file mode 100644
index 0000000..39c9387
--- /dev/null
+++ b/wear/watchface/watchface/api/restricted_current.ignore
@@ -0,0 +1,17 @@
+// Baseline format: 1.0
+InvalidNullConversion: androidx.wear.watchface.WatchState#getInterruptionFilter():
+    Attempted to change nullability of java.lang.Integer (from NONNULL to NULLABLE) in method androidx.wear.watchface.WatchState.getInterruptionFilter()
+InvalidNullConversion: androidx.wear.watchface.WatchState#interruptionFilter:
+    Attempted to change nullability of java.lang.Integer (from NONNULL to NULLABLE) in property WatchState.interruptionFilter
+InvalidNullConversion: androidx.wear.watchface.WatchState#isAmbient:
+    Attempted to change nullability of java.lang.Boolean (from NONNULL to NULLABLE) in property WatchState.isAmbient
+InvalidNullConversion: androidx.wear.watchface.WatchState#isAmbient():
+    Attempted to change nullability of java.lang.Boolean (from NONNULL to NULLABLE) in method androidx.wear.watchface.WatchState.isAmbient()
+InvalidNullConversion: androidx.wear.watchface.WatchState#isBatteryLowAndNotCharging:
+    Attempted to change nullability of java.lang.Boolean (from NONNULL to NULLABLE) in property WatchState.isBatteryLowAndNotCharging
+InvalidNullConversion: androidx.wear.watchface.WatchState#isBatteryLowAndNotCharging():
+    Attempted to change nullability of java.lang.Boolean (from NONNULL to NULLABLE) in method androidx.wear.watchface.WatchState.isBatteryLowAndNotCharging()
+InvalidNullConversion: androidx.wear.watchface.WatchState#isVisible:
+    Attempted to change nullability of java.lang.Boolean (from NONNULL to NULLABLE) in property WatchState.isVisible
+InvalidNullConversion: androidx.wear.watchface.WatchState#isVisible():
+    Attempted to change nullability of java.lang.Boolean (from NONNULL to NULLABLE) in method androidx.wear.watchface.WatchState.isVisible()
diff --git a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFace.kt b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFace.kt
index df51d40..16a8a3f0 100644
--- a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFace.kt
+++ b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFace.kt
@@ -319,10 +319,11 @@
 
         /**
          * When a complication slot has been edited, we don't want to see a glimpse of the previous
-         * complication when the user has selected a new complication. To prevent that the
-         * complication will be replaced with EmptyComplicationData when [onDestroy] is called.
+         * complication when the user has selected a new complication. To prevent that if the
+         * datasource source changed, the complication will be replaced with EmptyComplicationData
+         * when [onDestroy] is called.
          */
-        public fun clearComplicationSlotAfterEditing(slotId: Int)
+        public fun clearComplicationSlotAfterEditing(slotId: Int, previewData: ComplicationData)
 
         /**
          * Instructs the system to ignore any previous calls to [clearComplicationSlotAfterEditing].
@@ -957,10 +958,10 @@
                 ?.overrideComplicationsForEditing(slotIdToComplicationData)
         }
 
-        override fun clearComplicationSlotAfterEditing(slotId: Int) {
+        override fun clearComplicationSlotAfterEditing(slotId: Int, previewData: ComplicationData) {
             InteractiveInstanceManager.getCurrentInteractiveInstance()
                 ?.engine
-                ?.clearComplicationSlotAfterEditing(slotId)
+                ?.clearComplicationSlotAfterEditing(slotId, previewData)
         }
 
         override fun dontClearAnyComplicationSlotsAfterEditing() {
diff --git a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt
index 0c213d6..0e19a63 100644
--- a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt
+++ b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt
@@ -1363,7 +1363,7 @@
         private var lastWatchFaceColors: WatchFaceColors? = null
         private var lastPreviewImageNeedsUpdateRequest: String? = null
         private var overriddenComplications: HashMap<Int, ComplicationData>? = null
-        private val complicationSlotsToClearAfterEditing = HashSet<Int>()
+        private val editedComplicationPreviewData = mutableMapOf<Int, ComplicationData>()
         private var pauseAnimationDeathRecipient: PauseAnimationDeathRecipient? = null
         private var privIsVisible = true
 
@@ -1714,51 +1714,42 @@
         }
 
         /**
-         * Marks [slotId] to be cleared after editing, to prevent the user seeing a glimpse of the
-         * old complication.
+         * Marks [slotId] to be cleared after editing if necessary, to prevent the user seeing a
+         * glimpse of the old complication.
          */
         @AnyThread
-        internal fun clearComplicationSlotAfterEditing(slotId: Int) {
-            synchronized(lock) { complicationSlotsToClearAfterEditing.add(slotId) }
+        internal fun clearComplicationSlotAfterEditing(slotId: Int, previewData: ComplicationData) {
+            synchronized(lock) { editedComplicationPreviewData.put(slotId, previewData) }
         }
 
         /** Forgets any calls to [clearComplicationSlotAfterEditing]. */
         @AnyThread
         internal fun dontClearAnyComplicationSlotsAfterEditing() {
-            synchronized(lock) { complicationSlotsToClearAfterEditing.clear() }
+            synchronized(lock) { editedComplicationPreviewData.clear() }
         }
 
         /**
          * Undoes any complication overrides by [overrideComplicationsForEditing], restoring the
-         * original data. However any complications marked as being cleared after editing by
-         * [clearComplicationSlotAfterEditing] will be replaced by [EmptyComplicationData] to
-         * prevent the user seeing a flash of the old data.
+         * original data. In addition any complications marked as being cleared after editing by
+         * [clearComplicationSlotAfterEditing] whose data soure changed, will be replaced by
+         * [EmptyComplicationData] to prevent the user seeing a flash of the old complication.
          */
         @AnyThread
         internal fun onEditSessionFinished() {
             synchronized(lock) {
-                if (overriddenComplications == null) {
-                    complicationsFlow.update {
-                        it.toMutableMap().apply {
-                            for (frozenSlot in complicationSlotsToClearAfterEditing) {
-                                put(frozenSlot, EmptyComplicationData())
-                            }
-                            complicationSlotsToClearAfterEditing.clear()
-                        }
+                val complications = overriddenComplications ?: HashMap(complicationsFlow.value)
+                for ((frozenSlot, previewData) in editedComplicationPreviewData) {
+                    if (
+                        complicationsFlow.value[frozenSlot]!!.dataSource != previewData.dataSource
+                    ) {
+                        complications[frozenSlot] = EmptyComplicationData()
                     }
-                    return
                 }
 
-                // Restore the original complications, except for any frozen slots which are
-                // replaced with EmptyComplicationData.
-                for (frozenSlot in complicationSlotsToClearAfterEditing) {
-                    overriddenComplications!![frozenSlot] = EmptyComplicationData()
-                }
-                complicationSlotsToClearAfterEditing.clear()
-
-                complicationsFlow.update { overriddenComplications!! }
-
+                complicationsFlow.value = complications
                 overriddenComplications = null
+
+                editedComplicationPreviewData.clear()
             }
         }
 
@@ -2610,6 +2601,7 @@
         override fun onVisibilityChanged(visible: Boolean): Unit =
             TraceEvent("onVisibilityChanged").use {
                 super.onVisibilityChanged(visible)
+                Log.i(TAG, "onVisibilityChanged($isVisible)")
 
                 // In the WSL flow Home doesn't know when WallpaperService has actually launched a
                 // watchface after requesting a change. It used [Constants.ACTION_REQUEST_STATE] as
diff --git a/wear/watchface/watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt b/wear/watchface/watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt
index c75c731..63d4007 100644
--- a/wear/watchface/watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt
+++ b/wear/watchface/watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt
@@ -153,6 +153,7 @@
 private const val RIGHT_COMPLICATION_ID = 1001
 private const val EDGE_COMPLICATION_ID = 1002
 private const val MOCK_COMPLICATION_ID = 1003
+private const val MOCK_COMPLICATION_ID2 = 1004
 private const val BACKGROUND_COMPLICATION_ID = 1111
 private const val NO_COMPLICATIONS = "NO_COMPLICATIONS"
 private const val LEFT_COMPLICATION = "LEFT_COMPLICATION"
@@ -370,6 +371,29 @@
             )
             .build()
 
+    private val mockCanvasComplication2 = mock<CanvasComplication>()
+    private val mockComplication2 =
+        ComplicationSlot.createRoundRectComplicationSlotBuilder(
+                MOCK_COMPLICATION_ID2,
+                { _, _ -> mockCanvasComplication2 },
+                listOf(
+                    ComplicationType.RANGED_VALUE,
+                    ComplicationType.LONG_TEXT,
+                    ComplicationType.SHORT_TEXT,
+                    ComplicationType.MONOCHROMATIC_IMAGE,
+                    ComplicationType.SMALL_IMAGE
+                ),
+                DefaultComplicationDataSourcePolicy(
+                    SystemDataSources.DATA_SOURCE_DAY_OF_WEEK,
+                    ComplicationType.LONG_TEXT
+                ),
+                ComplicationSlotBounds(
+                    bounds = RectF(0.6f, 0.4f, 0.8f, 0.6f),
+                    margins = RectF(0.1f, 0.1f, 0.1f, 0.1f)
+                )
+            )
+            .build()
+
     @Suppress("DEPRECATION") // setDefaultDataSourceType
     private val backgroundComplication =
         ComplicationSlot.createBackgroundComplicationSlotBuilder(
@@ -3059,10 +3083,27 @@
     }
 
     @Test
-    public fun clearComplicationSlotAfterEditing() {
+    public fun clearComplicationSlotAfterEditing_dataSourceChanged() {
         initWallpaperInteractiveWatchFaceInstance(complicationSlots = listOf(mockComplication))
+        interactiveWatchFaceInstance.updateComplicationData(
+            listOf(
+                IdAndComplicationDataWireFormat(
+                    MOCK_COMPLICATION_ID,
+                    WireComplicationData.Builder(WireComplicationData.TYPE_LONG_TEXT)
+                        .setLongText(WireComplicationText.plainText("Live complication"))
+                        .setDataSource(ComponentName("one.com", "one"))
+                        .build()
+                )
+            )
+        )
+        val previewData =
+            WireComplicationData.Builder(WireComplicationData.TYPE_LONG_TEXT)
+                .setLongText(WireComplicationText.plainText("Preview"))
+                .setDataSource(ComponentName("two.com", "two"))
+                .build()
+                .toApiComplicationData()
 
-        engineWrapper.clearComplicationSlotAfterEditing(MOCK_COMPLICATION_ID)
+        engineWrapper.clearComplicationSlotAfterEditing(MOCK_COMPLICATION_ID, previewData)
         engineWrapper.onEditSessionFinished()
 
         verify(mockCanvasComplication)
@@ -3070,20 +3111,120 @@
     }
 
     @Test
+    public fun clearComplicationSlotAfterEditing_doesNothing_dataSourceUnchanged() {
+        initWallpaperInteractiveWatchFaceInstance(complicationSlots = listOf(mockComplication))
+        interactiveWatchFaceInstance.updateComplicationData(
+            listOf(
+                IdAndComplicationDataWireFormat(
+                    MOCK_COMPLICATION_ID,
+                    WireComplicationData.Builder(WireComplicationData.TYPE_LONG_TEXT)
+                        .setLongText(WireComplicationText.plainText("Live complication"))
+                        .setDataSource(ComponentName("one.com", "one"))
+                        .build()
+                )
+            )
+        )
+        val previewComplication =
+            WireComplicationData.Builder(WireComplicationData.TYPE_LONG_TEXT)
+                .setLongText(WireComplicationText.plainText("Preview"))
+                .setDataSource(ComponentName("one.com", "one"))
+                .build()
+                .toApiComplicationData()
+
+        engineWrapper.clearComplicationSlotAfterEditing(MOCK_COMPLICATION_ID, previewComplication)
+        engineWrapper.onEditSessionFinished()
+
+        verify(mockCanvasComplication, times(0))
+            .loadData(EmptyComplicationData(), loadDrawablesAsynchronous = true)
+    }
+
+    @Test
     public fun clearComplicationSlotAfterEditing_doesNotBlockOverrideComplicationData() {
         initWallpaperInteractiveWatchFaceInstance(complicationSlots = listOf(mockComplication))
-        val data =
+        val previewData =
             WireComplicationData.Builder(WireComplicationData.TYPE_LONG_TEXT)
-                .setLongText(WireComplicationText.plainText("TYPE_LONG_TEXT"))
+                .setDataSource(ComponentName("one.com", "one"))
+                .setLongText(WireComplicationText.plainText("Preview complication"))
                 .build()
         interactiveWatchFaceInstance.overrideComplicationData(
-            listOf(IdAndComplicationDataWireFormat(MOCK_COMPLICATION_ID, data))
+            listOf(IdAndComplicationDataWireFormat(MOCK_COMPLICATION_ID, previewData))
         )
 
-        engineWrapper.clearComplicationSlotAfterEditing(MOCK_COMPLICATION_ID)
+        engineWrapper.clearComplicationSlotAfterEditing(
+            MOCK_COMPLICATION_ID,
+            previewData.toApiComplicationData()
+        )
 
         verify(mockCanvasComplication)
-            .loadData(data.toApiComplicationData(), loadDrawablesAsynchronous = true)
+            .loadData(previewData.toApiComplicationData(), loadDrawablesAsynchronous = true)
+    }
+
+    @Test
+    public fun overrideComplicationData_onEditSessionFinished() {
+        initWallpaperInteractiveWatchFaceInstance(
+            complicationSlots = listOf(mockComplication, mockComplication2)
+        )
+        // Set initial complications.
+        val liveComplication1 =
+            WireComplicationData.Builder(WireComplicationData.TYPE_LONG_TEXT)
+                .setLongText(WireComplicationText.plainText("Live complication1"))
+                .setDataSource(ComponentName("one.com", "one"))
+                .build()
+        val liveComplication2 =
+            WireComplicationData.Builder(WireComplicationData.TYPE_LONG_TEXT)
+                .setLongText(WireComplicationText.plainText("Live complication2"))
+                .setDataSource(ComponentName("two.com", "one"))
+                .build()
+        interactiveWatchFaceInstance.updateComplicationData(
+            listOf(
+                IdAndComplicationDataWireFormat(MOCK_COMPLICATION_ID, liveComplication1),
+                IdAndComplicationDataWireFormat(MOCK_COMPLICATION_ID2, liveComplication2)
+            )
+        )
+        // Preview complications set by the editor.
+        val previewComplication1 =
+            WireComplicationData.Builder(WireComplicationData.TYPE_LONG_TEXT)
+                .setLongText(WireComplicationText.plainText("Preview complication1"))
+                .setDataSource(ComponentName("one.com", "one"))
+                .build()
+        val previewComplication2 =
+            WireComplicationData.Builder(WireComplicationData.TYPE_LONG_TEXT)
+                .setLongText(WireComplicationText.plainText("Preview complication2"))
+                .setDataSource(ComponentName("two.com", "one"))
+                .build()
+        interactiveWatchFaceInstance.overrideComplicationData(
+            listOf(
+                IdAndComplicationDataWireFormat(MOCK_COMPLICATION_ID, previewComplication1),
+                IdAndComplicationDataWireFormat(MOCK_COMPLICATION_ID2, previewComplication2)
+            )
+        )
+        val previewComplication3 =
+            WireComplicationData.Builder(WireComplicationData.TYPE_LONG_TEXT)
+                .setLongText(WireComplicationText.plainText("Preview complication3"))
+                .setDataSource(ComponentName("three.com", "one"))
+                .build()
+        // Simulate the user changing MOCK_COMPLICATION_ID to point to the same complication.
+        engineWrapper.clearComplicationSlotAfterEditing(
+            MOCK_COMPLICATION_ID,
+            previewComplication1.toApiComplicationData()
+        )
+        // Simulate the user changing MOCK_COMPLICATION_ID2 to point to a new complication.
+        engineWrapper.clearComplicationSlotAfterEditing(
+            MOCK_COMPLICATION_ID2,
+            previewComplication3.toApiComplicationData()
+        )
+        reset(mockCanvasComplication)
+        reset(mockCanvasComplication2)
+
+        engineWrapper.onEditSessionFinished()
+
+        // MOCK_COMPLICATION_ID was unchanged so we should load the origional.
+        verify(mockCanvasComplication)
+            .loadData(liveComplication1.toApiComplicationData(), loadDrawablesAsynchronous = true)
+        // MOCK_COMPLICATION_ID was changed so we should load empty to prevent the user from seeing
+        // a glimpse of the old complication.
+        verify(mockCanvasComplication2)
+            .loadData(EmptyComplicationData(), loadDrawablesAsynchronous = true)
     }
 
     @Test
diff --git a/webkit/integration-tests/instrumentation/build.gradle b/webkit/integration-tests/instrumentation/build.gradle
index 1a7a216..289f6b7 100644
--- a/webkit/integration-tests/instrumentation/build.gradle
+++ b/webkit/integration-tests/instrumentation/build.gradle
@@ -20,7 +20,7 @@
     productFlavors {
         targetSdk32 {
             dimension "targetSdk"
-            targetSdkVersion 32
+
         }
         targetSdkLatest {
             dimension "targetSdk"
@@ -28,6 +28,13 @@
         }
     }
 }
+
+androidComponents {
+    beforeVariants(selector().withFlavor("targetSdk", "targetSdk32")) { variant ->
+        variant.androidTest.targetSdk = 32
+    }
+}
+
 dependencies {
     androidTestImplementation(project(":webkit:webkit"))
 
diff --git a/window/extensions/extensions/api/current.txt b/window/extensions/extensions/api/current.txt
index 8bf868f..e72e167 100644
--- a/window/extensions/extensions/api/current.txt
+++ b/window/extensions/extensions/api/current.txt
@@ -54,15 +54,25 @@
   public interface ActivityEmbeddingComponent {
     method public void clearSplitAttributesCalculator();
     method public void clearSplitInfoCallback();
-    method public default void finishActivityStacks(java.util.Set<android.os.IBinder!>);
+    method @Deprecated public default void finishActivityStacks(java.util.Set<android.os.IBinder!>);
+    method public default void finishActivityStacksWithTokens(java.util.Set<androidx.window.extensions.embedding.ActivityStack.Token!>);
     method public default void invalidateTopVisibleSplitAttributes();
     method public boolean isActivityEmbedded(android.app.Activity);
+    method public default boolean pinTopActivityStack(int, androidx.window.extensions.embedding.SplitPinRule);
+    method public default void registerActivityStackCallback(java.util.concurrent.Executor, androidx.window.extensions.core.util.function.Consumer<java.util.List<androidx.window.extensions.embedding.ActivityStack!>!>);
     method public void setEmbeddingRules(java.util.Set<androidx.window.extensions.embedding.EmbeddingRule!>);
-    method public default android.app.ActivityOptions setLaunchingActivityStack(android.app.ActivityOptions, android.os.IBinder);
+    method @Deprecated public default android.app.ActivityOptions setLaunchingActivityStack(android.app.ActivityOptions, android.os.IBinder);
     method public void setSplitAttributesCalculator(androidx.window.extensions.core.util.function.Function<androidx.window.extensions.embedding.SplitAttributesCalculatorParams!,androidx.window.extensions.embedding.SplitAttributes!>);
     method public default void setSplitInfoCallback(androidx.window.extensions.core.util.function.Consumer<java.util.List<androidx.window.extensions.embedding.SplitInfo!>!>);
     method @Deprecated public void setSplitInfoCallback(java.util.function.Consumer<java.util.List<androidx.window.extensions.embedding.SplitInfo!>!>);
-    method public default void updateSplitAttributes(android.os.IBinder, androidx.window.extensions.embedding.SplitAttributes);
+    method public default void unpinTopActivityStack(int);
+    method public default void unregisterActivityStackCallback(androidx.window.extensions.core.util.function.Consumer<java.util.List<androidx.window.extensions.embedding.ActivityStack!>!>);
+    method @Deprecated public default void updateSplitAttributes(android.os.IBinder, androidx.window.extensions.embedding.SplitAttributes);
+    method public default void updateSplitAttributes(androidx.window.extensions.embedding.SplitInfo.Token, androidx.window.extensions.embedding.SplitAttributes);
+  }
+
+  public class ActivityEmbeddingOptionsProperties {
+    field public static final String KEY_ACTIVITY_STACK_TOKEN = "androidx.window.extensions.embedding.ActivityStackToken";
   }
 
   public class ActivityRule extends androidx.window.extensions.embedding.EmbeddingRule {
@@ -81,23 +91,44 @@
 
   public class ActivityStack {
     method public java.util.List<android.app.Activity!> getActivities();
+    method public androidx.window.extensions.embedding.ActivityStack.Token getActivityStackToken();
     method public boolean isEmpty();
   }
 
+  public static final class ActivityStack.Token {
+    method public static androidx.window.extensions.embedding.ActivityStack.Token createFromBinder(android.os.IBinder);
+    method public static androidx.window.extensions.embedding.ActivityStack.Token readFromBundle(android.os.Bundle);
+    method public android.os.Bundle toBundle();
+    field public static final androidx.window.extensions.embedding.ActivityStack.Token INVALID_ACTIVITY_STACK_TOKEN;
+  }
+
+  public abstract class AnimationBackground {
+    method public static androidx.window.extensions.embedding.AnimationBackground.ColorBackground createColorBackground(@ColorInt int);
+    field public static final androidx.window.extensions.embedding.AnimationBackground ANIMATION_BACKGROUND_DEFAULT;
+  }
+
+  public static class AnimationBackground.ColorBackground extends androidx.window.extensions.embedding.AnimationBackground {
+    method @ColorInt public int getColor();
+  }
+
   public abstract class EmbeddingRule {
     method public String? getTag();
   }
 
   public class SplitAttributes {
+    method public androidx.window.extensions.embedding.AnimationBackground getAnimationBackground();
     method public int getLayoutDirection();
     method public androidx.window.extensions.embedding.SplitAttributes.SplitType getSplitType();
+    method public androidx.window.extensions.embedding.WindowAttributes getWindowAttributes();
   }
 
   public static final class SplitAttributes.Builder {
     ctor public SplitAttributes.Builder();
     method public androidx.window.extensions.embedding.SplitAttributes build();
+    method public androidx.window.extensions.embedding.SplitAttributes.Builder setAnimationBackground(androidx.window.extensions.embedding.AnimationBackground);
     method public androidx.window.extensions.embedding.SplitAttributes.Builder setLayoutDirection(int);
     method public androidx.window.extensions.embedding.SplitAttributes.Builder setSplitType(androidx.window.extensions.embedding.SplitAttributes.SplitType);
+    method public androidx.window.extensions.embedding.SplitAttributes.Builder setWindowAttributes(androidx.window.extensions.embedding.WindowAttributes);
   }
 
   public static final class SplitAttributes.LayoutDirection {
@@ -139,8 +170,13 @@
     method public androidx.window.extensions.embedding.ActivityStack getPrimaryActivityStack();
     method public androidx.window.extensions.embedding.ActivityStack getSecondaryActivityStack();
     method public androidx.window.extensions.embedding.SplitAttributes getSplitAttributes();
+    method public androidx.window.extensions.embedding.SplitInfo.Token getSplitInfoToken();
     method @Deprecated public float getSplitRatio();
-    method public android.os.IBinder getToken();
+    method @Deprecated public android.os.IBinder getToken();
+  }
+
+  public static final class SplitInfo.Token {
+    method public static androidx.window.extensions.embedding.SplitInfo.Token createFromBinder(android.os.IBinder);
   }
 
   public class SplitPairRule extends androidx.window.extensions.embedding.SplitRule {
@@ -166,6 +202,17 @@
     method public androidx.window.extensions.embedding.SplitPairRule.Builder setTag(String);
   }
 
+  public class SplitPinRule extends androidx.window.extensions.embedding.SplitRule {
+    method public boolean isSticky();
+  }
+
+  public static final class SplitPinRule.Builder {
+    ctor public SplitPinRule.Builder(androidx.window.extensions.embedding.SplitAttributes, androidx.window.extensions.core.util.function.Predicate<android.view.WindowMetrics!>);
+    method public androidx.window.extensions.embedding.SplitPinRule build();
+    method public androidx.window.extensions.embedding.SplitPinRule.Builder setSticky(boolean);
+    method public androidx.window.extensions.embedding.SplitPinRule.Builder setTag(String);
+  }
+
   public class SplitPlaceholderRule extends androidx.window.extensions.embedding.SplitRule {
     method public int getFinishPrimaryWithPlaceholder();
     method @Deprecated public int getFinishPrimaryWithSecondary();
@@ -198,6 +245,13 @@
     field public static final int FINISH_NEVER = 0; // 0x0
   }
 
+  public final class WindowAttributes {
+    ctor public WindowAttributes(int);
+    method public int getDimAreaBehavior();
+    field public static final int DIM_AREA_ON_ACTIVITY_STACK = 1; // 0x1
+    field public static final int DIM_AREA_ON_TASK = 2; // 0x2
+  }
+
 }
 
 package androidx.window.extensions.layout {
diff --git a/window/extensions/extensions/api/restricted_current.txt b/window/extensions/extensions/api/restricted_current.txt
index 8bf868f..13940ea 100644
--- a/window/extensions/extensions/api/restricted_current.txt
+++ b/window/extensions/extensions/api/restricted_current.txt
@@ -54,15 +54,25 @@
   public interface ActivityEmbeddingComponent {
     method public void clearSplitAttributesCalculator();
     method public void clearSplitInfoCallback();
-    method public default void finishActivityStacks(java.util.Set<android.os.IBinder!>);
+    method @Deprecated public default void finishActivityStacks(java.util.Set<android.os.IBinder!>);
+    method public default void finishActivityStacksWithTokens(java.util.Set<androidx.window.extensions.embedding.ActivityStack.Token!>);
     method public default void invalidateTopVisibleSplitAttributes();
     method public boolean isActivityEmbedded(android.app.Activity);
+    method public default boolean pinTopActivityStack(int, androidx.window.extensions.embedding.SplitPinRule);
+    method public default void registerActivityStackCallback(java.util.concurrent.Executor, androidx.window.extensions.core.util.function.Consumer<java.util.List<androidx.window.extensions.embedding.ActivityStack!>!>);
     method public void setEmbeddingRules(java.util.Set<androidx.window.extensions.embedding.EmbeddingRule!>);
-    method public default android.app.ActivityOptions setLaunchingActivityStack(android.app.ActivityOptions, android.os.IBinder);
+    method @Deprecated public default android.app.ActivityOptions setLaunchingActivityStack(android.app.ActivityOptions, android.os.IBinder);
     method public void setSplitAttributesCalculator(androidx.window.extensions.core.util.function.Function<androidx.window.extensions.embedding.SplitAttributesCalculatorParams!,androidx.window.extensions.embedding.SplitAttributes!>);
     method public default void setSplitInfoCallback(androidx.window.extensions.core.util.function.Consumer<java.util.List<androidx.window.extensions.embedding.SplitInfo!>!>);
     method @Deprecated public void setSplitInfoCallback(java.util.function.Consumer<java.util.List<androidx.window.extensions.embedding.SplitInfo!>!>);
-    method public default void updateSplitAttributes(android.os.IBinder, androidx.window.extensions.embedding.SplitAttributes);
+    method public default void unpinTopActivityStack(int);
+    method public default void unregisterActivityStackCallback(androidx.window.extensions.core.util.function.Consumer<java.util.List<androidx.window.extensions.embedding.ActivityStack!>!>);
+    method @Deprecated public default void updateSplitAttributes(android.os.IBinder, androidx.window.extensions.embedding.SplitAttributes);
+    method public default void updateSplitAttributes(androidx.window.extensions.embedding.SplitInfo.Token, androidx.window.extensions.embedding.SplitAttributes);
+  }
+
+  public class ActivityEmbeddingOptionsProperties {
+    field public static final String KEY_ACTIVITY_STACK_TOKEN = "androidx.window.extensions.embedding.ActivityStackToken";
   }
 
   public class ActivityRule extends androidx.window.extensions.embedding.EmbeddingRule {
@@ -81,23 +91,45 @@
 
   public class ActivityStack {
     method public java.util.List<android.app.Activity!> getActivities();
+    method public androidx.window.extensions.embedding.ActivityStack.Token getActivityStackToken();
+    method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.os.IBinder getToken();
     method public boolean isEmpty();
   }
 
+  public static final class ActivityStack.Token {
+    method public static androidx.window.extensions.embedding.ActivityStack.Token createFromBinder(android.os.IBinder);
+    method public static androidx.window.extensions.embedding.ActivityStack.Token readFromBundle(android.os.Bundle);
+    method public android.os.Bundle toBundle();
+    field public static final androidx.window.extensions.embedding.ActivityStack.Token INVALID_ACTIVITY_STACK_TOKEN;
+  }
+
+  public abstract class AnimationBackground {
+    method public static androidx.window.extensions.embedding.AnimationBackground.ColorBackground createColorBackground(@ColorInt int);
+    field public static final androidx.window.extensions.embedding.AnimationBackground ANIMATION_BACKGROUND_DEFAULT;
+  }
+
+  public static class AnimationBackground.ColorBackground extends androidx.window.extensions.embedding.AnimationBackground {
+    method @ColorInt public int getColor();
+  }
+
   public abstract class EmbeddingRule {
     method public String? getTag();
   }
 
   public class SplitAttributes {
+    method public androidx.window.extensions.embedding.AnimationBackground getAnimationBackground();
     method public int getLayoutDirection();
     method public androidx.window.extensions.embedding.SplitAttributes.SplitType getSplitType();
+    method public androidx.window.extensions.embedding.WindowAttributes getWindowAttributes();
   }
 
   public static final class SplitAttributes.Builder {
     ctor public SplitAttributes.Builder();
     method public androidx.window.extensions.embedding.SplitAttributes build();
+    method public androidx.window.extensions.embedding.SplitAttributes.Builder setAnimationBackground(androidx.window.extensions.embedding.AnimationBackground);
     method public androidx.window.extensions.embedding.SplitAttributes.Builder setLayoutDirection(int);
     method public androidx.window.extensions.embedding.SplitAttributes.Builder setSplitType(androidx.window.extensions.embedding.SplitAttributes.SplitType);
+    method public androidx.window.extensions.embedding.SplitAttributes.Builder setWindowAttributes(androidx.window.extensions.embedding.WindowAttributes);
   }
 
   public static final class SplitAttributes.LayoutDirection {
@@ -139,8 +171,13 @@
     method public androidx.window.extensions.embedding.ActivityStack getPrimaryActivityStack();
     method public androidx.window.extensions.embedding.ActivityStack getSecondaryActivityStack();
     method public androidx.window.extensions.embedding.SplitAttributes getSplitAttributes();
+    method public androidx.window.extensions.embedding.SplitInfo.Token getSplitInfoToken();
     method @Deprecated public float getSplitRatio();
-    method public android.os.IBinder getToken();
+    method @Deprecated public android.os.IBinder getToken();
+  }
+
+  public static final class SplitInfo.Token {
+    method public static androidx.window.extensions.embedding.SplitInfo.Token createFromBinder(android.os.IBinder);
   }
 
   public class SplitPairRule extends androidx.window.extensions.embedding.SplitRule {
@@ -166,6 +203,17 @@
     method public androidx.window.extensions.embedding.SplitPairRule.Builder setTag(String);
   }
 
+  public class SplitPinRule extends androidx.window.extensions.embedding.SplitRule {
+    method public boolean isSticky();
+  }
+
+  public static final class SplitPinRule.Builder {
+    ctor public SplitPinRule.Builder(androidx.window.extensions.embedding.SplitAttributes, androidx.window.extensions.core.util.function.Predicate<android.view.WindowMetrics!>);
+    method public androidx.window.extensions.embedding.SplitPinRule build();
+    method public androidx.window.extensions.embedding.SplitPinRule.Builder setSticky(boolean);
+    method public androidx.window.extensions.embedding.SplitPinRule.Builder setTag(String);
+  }
+
   public class SplitPlaceholderRule extends androidx.window.extensions.embedding.SplitRule {
     method public int getFinishPrimaryWithPlaceholder();
     method @Deprecated public int getFinishPrimaryWithSecondary();
@@ -198,6 +246,13 @@
     field public static final int FINISH_NEVER = 0; // 0x0
   }
 
+  public final class WindowAttributes {
+    ctor public WindowAttributes(int);
+    method public int getDimAreaBehavior();
+    field public static final int DIM_AREA_ON_ACTIVITY_STACK = 1; // 0x1
+    field public static final int DIM_AREA_ON_TASK = 2; // 0x2
+  }
+
 }
 
 package androidx.window.extensions.layout {
diff --git a/window/extensions/extensions/build.gradle b/window/extensions/extensions/build.gradle
index 611e695..ac53d85 100644
--- a/window/extensions/extensions/build.gradle
+++ b/window/extensions/extensions/build.gradle
@@ -32,16 +32,18 @@
 dependencies {
     implementation("androidx.annotation:annotation:1.6.0")
     implementation("androidx.annotation:annotation-experimental:1.4.0")
-    compileOnly(implementation("androidx.window.extensions.core:core:1.0.0"))
+    compileOnly("androidx.window.extensions.core:core:1.0.0")
 
     testImplementation(libs.robolectric)
     testImplementation(libs.testExtJunit)
     testImplementation(libs.testRunner)
     testImplementation(libs.testRules)
+    testImplementation(libs.truth)
 
     androidTestImplementation(libs.testExtJunit)
     androidTestImplementation(libs.testRunner)
     androidTestImplementation(libs.testRules)
+    androidTestImplementation(libs.truth)
     androidTestImplementation(libs.dexmakerMockito, excludes.bytebuddy)
     androidTestImplementation(libs.mockitoCore, excludes.bytebuddy)
 }
diff --git a/window/extensions/extensions/src/main/java/androidx/window/extensions/area/WindowAreaComponent.java b/window/extensions/extensions/src/main/java/androidx/window/extensions/area/WindowAreaComponent.java
index 8ad2a9c..6d01778 100644
--- a/window/extensions/extensions/src/main/java/androidx/window/extensions/area/WindowAreaComponent.java
+++ b/window/extensions/extensions/src/main/java/androidx/window/extensions/area/WindowAreaComponent.java
@@ -16,15 +16,12 @@
 
 package androidx.window.extensions.area;
 
-import android.annotation.SuppressLint;
 import android.app.Activity;
-import android.os.Build;
 import android.util.DisplayMetrics;
 
 import androidx.annotation.IntDef;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
 import androidx.window.extensions.RequiresVendorApiLevel;
 import androidx.window.extensions.WindowExtensions;
@@ -162,20 +159,6 @@
             @NonNull Consumer<@WindowAreaSessionState Integer> consumer);
 
     /**
-     * @deprecated Use {@link #startRearDisplaySession(Activity, Consumer)}.
-     */
-    @RequiresVendorApiLevel(level = 2)
-    @Deprecated
-    @SuppressLint("ClassVerificationFailure")
-    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-    @RequiresApi(api = Build.VERSION_CODES.N)
-    default void startRearDisplaySession(@NonNull Activity activity,
-            @NonNull java.util.function.Consumer<@WindowAreaSessionState Integer> consumer) {
-        final Consumer<Integer> extensionsConsumer = consumer::accept;
-        startRearDisplaySession(activity, extensionsConsumer);
-    }
-
-    /**
      * Ends a RearDisplaySession and sends [STATE_INACTIVE] to the consumer
      * provided in the {@code startRearDisplaySession} method. This method is only
      * called through the {@code RearDisplaySession} provided to the developer.
diff --git a/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/ActivityEmbeddingComponent.java b/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/ActivityEmbeddingComponent.java
index b582e92..d032b00 100644
--- a/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/ActivityEmbeddingComponent.java
+++ b/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/ActivityEmbeddingComponent.java
@@ -26,9 +26,11 @@
 import androidx.window.extensions.WindowExtensions;
 import androidx.window.extensions.core.util.function.Consumer;
 import androidx.window.extensions.core.util.function.Function;
+import androidx.window.extensions.util.SetCompat;
 
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.Executor;
 
 /**
  * Extension component definition that is used by the WindowManager library to trigger custom
@@ -57,8 +59,7 @@
     /**
      * Sets the callback that notifies WM Jetpack about changes in split states from the Extensions
      * Sidecar implementation. The listener should be registered for the lifetime of the process.
-     * There are no threading guarantees where the events are dispatched from. All messages are
-     * re-posted to the executors provided by developers.
+     * There are no threading guarantees where the events are dispatched from.
      *
      * @param consumer the callback to notify {@link SplitInfo} list changes
      */
@@ -86,6 +87,50 @@
     boolean isActivityEmbedded(@NonNull Activity activity);
 
     /**
+     * Pins the top-most {@link ActivityStack} to keep the stack of the Activities to be
+     * positioned on top. The rest of the activities in the Task will be split with the pinned
+     * {@link ActivityStack}. The pinned {@link ActivityStack} would also have isolated activity
+     * navigation in which only the activities that are started from the pinned
+     * {@link ActivityStack} can be added on top of the {@link ActivityStack}.
+     * <p>
+     * The pinned {@link ActivityStack} is unpinned whenever the parent Task bounds don't
+     * satisfy the dimensions and aspect ratio requirements {@link SplitRule#checkParentMetrics}
+     * to show two {@link ActivityStack}s. See {@link SplitPinRule.Builder#setSticky} if
+     * the same {@link ActivityStack} should be pinned again whenever the parent Task bounds
+     * satisfies the dimensions and aspect ratios requirements defined in the rule.
+     *
+     * @param taskId The id of the Task that top {@link ActivityStack} should be pinned.
+     * @param splitPinRule The SplitRule that specifies how the top {@link ActivityStack} should
+     *                     be split with others.
+     * @return Returns {@code true} if the top {@link ActivityStack} is successfully pinned.
+     *         Otherwise, {@code false}. Few examples are:
+     *         1. There's no {@link ActivityStack}.
+     *         2. There is already an existing pinned {@link ActivityStack}.
+     *         3. There's no other {@link ActivityStack} to split with the top
+     *         {@link ActivityStack}.
+     */
+    @RequiresVendorApiLevel(level = 5)
+    default boolean pinTopActivityStack(int taskId, @NonNull SplitPinRule splitPinRule) {
+        throw new UnsupportedOperationException("This method must not be called unless there is a"
+                + " corresponding override implementation on the device.");
+    }
+
+    /**
+     * Unpins the pinned {@link ActivityStack}. The {@link ActivityStack} will still be the
+     * top-most {@link ActivityStack} right after unpinned, and the {@link ActivityStack} could
+     * be expanded or continue to be split with the next top {@link ActivityStack} if the current
+     * state matches any of the existing {@link SplitPairRule}. It is a no-op call if the task
+     * does not have a pinned {@link ActivityStack}.
+     *
+     * @param taskId The id of the Task that top {@link ActivityStack} should be unpinned.
+     */
+    @RequiresVendorApiLevel(level = 5)
+    default void unpinTopActivityStack(int taskId) {
+        throw new UnsupportedOperationException("This method must not be called unless there is a"
+                + " corresponding override implementation on the device.");
+    }
+
+    /**
      * Sets a function to compute the {@link SplitAttributes} for the {@link SplitRule} and current
      * window state provided in {@link SplitAttributesCalculatorParams}.
      * <p>
@@ -127,12 +172,10 @@
     void clearSplitAttributesCalculator();
 
     /**
-     * Sets the launching {@link ActivityStack} to the given {@link ActivityOptions}.
-     *
-     * @param options The {@link ActivityOptions} to be updated.
-     * @param token The {@link ActivityStack#getToken()} to represent the {@link ActivityStack}
+     * @deprecated Use {@link ActivityEmbeddingOptionsProperties#KEY_ACTIVITY_STACK_TOKEN} instead.
      */
-    @RequiresVendorApiLevel(level = 3)
+    @Deprecated
+    @RequiresVendorApiLevel(level = 3, deprecatedSince = 5)
     @NonNull
     default ActivityOptions setLaunchingActivityStack(@NonNull ActivityOptions options,
             @NonNull IBinder token) {
@@ -141,6 +184,16 @@
     }
 
     /**
+     * @deprecated Use {@link #finishActivityStacksWithTokens(Set)} with instead.
+     */
+    @Deprecated
+    @RequiresVendorApiLevel(level = 3, deprecatedSince = 5)
+    default void finishActivityStacks(@NonNull Set<IBinder> activityStackTokens) {
+        throw new UnsupportedOperationException("This method must not be called unless there is a"
+                + " corresponding override implementation on the device.");
+    }
+
+    /**
      * Finishes a set of {@link ActivityStack}s. When an {@link ActivityStack} that was in an active
      * split is finished, the other {@link ActivityStack} in the same {@link SplitInfo} can be
      * expanded to fill the parent task container.
@@ -148,10 +201,16 @@
      * @param activityStackTokens The set of tokens of {@link ActivityStack}-s that is going to be
      *                            finished.
      */
-    @RequiresVendorApiLevel(level = 3)
-    default void finishActivityStacks(@NonNull Set<IBinder> activityStackTokens) {
-        throw new UnsupportedOperationException("This method must not be called unless there is a"
-                + " corresponding override implementation on the device.");
+    @SuppressWarnings("deprecation") // Use finishActivityStacks(Set) as its core implementation.
+    @RequiresVendorApiLevel(level = 5)
+    default void finishActivityStacksWithTokens(
+            @NonNull Set<ActivityStack.Token> activityStackTokens) {
+        final Set<IBinder> binderSet = SetCompat.create();
+
+        for (ActivityStack.Token token : activityStackTokens) {
+            binderSet.add(token.getRawToken());
+        }
+        finishActivityStacks(binderSet);
     }
 
     /**
@@ -169,15 +228,84 @@
     }
 
     /**
+     * @deprecated Use {@link #updateSplitAttributes(SplitInfo.Token, SplitAttributes)} instead.
+     */
+    @Deprecated
+    @RequiresVendorApiLevel(level = 3, deprecatedSince = 5)
+    default void updateSplitAttributes(@NonNull IBinder splitInfoToken,
+            @NonNull SplitAttributes splitAttributes) {
+        throw new UnsupportedOperationException("This method must not be called unless there is a"
+                + " corresponding override implementation on the device.");
+    }
+
+    /**
      * Updates the {@link SplitAttributes} of a split pair. This is an alternative to using
      * a split attributes calculator callback, applicable when apps only need to update the
      * splits in a few cases but rely on the default split attributes otherwise.
      * @param splitInfoToken The identifier of the split pair to update.
      * @param splitAttributes The {@link SplitAttributes} to apply to the split pair.
      */
-    @RequiresVendorApiLevel(level = 3)
-    default void updateSplitAttributes(@NonNull IBinder splitInfoToken,
+    @SuppressWarnings("deprecation") // Use finishActivityStacks(Set).
+    @RequiresVendorApiLevel(level = 5)
+    default void updateSplitAttributes(@NonNull SplitInfo.Token splitInfoToken,
             @NonNull SplitAttributes splitAttributes) {
+        updateSplitAttributes(splitInfoToken.getRawToken(), splitAttributes);
+    }
+
+    /**
+     * Registers a callback that notifies WindowManager Jetpack about changes in
+     * {@link ActivityStack}.
+     * <p>
+     * In most cases, {@link ActivityStack} are a part of {@link SplitInfo} as
+     * {@link SplitInfo#getPrimaryActivityStack() the primary ActivityStack} or
+     * {@link SplitInfo#getSecondaryActivityStack() the secondary ActivityStack} of a
+     * {@link SplitInfo}.
+     * <p>
+     * However, there are some cases that {@link ActivityStack} is standalone and usually
+     * expanded. Cases are:
+     * <ul>
+     *   <li>A started {@link Activity} matches {@link ActivityRule} with
+     *   {@link ActivityRule#shouldAlwaysExpand()} {@code true}.
+     *
+     *   <li>The {@code ActivityStack} is an overlay {@code ActivityStack}.
+     *
+     *   <li>The associated {@link ActivityStack activityStacks} of a {@code ActivityStack} are
+     *   dismissed by {@link #finishActivityStacks(Set)}.
+     *
+     *   <li>One {@link ActivityStack} of {@link SplitInfo}(Either
+     *   {@link SplitInfo#getPrimaryActivityStack() the primary ActivityStack} or
+     *   {@link SplitInfo#getSecondaryActivityStack() the secondary ActivityStack}) is
+     *   empty and finished, while the other {@link ActivityStack} is not finished with the
+     *   finishing {@link ActivityStack}.
+     *   <p>
+     *   An example is a pair of activities matches a {@link SplitPairRule}, and its
+     *   {@link SplitPairRule#getFinishPrimaryWithSecondary()} is {@link SplitRule#FINISH_NEVER}.
+     *   Then if the last activity of
+     *   {@link SplitInfo#getSecondaryActivityStack() the secondary ActivityStack}) is finished,
+     *   {@link SplitInfo#getPrimaryActivityStack() the primary ActivityStack} will still remain.
+     * </ul>
+     *
+     * @param executor the executor to dispatch {@link ActivityStack} list changes.
+     * @param callback the callback to notify {@link ActivityStack} list changes.
+     *
+     * @see ActivityEmbeddingComponent#finishActivityStacks(Set)
+     */
+    @RequiresVendorApiLevel(level = 5)
+    default void registerActivityStackCallback(@NonNull Executor executor,
+            @NonNull Consumer<List<ActivityStack>> callback) {
+        throw new UnsupportedOperationException("This method must not be called unless there is a"
+                + " corresponding override implementation on the device.");
+    }
+
+    /**
+     * Removes the callback previously registered in {@link #registerActivityStackCallback}, or
+     * no-op if the callback hasn't been registered yet.
+     *
+     * @param callback The callback to remove, which should have been registered.
+     */
+    @RequiresVendorApiLevel(level = 5)
+    default void unregisterActivityStackCallback(
+            @NonNull Consumer<List<ActivityStack>> callback) {
         throw new UnsupportedOperationException("This method must not be called unless there is a"
                 + " corresponding override implementation on the device.");
     }
diff --git a/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/ActivityEmbeddingOptionsProperties.java b/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/ActivityEmbeddingOptionsProperties.java
new file mode 100644
index 0000000..5279caa
--- /dev/null
+++ b/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/ActivityEmbeddingOptionsProperties.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window.extensions.embedding;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+
+/**
+ * A class that contains activity embedding properties that puts to or retrieves from
+ * {@link android.app.ActivityOptions}.
+ */
+public class ActivityEmbeddingOptionsProperties {
+
+    private ActivityEmbeddingOptionsProperties() {}
+
+    /**
+     * The key of {@link ActivityStack.Token#toBundle()} that put into
+     * {@link android.app.ActivityOptions}.
+     * <p>
+     * Type: {@link Bundle#putBundle}
+     * <p>
+     * Apps can launch an activity into the {@link ActivityStack} that associated with
+     * {@code token} by {@link android.app.Activity#startActivity(Intent, Bundle)}.
+     *
+     * @see androidx.window.extensions.embedding.ActivityStack.Token#toBundle()
+     * @see androidx.window.extensions.embedding.ActivityStack.Token#createFromBinder(IBinder)
+     */
+    public static final String KEY_ACTIVITY_STACK_TOKEN =
+            "androidx.window.extensions.embedding.ActivityStackToken";
+}
diff --git a/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/ActivityRule.java b/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/ActivityRule.java
index c741647..669923f 100644
--- a/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/ActivityRule.java
+++ b/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/ActivityRule.java
@@ -24,6 +24,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
+import androidx.window.extensions.RequiresVendorApiLevel;
 import androidx.window.extensions.WindowExtensions;
 import androidx.window.extensions.core.util.function.Predicate;
 
@@ -107,8 +108,8 @@
          *                         matches the rule
          * @param intentPredicate the {@link Predicate} to verify if a given {@link Intent}
          *                         matches the rule
-         * Since {@link WindowExtensions#VENDOR_API_LEVEL_2}
          */
+        @RequiresVendorApiLevel(level = 2)
         public Builder(@NonNull Predicate<Activity> activityPredicate,
                 @NonNull Predicate<Intent> intentPredicate) {
             mActivityPredicate = activityPredicate;
@@ -124,8 +125,8 @@
 
         /**
          * @see ActivityRule#getTag()
-         * Since {@link androidx.window.extensions.WindowExtensions#VENDOR_API_LEVEL_2}
          */
+        @RequiresVendorApiLevel(level = 2)
         @NonNull
         public Builder setTag(@NonNull String tag) {
             mTag = Objects.requireNonNull(tag);
diff --git a/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/ActivityStack.java b/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/ActivityStack.java
index 5f79d3a..69b7ad3 100644
--- a/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/ActivityStack.java
+++ b/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/ActivityStack.java
@@ -17,10 +17,13 @@
 package androidx.window.extensions.embedding;
 
 import android.app.Activity;
+import android.os.Binder;
+import android.os.Bundle;
 import android.os.IBinder;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.RestrictTo;
+import androidx.window.extensions.RequiresVendorApiLevel;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -38,7 +41,7 @@
     private final boolean mIsEmpty;
 
     @NonNull
-    private final IBinder mToken;
+    private final Token mToken;
 
     /**
      * The {@code ActivityStack} constructor
@@ -49,9 +52,10 @@
      *                {@code ActivityStack}
      * @param token The token to identify this {@code ActivityStack}
      */
-    ActivityStack(@NonNull List<Activity> activities, boolean isEmpty, @NonNull IBinder token) {
+    ActivityStack(@NonNull List<Activity> activities, boolean isEmpty, @NonNull Token token) {
         Objects.requireNonNull(activities);
         Objects.requireNonNull(token);
+
         mActivities = new ArrayList<>(activities);
         mIsEmpty = isEmpty;
         mToken = token;
@@ -86,14 +90,26 @@
 
     /**
      * Returns a token uniquely identifying the container.
-     * Since {@link WindowExtensions#VENDOR_API_LEVEL_3}
      */
-    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    @RequiresVendorApiLevel(level = 5)
     @NonNull
-    public IBinder getToken() {
+    public Token getActivityStackToken() {
         return mToken;
     }
 
+    // TODO(b/329997430): Remove it after there's no more usages.
+    /**
+     * @deprecated Use {@link #getActivityStackToken()} instead. Use this method only if
+     * {@link #getActivityStackToken()} cannot be used.
+     */
+    @RequiresVendorApiLevel(level = 5, deprecatedSince = 5)
+    @Deprecated
+    @NonNull
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+    public IBinder getToken() {
+        return mToken.getRawToken();
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
@@ -109,6 +125,7 @@
         int result = (mIsEmpty ? 1 : 0);
         result = result * 31 + mActivities.hashCode();
         result = result * 31 + mToken.hashCode();
+
         return result;
     }
 
@@ -120,4 +137,92 @@
                 + ", mToken=" + mToken
                 + '}';
     }
+
+    /**
+     * A unique identifier to represent an {@link ActivityStack}.
+     */
+    public static final class Token {
+
+        /**
+         * An invalid token to provide compatibility value before vendor API level 5.
+         */
+        @NonNull
+        public static final Token INVALID_ACTIVITY_STACK_TOKEN = new Token(new Binder());
+
+        private static final String KEY_ACTIVITY_STACK_RAW_TOKEN = "androidx.window.extensions"
+                + ".embedding.ActivityStack.Token";
+
+        private final IBinder mToken;
+
+        Token(@NonNull IBinder token) {
+            mToken = token;
+        }
+
+        /**
+         * Creates an {@link ActivityStack} token from binder.
+         *
+         * @param token the raw binder used by OEM Extensions implementation.
+         */
+        @RequiresVendorApiLevel(level = 5)
+        @NonNull
+        public static Token createFromBinder(@NonNull IBinder token) {
+            return new Token(token);
+        }
+
+        /**
+         * Retrieves an {@link ActivityStack} token from {@link Bundle} if it's valid.
+         *
+         * @param bundle the {@link Bundle} to retrieve the {@link ActivityStack} token from.
+         * @throws IllegalArgumentException if the {@code bundle} isn't valid.
+         */
+        @RequiresVendorApiLevel(level = 5)
+        @NonNull
+        public static Token readFromBundle(@NonNull Bundle bundle) {
+            final IBinder token = bundle.getBinder(KEY_ACTIVITY_STACK_RAW_TOKEN);
+
+            if (token == null) {
+                throw new IllegalArgumentException("Invalid bundle to create ActivityStack Token");
+            }
+            return new Token(token);
+        }
+
+        /**
+         * Converts the token to {@link Bundle}.
+         * <p>
+         * See {@link ActivityEmbeddingOptionsProperties#KEY_ACTIVITY_STACK_TOKEN} for sample usage.
+         */
+        @RequiresVendorApiLevel(level = 5)
+        @NonNull
+        public Bundle toBundle() {
+            final Bundle bundle = new Bundle();
+            bundle.putBinder(KEY_ACTIVITY_STACK_RAW_TOKEN, mToken);
+            return bundle;
+        }
+
+        @NonNull
+        IBinder getRawToken() {
+            return mToken;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (!(o instanceof Token)) return false;
+            Token token = (Token) o;
+            return Objects.equals(mToken, token.mToken);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mToken);
+        }
+
+        @NonNull
+        @Override
+        public String toString() {
+            return "Token{"
+                    + "mToken=" + mToken
+                    + '}';
+        }
+    }
 }
diff --git a/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/AnimationBackground.java b/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/AnimationBackground.java
new file mode 100644
index 0000000..0ca251e
--- /dev/null
+++ b/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/AnimationBackground.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window.extensions.embedding;
+
+import android.graphics.Color;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.window.extensions.RequiresVendorApiLevel;
+
+import java.util.Objects;
+
+/**
+ * A class to represent the background to show while animating embedding activity containers if the
+ * animation requires a background.
+ *
+ * @see SplitAttributes.Builder#setAnimationBackground
+ */
+public abstract class AnimationBackground {
+
+    /**
+     * The special {@link AnimationBackground} object representing the default option.
+     * When used, the system will determine the color to use, such as using the current theme
+     * window background color.
+     */
+    @RequiresVendorApiLevel(level = 5)
+    @NonNull
+    public static final AnimationBackground ANIMATION_BACKGROUND_DEFAULT = new DefaultBackground();
+
+    /**
+     * Creates a {@link ColorBackground} that wraps the given color.
+     * Only opaque background is supported.
+     *
+     * @param color the color to be stored.
+     * @throws IllegalArgumentException if the color is not opaque.
+     */
+    @RequiresVendorApiLevel(level = 5)
+    @NonNull
+    public static ColorBackground createColorBackground(@ColorInt int color) {
+        return new ColorBackground(color);
+    }
+
+    private AnimationBackground() {}
+
+    /** @see #ANIMATION_BACKGROUND_DEFAULT */
+    private static class DefaultBackground extends AnimationBackground {
+        @Override
+        public String toString() {
+            return DefaultBackground.class.getSimpleName();
+        }
+    }
+
+    /**
+     * An {@link AnimationBackground} to specify of using a developer-defined color as the
+     * animation background.
+     * Only opaque background is supported.
+     *
+     * @see #createColorBackground(int)
+     */
+    @RequiresVendorApiLevel(level = 5)
+    public static class ColorBackground extends AnimationBackground {
+
+        @ColorInt
+        private final int mColor;
+
+        private ColorBackground(@ColorInt int color) {
+            final int alpha = Color.alpha(color);
+            if (alpha != 255) {
+                throw new IllegalArgumentException(
+                        "Color must be fully opaque, current alpha is " + alpha);
+            }
+            mColor = color;
+        }
+
+        /**
+         * Returns the color to use as the animation background.
+         */
+        @RequiresVendorApiLevel(level = 5)
+        @ColorInt
+        public int getColor() {
+            return mColor;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (!(o instanceof ColorBackground)) return false;
+            final ColorBackground that = (ColorBackground) o;
+            return mColor == that.mColor;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mColor);
+        }
+
+        @NonNull
+        @Override
+        public String toString() {
+            return ColorBackground.class.getSimpleName() + " { color: " + mColor + " }";
+        }
+    }
+}
diff --git a/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/SplitAttributes.java b/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/SplitAttributes.java
index c5c4c78..844443e 100644
--- a/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/SplitAttributes.java
+++ b/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/SplitAttributes.java
@@ -16,27 +16,25 @@
 
 package androidx.window.extensions.embedding;
 
-import static androidx.annotation.RestrictTo.Scope.LIBRARY;
 import static androidx.window.extensions.embedding.SplitAttributes.LayoutDirection.BOTTOM_TO_TOP;
 import static androidx.window.extensions.embedding.SplitAttributes.LayoutDirection.LEFT_TO_RIGHT;
 import static androidx.window.extensions.embedding.SplitAttributes.LayoutDirection.LOCALE;
 import static androidx.window.extensions.embedding.SplitAttributes.LayoutDirection.RIGHT_TO_LEFT;
 import static androidx.window.extensions.embedding.SplitAttributes.LayoutDirection.TOP_TO_BOTTOM;
+import static androidx.window.extensions.embedding.WindowAttributes.DIM_AREA_ON_TASK;
 
 import android.annotation.SuppressLint;
-import android.graphics.Color;
 
-import androidx.annotation.ColorInt;
 import androidx.annotation.FloatRange;
 import androidx.annotation.IntDef;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
-import androidx.annotation.RestrictTo;
 import androidx.window.extensions.RequiresVendorApiLevel;
 import androidx.window.extensions.core.util.function.Function;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
 
 /**
  * Attributes that describe how the parent window (typically the activity task
@@ -50,9 +48,9 @@
  *         vertically or horizontally and in which direction the primary and
  *         secondary containers are respectively positioned (left to right,
  *         right to left, top to bottom, and so forth)</li>
- *     <li>Animation background color -- The color of the background during
- *         animation of the split involving this {@code SplitAttributes} object
- *         if the animation requires a background</li>
+ *     <li>Animation background -- The background to show during animation of
+ *         the split involving this {@code SplitAttributes} object if the
+ *         animation requires a background</li>
  * </ul>
  *
  * <p>Attributes can be configured by:
@@ -67,24 +65,12 @@
  *
  * @see SplitAttributes.SplitType
  * @see SplitAttributes.LayoutDirection
+ * @see AnimationBackground
  */
 @RequiresVendorApiLevel(level = 2)
 public class SplitAttributes {
 
     /**
-     * The default value for animation background color, which means to use the current theme window
-     * background color.
-     *
-     * Only opaque color is supported, so {@code 0} is used as the default. Any other non-opaque
-     * color will be treated as the default.
-     *
-     * @see Builder#setAnimationBackgroundColor(int)
-     */
-    @ColorInt
-    @RestrictTo(LIBRARY)
-    public static final int DEFAULT_ANIMATION_BACKGROUND_COLOR = 0;
-
-    /**
      * The type of window split, which defines the proportion of the parent
      * window occupied by the primary and secondary activity containers.
      */
@@ -132,8 +118,9 @@
         }
 
         /**
-         * A window split that's based on the ratio of the size of the primary
-         * container to the size of the parent window.
+         * A window split that's based on the ratio of the size of the primary container to the
+         * size of the parent window (excluding area unavailable for the containers such as the
+         * divider.
          *
          * <p>Values in the non-inclusive range (0.0, 1.0) define the size of
          * the primary container relative to the size of the parent window:
@@ -155,11 +142,12 @@
             /**
              * Creates an instance of this {@code RatioSplitType}.
              *
-             * @param ratio The proportion of the parent window occupied by the
-             *     primary container of the split. Can be a value in the
-             *     non-inclusive range (0.0, 1.0). Use
-             *     {@link SplitType.ExpandContainersSplitType} to create a split
-             *     type that occupies the entire parent window.
+             * @param ratio The proportion of the parent window occupied by the primary container
+             *              of the split (excluding area unavailable for the containers such as
+             *              the divider. Can be a value in the
+             *              non-inclusive range (0.0, 1.0). Use
+             *              {@link SplitType.ExpandContainersSplitType} to create a split
+             *              type that occupies the entire parent window.
              */
             public RatioSplitType(
                     @FloatRange(from = 0.0, to = 1.0, fromInclusive = false, toInclusive = false)
@@ -173,11 +161,12 @@
             }
 
             /**
-             * Gets the proportion of the parent window occupied by the primary
-             * activity container of the split.
+             * Gets the proportion of the parent window occupied by the primary activity
+             * container of the split (excluding area unavailable for the containers such as the
+             * divider.
              *
              * @return The proportion of the split occupied by the primary
-             *     container.
+             * container.
              */
             @FloatRange(from = 0.0, to = 1.0, fromInclusive = false, toInclusive = false)
             public float getRatio() {
@@ -193,7 +182,7 @@
              * specified.
              *
              * @return A {@code RatioSplitType} in which the activity containers
-             *     occupy equal portions of the parent window.
+             * occupy equal portions of the parent window.
              */
             @NonNull
             public static RatioSplitType splitEqually() {
@@ -235,9 +224,9 @@
              * Creates an instance of this {@code HingeSplitType}.
              *
              * @param fallbackSplitType The split type to use if a split based
-             *     on the device hinge or separating fold cannot be determined.
-             *     Can be a {@link RatioSplitType} or
-             *     {@link ExpandContainersSplitType}.
+             *                          on the device hinge or separating fold cannot be determined.
+             *                          Can be a {@link RatioSplitType} or
+             *                          {@link ExpandContainersSplitType}.
              */
             public HingeSplitType(@NonNull SplitType fallbackSplitType) {
                 super("hinge, fallbackType=" + fallbackSplitType);
@@ -284,15 +273,15 @@
          *
          * A possible return value of {@link SplitType#getLayoutDirection()}.
          */
-         //
-         // -------------------------
-         // |           |           |
-         // |  Primary  | Secondary |
-         // |           |           |
-         // -------------------------
-         //
-         // Must match {@link LayoutDirection#LTR} for backwards compatibility
-         // with prior versions of Extensions.
+        //
+        // -------------------------
+        // |           |           |
+        // |  Primary  | Secondary |
+        // |           |           |
+        // -------------------------
+        //
+        // Must match {@link LayoutDirection#LTR} for backwards compatibility
+        // with prior versions of Extensions.
         public static final int LEFT_TO_RIGHT = 0;
 
         /**
@@ -304,14 +293,14 @@
          *
          * A possible return value of {@link SplitType#getLayoutDirection()}.
          */
-         // -------------------------
-         // |           |           |
-         // | Secondary |  Primary  |
-         // |           |           |
-         // -------------------------
-         //
-         // Must match {@link LayoutDirection#RTL} for backwards compatibility
-         // with prior versions of Extensions.
+        // -------------------------
+        // |           |           |
+        // | Secondary |  Primary  |
+        // |           |           |
+        // -------------------------
+        //
+        // Must match {@link LayoutDirection#RTL} for backwards compatibility
+        // with prior versions of Extensions.
         public static final int RIGHT_TO_LEFT = 1;
 
         /**
@@ -323,8 +312,8 @@
          *
          * A possible return value of {@link SplitType#getLayoutDirection()}.
          */
-         // Must match {@link LayoutDirection#LOCALE} for backwards
-         // compatibility with prior versions of Extensions.
+        // Must match {@link LayoutDirection#LOCALE} for backwards
+        // compatibility with prior versions of Extensions.
         public static final int LOCALE = 3;
 
         /**
@@ -339,15 +328,15 @@
          *
          * A possible return value of {@link SplitType#getLayoutDirection()}.
          */
-         // -------------
-         // |           |
-         // |  Primary  |
-         // |           |
-         // -------------
-         // |           |
-         // | Secondary |
-         // |           |
-         // -------------
+        // -------------
+        // |           |
+        // |  Primary  |
+        // |           |
+        // -------------
+        // |           |
+        // | Secondary |
+        // |           |
+        // -------------
         public static final int TOP_TO_BOTTOM = 4;
 
         /**
@@ -362,49 +351,62 @@
          *
          * A possible return value of {@link SplitType#getLayoutDirection()}.
          */
-         // -------------
-         // |           |
-         // | Secondary |
-         // |           |
-         // -------------
-         // |           |
-         // |  Primary  |
-         // |           |
-         // -------------
+        // -------------
+        // |           |
+        // | Secondary |
+        // |           |
+        // -------------
+        // |           |
+        // |  Primary  |
+        // |           |
+        // -------------
         public static final int BOTTOM_TO_TOP = 5;
 
-        private LayoutDirection() {}
+        private LayoutDirection() {
+        }
     }
 
     @IntDef({LEFT_TO_RIGHT, RIGHT_TO_LEFT, LOCALE, TOP_TO_BOTTOM, BOTTOM_TO_TOP})
     @Retention(RetentionPolicy.SOURCE)
-    @interface ExtLayoutDirection {}
+    @interface ExtLayoutDirection {
+    }
 
     @ExtLayoutDirection
     private final int mLayoutDirection;
 
+    @NonNull
     private final SplitType mSplitType;
 
-    @ColorInt
-    private final int mAnimationBackgroundColor;
+    @NonNull
+    private final AnimationBackground mAnimationBackground;
+
+    @NonNull
+    private final WindowAttributes mWindowAttributes;
 
     /**
      * Creates an instance of this {@code SplitAttributes}.
      *
-     * @param splitType The type of split. See
-     *     {@link SplitAttributes.SplitType}.
-     * @param layoutDirection The layout direction of the split, such as left to
-     *     right or top to bottom. See {@link SplitAttributes.LayoutDirection}.
-     * @param animationBackgroundColor The {@link ColorInt} to use for the
-     *     background color during animation of the split involving this
-     *     {@code SplitAttributes} object if the animation requires a
-     *     background.
+     * @param splitType           The type of split. See
+     *                            {@link SplitAttributes.SplitType}.
+     * @param layoutDirection     The layout direction of the split, such as left to
+     *                            right or top to bottom. See
+     *                            {@link SplitAttributes.LayoutDirection}.
+     * @param animationBackground The {@link AnimationBackground} to use for the during animation
+     *                            of the split involving this {@code SplitAttributes} object if the
+     *                            animation requires a background.
+     * @param attributes          The {@link WindowAttributes} of the split, such as dim area
+     *                            behavior.
      */
-    SplitAttributes(@NonNull SplitType splitType, @ExtLayoutDirection int layoutDirection,
-            @ColorInt int animationBackgroundColor) {
+    SplitAttributes(
+            @NonNull SplitType splitType,
+            @ExtLayoutDirection int layoutDirection,
+            @NonNull AnimationBackground animationBackground,
+            @NonNull WindowAttributes attributes
+    ) {
         mSplitType = splitType;
         mLayoutDirection = layoutDirection;
-        mAnimationBackgroundColor = animationBackgroundColor;
+        mAnimationBackground = animationBackground;
+        mWindowAttributes = attributes;
     }
 
     /**
@@ -428,18 +430,23 @@
     }
 
     /**
-     * Gets the {@link ColorInt} to use for the background color during the
+     * Returns the {@link AnimationBackground} to use for the background during the
      * animation of the split involving this {@code SplitAttributes} object.
-     *
-     * The default is {@link #DEFAULT_ANIMATION_BACKGROUND_COLOR}, which means
-     * to use the current theme window background color.
-     *
-     * @return The animation background {@code ColorInt}.
      */
-    @ColorInt
-    @RestrictTo(LIBRARY)
-    public int getAnimationBackgroundColor() {
-        return mAnimationBackgroundColor;
+    @NonNull
+    @RequiresVendorApiLevel(level = 5)
+    public AnimationBackground getAnimationBackground() {
+        return mAnimationBackground;
+    }
+
+    /**
+     * Returns the {@link WindowAttributes} which contains the configurations of the embedded
+     * Activity windows in this SplitAttributes.
+     */
+    @NonNull
+    @RequiresVendorApiLevel(level = 5)
+    public WindowAttributes getWindowAttributes() {
+        return mWindowAttributes;
     }
 
     /**
@@ -447,16 +454,25 @@
      *
      * - The default split type is an equal split between primary and secondary containers.
      * - The default layout direction is based on locale.
-     * - The default animation background color is to use the current theme window background color.
+     * - The default animation background is to use the current theme window background color.
      */
     public static final class Builder {
         @NonNull
-        private SplitType mSplitType =  new SplitType.RatioSplitType(0.5f);
+        private SplitType mSplitType = new SplitType.RatioSplitType(0.5f);
         @ExtLayoutDirection
         private int mLayoutDirection = LOCALE;
 
-        @ColorInt
-        private int mAnimationBackgroundColor = 0;
+        @NonNull
+        private AnimationBackground mAnimationBackground =
+                AnimationBackground.ANIMATION_BACKGROUND_DEFAULT;
+
+        @NonNull
+        private WindowAttributes mWindowAttributes =
+                new WindowAttributes(DIM_AREA_ON_TASK);
+
+        /** Creates a new {@link Builder} to create {@link SplitAttributes}. */
+        public Builder() {
+        }
 
         /**
          * Sets the split type attribute.
@@ -498,64 +514,66 @@
         }
 
         /**
-         * Sets the {@link ColorInt} to use for the background during the
+         * Sets the {@link AnimationBackground} to use for the background during the
          * animation of the split involving this {@code SplitAttributes} object
          * if the animation requires a background.
          *
-         * Only opaque color is supported.
+         * The default value is {@link AnimationBackground#ANIMATION_BACKGROUND_DEFAULT}, which
+         * means to use the current theme window background color.
          *
-         * The default value is {@link #DEFAULT_ANIMATION_BACKGROUND_COLOR}, which
-         * means to use the current theme window background color. Any non-opaque
-         * animation color will be treated as
-         * {@link #DEFAULT_ANIMATION_BACKGROUND_COLOR}.
-         *
-         * @param color A packed color int of the form {@code AARRGGBB} for the
-         *              animation background color.
+         * @param background An {@link AnimationBackground} to be used for the animation of the
+         *                   split.
          * @return This {@code Builder}.
          */
         @NonNull
-        @RestrictTo(LIBRARY)
-        public Builder setAnimationBackgroundColor(@ColorInt int color) {
-            // Any non-opaque color will be treated as the default.
-            mAnimationBackgroundColor = Color.alpha(color) != 255
-                    ? DEFAULT_ANIMATION_BACKGROUND_COLOR
-                    : color;
+        @RequiresVendorApiLevel(level = 5)
+        public Builder setAnimationBackground(@NonNull AnimationBackground background) {
+            mAnimationBackground = background;
+            return this;
+        }
+
+        /**
+         * Sets the window attributes. If this value is not specified, the
+         * {@link WindowAttributes#getDimAreaBehavior()} will be only applied on the
+         * {@link ActivityStack} of the requested activity.
+         *
+         * @param attributes The {@link WindowAttributes}
+         * @return This {@code Builder}.
+         */
+        @NonNull
+        @RequiresVendorApiLevel(level = 5)
+        public Builder setWindowAttributes(@NonNull WindowAttributes attributes) {
+            mWindowAttributes = attributes;
             return this;
         }
 
         /**
          * Builds a {@link SplitAttributes} instance with the attributes
          * specified by {@link #setSplitType}, {@link #setLayoutDirection}, and
-         * {@link #setAnimationBackgroundColor}.
+         * {@link #setAnimationBackground}.
          *
          * @return The new {@code SplitAttributes} instance.
          */
         @NonNull
         public SplitAttributes build() {
-            return new SplitAttributes(mSplitType, mLayoutDirection, mAnimationBackgroundColor);
+            return new SplitAttributes(mSplitType, mLayoutDirection, mAnimationBackground,
+                    mWindowAttributes);
         }
     }
 
     @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof SplitAttributes)) return false;
+        SplitAttributes that = (SplitAttributes) o;
+        return mLayoutDirection == that.mLayoutDirection && mSplitType.equals(that.mSplitType)
+                && mAnimationBackground.equals(that.mAnimationBackground)
+                && mWindowAttributes.equals(that.mWindowAttributes);
+    }
+
+    @Override
     public int hashCode() {
-        int result = mSplitType.hashCode();
-        result = result * 31 + mLayoutDirection;
-        result = result * 31 + mAnimationBackgroundColor;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object other) {
-        if (other == this) {
-            return true;
-        }
-        if (!(other instanceof SplitAttributes)) {
-            return false;
-        }
-        final SplitAttributes otherAttributes = (SplitAttributes) other;
-        return mLayoutDirection == otherAttributes.mLayoutDirection
-                && mSplitType.equals(otherAttributes.mSplitType)
-                && mAnimationBackgroundColor == otherAttributes.mAnimationBackgroundColor;
+        return Objects.hash(mLayoutDirection, mSplitType, mAnimationBackground, mWindowAttributes);
     }
 
     @NonNull
@@ -563,14 +581,15 @@
     public String toString() {
         return SplitAttributes.class.getSimpleName() + "{"
                 + "layoutDir=" + layoutDirectionToString()
-                + ", ratio=" + mSplitType
-                + ", animationBgColor=" + Integer.toHexString(mAnimationBackgroundColor)
+                + ", splitType=" + mSplitType
+                + ", animationBackground=" + mAnimationBackground
+                + ", windowAttributes=" + mWindowAttributes
                 + "}";
     }
 
     @NonNull
     private String layoutDirectionToString() {
-        switch(mLayoutDirection) {
+        switch (mLayoutDirection) {
             case LEFT_TO_RIGHT:
                 return "LEFT_TO_RIGHT";
             case RIGHT_TO_LEFT:
diff --git a/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/SplitAttributesCalculatorParams.java b/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/SplitAttributesCalculatorParams.java
index 80f98fe..723a96f 100644
--- a/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/SplitAttributesCalculatorParams.java
+++ b/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/SplitAttributesCalculatorParams.java
@@ -17,12 +17,11 @@
 package androidx.window.extensions.embedding;
 
 import android.content.res.Configuration;
-import android.os.Build;
 import android.view.WindowMetrics;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
+import androidx.window.extensions.RequiresVendorApiLevel;
 import androidx.window.extensions.layout.WindowLayoutInfo;
 
 /**
@@ -32,8 +31,8 @@
  * {@link SplitRule} by {@link #getSplitRuleTag()} if {@link SplitRule#getTag()} is specified.
  *
  * @see ActivityEmbeddingComponent#clearSplitAttributesCalculator()
- * Since {@link androidx.window.extensions.WindowExtensions#VENDOR_API_LEVEL_2}
  */
+@RequiresVendorApiLevel(level = 2)
 public class SplitAttributesCalculatorParams {
     @NonNull
     private final WindowMetrics mParentWindowMetrics;
@@ -121,29 +120,11 @@
     @Override
     public String toString() {
         return getClass().getSimpleName() + ":{"
-                + "windowMetrics=" + windowMetricsToString(mParentWindowMetrics)
+                + "windowMetrics=" + WindowMetricsCompat.toString(mParentWindowMetrics)
                 + ", configuration=" + mParentConfiguration
                 + ", windowLayoutInfo=" + mParentWindowLayoutInfo
                 + ", defaultSplitAttributes=" + mDefaultSplitAttributes
                 + ", areDefaultConstraintsSatisfied=" + mAreDefaultConstraintsSatisfied
                 + ", tag=" + mSplitRuleTag + "}";
     }
-
-    private static String windowMetricsToString(@NonNull WindowMetrics windowMetrics) {
-        // TODO(b/187712731): Use WindowMetrics#toString after it's implemented in U.
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
-            return Api30Impl.windowMetricsToString(windowMetrics);
-        }
-        throw new UnsupportedOperationException("WindowMetrics didn't exist in R.");
-    }
-
-    @RequiresApi(30)
-    private static final class Api30Impl {
-        static String windowMetricsToString(@NonNull WindowMetrics windowMetrics) {
-            return WindowMetrics.class.getSimpleName() + ":{"
-                    + "bounds=" + windowMetrics.getBounds()
-                    + ", windowInsets=" + windowMetrics.getWindowInsets()
-                    + "}";
-        }
-    }
 }
diff --git a/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/SplitInfo.java b/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/SplitInfo.java
index 7b79b1c..b8d9c66 100644
--- a/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/SplitInfo.java
+++ b/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/SplitInfo.java
@@ -35,7 +35,7 @@
     private final SplitAttributes mSplitAttributes;
 
     @NonNull
-    private final IBinder mToken;
+    private final Token mToken;
 
     /**
      * The {@code SplitInfo} constructor
@@ -48,7 +48,7 @@
     SplitInfo(@NonNull ActivityStack primaryActivityStack,
             @NonNull ActivityStack secondaryActivityStack,
             @NonNull SplitAttributes splitAttributes,
-            @NonNull IBinder token) {
+            @NonNull Token token) {
         Objects.requireNonNull(primaryActivityStack);
         Objects.requireNonNull(secondaryActivityStack);
         Objects.requireNonNull(splitAttributes);
@@ -91,10 +91,18 @@
         return mSplitAttributes;
     }
 
-    /** Returns a token uniquely identifying the container. */
-    @RequiresVendorApiLevel(level = 3)
+    /** @deprecated Use {@link #getSplitInfoToken()} instead. */
+    @Deprecated
+    @RequiresVendorApiLevel(level = 3, deprecatedSince = 5)
     @NonNull
     public IBinder getToken() {
+        return mToken.getRawToken();
+    }
+
+    /** Returns a token uniquely identifying the split. */
+    @RequiresVendorApiLevel(level = 5)
+    @NonNull
+    public Token getSplitInfoToken() {
         return mToken;
     }
 
@@ -127,4 +135,54 @@
                 + ", mToken=" + mToken
                 + '}';
     }
+
+    /**
+     * A unique identifier to represent the split.
+     */
+    public static final class Token {
+
+        @NonNull
+        private final IBinder mToken;
+
+        Token(@NonNull IBinder token) {
+            mToken = token;
+        }
+
+        @NonNull
+        IBinder getRawToken() {
+            return mToken;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (!(o instanceof Token)) return false;
+            Token token = (Token) o;
+            return Objects.equals(mToken, token.mToken);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mToken);
+        }
+
+        @NonNull
+        @Override
+        public String toString() {
+            return "Token{"
+                    + "mToken=" + mToken
+                    + '}';
+        }
+
+        /**
+         * Creates a split token from binder.
+         *
+         * @param token the raw binder used by OEM Extensions implementation.
+         */
+        @RequiresVendorApiLevel(level = 5)
+        @NonNull
+        public static Token createFromBinder(@NonNull IBinder token) {
+            return new Token(token);
+        }
+    }
 }
diff --git a/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/SplitPinRule.java b/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/SplitPinRule.java
new file mode 100644
index 0000000..09932fc8
--- /dev/null
+++ b/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/SplitPinRule.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window.extensions.embedding;
+
+import android.view.WindowMetrics;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.window.extensions.RequiresVendorApiLevel;
+import androidx.window.extensions.core.util.function.Predicate;
+
+import java.util.Objects;
+
+/**
+ * Split configuration rules for keeping an {@link ActivityStack} in the split in a pin state to
+ * provide an isolated Activity navigation from the split. A pin state here is referring the
+ * {@link ActivityStack} to be fixed on top.
+ *
+ * @see ActivityEmbeddingComponent#pinTopActivityStack
+ */
+@RequiresVendorApiLevel(level = 5)
+public class SplitPinRule extends SplitRule {
+    /**
+     * Whether the rule should be applied whenever the parent Task satisfied the parent window
+     * metrics predicate. See {@link ActivityEmbeddingComponent#pinTopActivityStack}.
+     */
+    private final boolean mIsSticky;
+
+    SplitPinRule(@NonNull SplitAttributes defaultSplitAttributes,
+            @NonNull Predicate<WindowMetrics> parentWindowMetricsPredicate,
+            boolean isSticky, @Nullable String tag) {
+        super(parentWindowMetricsPredicate, defaultSplitAttributes, tag);
+        mIsSticky = isSticky;
+    }
+
+    /**
+     * Whether the rule is sticky. This configuration rule can only be applied once when
+     * possible. That is, the rule will be abandoned whenever the pinned {@link ActivityStack} no
+     * longer able to be split with another {@link ActivityStack} once the configuration of the
+     * parent Task is changed. Sets the rule to be sticky if the rule should be permanent until
+     * the {@link ActivityStack} explicitly unpin.
+     *
+     * @see ActivityEmbeddingComponent#pinTopActivityStack
+     */
+    public boolean isSticky() {
+        return mIsSticky;
+    }
+
+    /**
+     * Builder for {@link SplitPinRule}.
+     */
+    public static final class Builder {
+        @NonNull
+        private final SplitAttributes mDefaultSplitAttributes;
+        @NonNull
+        private final Predicate<WindowMetrics> mParentWindowMetricsPredicate;
+        private boolean mIsSticky;
+        @Nullable
+        private String mTag;
+
+        /**
+         * The {@link SplitPinRule} builder constructor.
+         *
+         * @param defaultSplitAttributes the default {@link SplitAttributes} to apply
+         * @param parentWindowMetricsPredicate the {@link Predicate} to verify if the pinned
+         *                                     {@link ActivityStack} and the one behind are
+         *                                     allowed to show adjacent to each other with the
+         *                                     given parent {@link WindowMetrics}
+         */
+        public Builder(@NonNull SplitAttributes defaultSplitAttributes,
+                @NonNull Predicate<WindowMetrics> parentWindowMetricsPredicate) {
+            mDefaultSplitAttributes = defaultSplitAttributes;
+            mParentWindowMetricsPredicate = parentWindowMetricsPredicate;
+        }
+
+        /**
+         * Sets the rule to be sticky.
+         *
+         * @see SplitPinRule#isSticky()
+         */
+        @NonNull
+        public Builder setSticky(boolean isSticky) {
+            mIsSticky = isSticky;
+            return this;
+        }
+
+        /**
+         * @see SplitPinRule#getTag()
+         */
+        @NonNull
+        public Builder setTag(@NonNull String tag) {
+            mTag =  Objects.requireNonNull(tag);
+            return this;
+        }
+
+        /**
+         * Builds a new instance of {@link SplitPinRule}.
+         */
+        @NonNull
+        public SplitPinRule build() {
+            return new SplitPinRule(mDefaultSplitAttributes, mParentWindowMetricsPredicate,
+                    mIsSticky, mTag);
+        }
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof SplitPinRule)) return false;
+        SplitPinRule that = (SplitPinRule) o;
+        return super.equals(o)
+                && mIsSticky == that.mIsSticky;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + (mIsSticky ? 1 : 0);
+        return result;
+    }
+
+    @NonNull
+    @Override
+    public String toString() {
+        return "SplitPinRule{"
+                + "mTag=" + getTag()
+                + ", mDefaultSplitAttributes=" + getDefaultSplitAttributes()
+                + ", mIsSticky=" + mIsSticky
+                + '}';
+    }
+}
diff --git a/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/SplitPlaceholderRule.java b/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/SplitPlaceholderRule.java
index 9f2b5e9..29d60b7 100644
--- a/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/SplitPlaceholderRule.java
+++ b/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/SplitPlaceholderRule.java
@@ -129,7 +129,6 @@
      * Determines what happens with the primary container when all activities are finished in the
      * associated secondary/placeholder container.
      */
-    // TODO(b/238905747): Add api guard for extensions.
     @RequiresVendorApiLevel(level = 2)
     @SplitPlaceholderFinishBehavior
     public int getFinishPrimaryWithPlaceholder() {
@@ -270,7 +269,6 @@
         /**
          * @see SplitPlaceholderRule#getFinishPrimaryWithPlaceholder()
          */
-        // TODO(b/238905747): Add api guard for extensions.
         @RequiresVendorApiLevel(level = 2)
         @NonNull
         public Builder setFinishPrimaryWithPlaceholder(
diff --git a/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/WindowAttributes.java b/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/WindowAttributes.java
new file mode 100644
index 0000000..8f3d6ad
--- /dev/null
+++ b/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/WindowAttributes.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window.extensions.embedding;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.window.extensions.RequiresVendorApiLevel;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * The attributes of the embedded Activity Window.
+ */
+public final class WindowAttributes {
+
+    /**
+     * The dim effect is applying on the {@link ActivityStack} of the Activity window when
+     * needed. If the {@link ActivityStack} is not expanded to fill the parent container, the dim
+     * effect is applying only on the {@link ActivityStack} of
+     * the requested Activity.
+     */
+    public static final int DIM_AREA_ON_ACTIVITY_STACK = 1;
+
+    /**
+     * The dim effect is applying on the area of the whole Task when needed. If the embedded
+     * transparent activity is split and displayed side-by-side with another activity, the dim
+     * effect is applying on the Task, which across over the two {@link ActivityStack}s.
+     */
+    public static final int DIM_AREA_ON_TASK = 2;
+
+    @IntDef({
+            DIM_AREA_ON_ACTIVITY_STACK,
+            DIM_AREA_ON_TASK
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    @interface DimAreaBehavior {
+    }
+
+    @DimAreaBehavior
+    private final int mDimAreaBehavior;
+
+    /**
+     * The {@link WindowAttributes} constructor.
+     *
+     * @param dimAreaBehavior the type of area that the dim layer is applying.
+     */
+    @RequiresVendorApiLevel(level = 5)
+    public WindowAttributes(@DimAreaBehavior int dimAreaBehavior) {
+        mDimAreaBehavior = dimAreaBehavior;
+    }
+
+    /**
+     * Returns the {@link DimAreaBehavior} to use when dim behind the Activity window is
+     * needed.
+     * @return The dim area behavior.
+     */
+    @DimAreaBehavior
+    @RequiresVendorApiLevel(level = 5)
+    public int getDimAreaBehavior() {
+        return mDimAreaBehavior;
+    }
+
+    @Override
+    public boolean equals(@Nullable Object obj) {
+        if (this == obj) return true;
+        if (obj == null || !(obj instanceof WindowAttributes)) return false;
+        final WindowAttributes other = (WindowAttributes) obj;
+        return mDimAreaBehavior == other.getDimAreaBehavior();
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mDimAreaBehavior);
+    }
+
+    @NonNull
+    @Override
+    public String toString() {
+        return "dimAreaBehavior=" + mDimAreaBehavior;
+    }
+}
diff --git a/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/WindowMetricsCompat.java b/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/WindowMetricsCompat.java
new file mode 100644
index 0000000..8f99d11
--- /dev/null
+++ b/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/WindowMetricsCompat.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window.extensions.embedding;
+
+import android.os.Build;
+import android.view.WindowMetrics;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+
+/**
+ * A helper class to access {@link WindowMetrics#toString()} with compatibility.
+ */
+class WindowMetricsCompat {
+    private WindowMetricsCompat() {}
+
+    @NonNull
+    static String toString(@NonNull WindowMetrics windowMetrics) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
+            // WindowMetrics#toString is implemented in U.
+            return windowMetrics.toString();
+        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+            return Api30Impl.toString(windowMetrics);
+        }
+        // Should be safe since ActivityEmbedding is not enabled before R.
+        throw new UnsupportedOperationException("WindowMetrics didn't exist in R.");
+    }
+
+    @RequiresApi(30)
+    private static final class Api30Impl {
+        @NonNull
+        static String toString(@NonNull WindowMetrics windowMetrics) {
+            return WindowMetrics.class.getSimpleName() + ":{"
+                    + "bounds=" + windowMetrics.getBounds()
+                    + ", windowInsets=" + windowMetrics.getWindowInsets()
+                    + "}";
+        }
+    }
+}
diff --git a/window/extensions/extensions/src/main/java/androidx/window/extensions/util/SetCompat.java b/window/extensions/extensions/src/main/java/androidx/window/extensions/util/SetCompat.java
new file mode 100644
index 0000000..15305f2d
--- /dev/null
+++ b/window/extensions/extensions/src/main/java/androidx/window/extensions/util/SetCompat.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window.extensions.util;
+
+import android.os.Build;
+import android.util.ArraySet;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.annotation.RestrictTo;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A {@link Set} wrapper for compatibility. It {@link ArraySet} if it's available, and uses
+ * other compatible {@link Set} class, otherwise.
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+public final class SetCompat {
+
+    private SetCompat() {}
+
+    /**
+     * Creates a {@link Set}.
+     *
+     * @param <T> the type of the {@link Set}.
+     */
+    @NonNull
+    public static <T> Set<T> create() {
+        if (Build.VERSION.SDK_INT < 23) {
+            return new HashSet<>();
+        } else {
+            return Api23Impl.create();
+        }
+    }
+
+    @RequiresApi(23)
+    private static class Api23Impl {
+
+        @NonNull
+        static <T> Set<T> create() {
+            return new ArraySet<>();
+        }
+    }
+}
diff --git a/window/extensions/extensions/src/main/java/androidx/window/extensions/util/SetUtilApi23.java b/window/extensions/extensions/src/main/java/androidx/window/extensions/util/SetUtilApi23.java
new file mode 100644
index 0000000..c7896a1
--- /dev/null
+++ b/window/extensions/extensions/src/main/java/androidx/window/extensions/util/SetUtilApi23.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window.extensions.util;
+
+import android.util.ArraySet;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.annotation.RestrictTo;
+
+import java.util.Set;
+
+/**
+ * Set utilities for creating working with newer {@link ArraySet} apis.
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+@RequiresApi(23)
+public final class SetUtilApi23 {
+
+    private SetUtilApi23() {}
+
+    /**
+     * Creates an instance of {@link ArraySet}.
+     */
+    @NonNull
+    public static <T> Set<T> createSet() {
+        return new ArraySet<>();
+    }
+}
diff --git a/window/extensions/extensions/src/test/java/androidx/window/extensions/embedding/AnimationBackgroundTest.java b/window/extensions/extensions/src/test/java/androidx/window/extensions/embedding/AnimationBackgroundTest.java
new file mode 100644
index 0000000..b4475e9
--- /dev/null
+++ b/window/extensions/extensions/src/test/java/androidx/window/extensions/embedding/AnimationBackgroundTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window.extensions.embedding;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertThrows;
+
+import android.graphics.Color;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+/** Test for {@link AnimationBackground} */
+@SmallTest
+@RunWith(RobolectricTestRunner.class)
+public class AnimationBackgroundTest {
+
+    @Test
+    public void testDefaultBackground() {
+        assertEquals(AnimationBackground.ANIMATION_BACKGROUND_DEFAULT,
+                AnimationBackground.ANIMATION_BACKGROUND_DEFAULT);
+        assertFalse(AnimationBackground.ANIMATION_BACKGROUND_DEFAULT
+                instanceof AnimationBackground.ColorBackground);
+    }
+
+    @Test
+    public void testCreateColorBackground() {
+        final AnimationBackground.ColorBackground background =
+                AnimationBackground.createColorBackground(Color.BLUE);
+
+        assertEquals(Color.BLUE, background.getColor());
+        assertEquals(background, AnimationBackground.createColorBackground(
+                Color.BLUE));
+        assertNotEquals(background, AnimationBackground.createColorBackground(
+                Color.GREEN));
+        assertThrows(IllegalArgumentException.class,
+                () -> AnimationBackground.createColorBackground(Color.TRANSPARENT));
+    }
+}
diff --git a/window/extensions/extensions/src/test/java/androidx/window/extensions/embedding/SplitAttributesTest.java b/window/extensions/extensions/src/test/java/androidx/window/extensions/embedding/SplitAttributesTest.java
index 7886c84..1c998a0 100644
--- a/window/extensions/extensions/src/test/java/androidx/window/extensions/embedding/SplitAttributesTest.java
+++ b/window/extensions/extensions/src/test/java/androidx/window/extensions/embedding/SplitAttributesTest.java
@@ -36,46 +36,46 @@
 public class SplitAttributesTest {
     @Test
     public void testSplitAttributesEquals() {
-        final SplitAttributes layout1 = new SplitAttributes.Builder()
+        final SplitAttributes attrs1 = new SplitAttributes.Builder()
                 .setSplitType(splitEqually())
                 .setLayoutDirection(LayoutDirection.LOCALE)
-                .setAnimationBackgroundColor(SplitAttributes.DEFAULT_ANIMATION_BACKGROUND_COLOR)
+                .setAnimationBackground(AnimationBackground.ANIMATION_BACKGROUND_DEFAULT)
                 .build();
-        final SplitAttributes layout2 = new SplitAttributes.Builder()
+        final SplitAttributes attrs2 = new SplitAttributes.Builder()
                 .setSplitType(new SplitAttributes.SplitType.HingeSplitType(splitEqually()))
                 .setLayoutDirection(LayoutDirection.LOCALE)
-                .setAnimationBackgroundColor(SplitAttributes.DEFAULT_ANIMATION_BACKGROUND_COLOR)
+                .setAnimationBackground(AnimationBackground.ANIMATION_BACKGROUND_DEFAULT)
                 .build();
-        final SplitAttributes layout3 = new SplitAttributes.Builder()
+        final SplitAttributes attrs3 = new SplitAttributes.Builder()
                 .setSplitType(new SplitAttributes.SplitType.HingeSplitType(splitEqually()))
                 .setLayoutDirection(LayoutDirection.TOP_TO_BOTTOM)
-                .setAnimationBackgroundColor(SplitAttributes.DEFAULT_ANIMATION_BACKGROUND_COLOR)
+                .setAnimationBackground(AnimationBackground.ANIMATION_BACKGROUND_DEFAULT)
                 .build();
-        final SplitAttributes layout4 = new SplitAttributes.Builder()
+        final SplitAttributes attrs4 = new SplitAttributes.Builder()
                 .setSplitType(new SplitAttributes.SplitType.HingeSplitType(splitEqually()))
                 .setLayoutDirection(LayoutDirection.TOP_TO_BOTTOM)
-                .setAnimationBackgroundColor(Color.BLUE)
+                .setAnimationBackground(AnimationBackground.createColorBackground(Color.BLUE))
                 .build();
-        final SplitAttributes layout5 = new SplitAttributes.Builder()
+        final SplitAttributes attrs5 = new SplitAttributes.Builder()
                 .setSplitType(new SplitAttributes.SplitType.HingeSplitType(splitEqually()))
                 .setLayoutDirection(LayoutDirection.TOP_TO_BOTTOM)
-                .setAnimationBackgroundColor(Color.BLUE)
+                .setAnimationBackground(AnimationBackground.createColorBackground(Color.BLUE))
                 .build();
 
-        assertNotEquals(layout1, layout2);
-        assertNotEquals(layout1.hashCode(), layout2.hashCode());
+        assertNotEquals(attrs1, attrs2);
+        assertNotEquals(attrs1.hashCode(), attrs2.hashCode());
 
-        assertNotEquals(layout2, layout3);
-        assertNotEquals(layout2.hashCode(), layout3.hashCode());
+        assertNotEquals(attrs2, attrs3);
+        assertNotEquals(attrs2.hashCode(), attrs3.hashCode());
 
-        assertNotEquals(layout3, layout1);
-        assertNotEquals(layout3.hashCode(), layout1.hashCode());
+        assertNotEquals(attrs3, attrs1);
+        assertNotEquals(attrs3.hashCode(), attrs1.hashCode());
 
-        assertNotEquals(layout4, layout3);
-        assertNotEquals(layout4.hashCode(), layout3.hashCode());
+        assertNotEquals(attrs4, attrs3);
+        assertNotEquals(attrs4.hashCode(), attrs3.hashCode());
 
-        assertEquals(layout4, layout5);
-        assertEquals(layout4.hashCode(), layout5.hashCode());
+        assertEquals(attrs4, attrs5);
+        assertEquals(attrs4.hashCode(), attrs5.hashCode());
     }
 
     @Test
diff --git a/window/window-demos/demo/build.gradle b/window/window-demos/demo/build.gradle
index 61df674..615fea8 100644
--- a/window/window-demos/demo/build.gradle
+++ b/window/window-demos/demo/build.gradle
@@ -53,6 +53,10 @@
         }
         release {
             minifyEnabled true
+            applicationIdSuffix ".release"
+        }
+        debug {
+            applicationIdSuffix ".debug"
         }
     }
     compileOptions {
diff --git a/window/window/build.gradle b/window/window/build.gradle
index d65067d..90908f3 100644
--- a/window/window/build.gradle
+++ b/window/window/build.gradle
@@ -61,7 +61,7 @@
     // A compile only dependency on extnensions.core so that other libraries do not expose it
     // transitively. The testCompile is added because tests are not getting the dependency
     // transitively.
-    testCompileOnly(extensions_core_version)
+    testImplementation(extensions_core_version)
     // A compile only dependency on extnensions.core so that other libraries do not expose it
     // transitively. The androidTestCompile is added because tests are not getting the dependency
     // transitively.
diff --git a/window/window/proguard-rules.pro b/window/window/proguard-rules.pro
index b5faff0..7864964 100644
--- a/window/window/proguard-rules.pro
+++ b/window/window/proguard-rules.pro
@@ -28,4 +28,13 @@
 # Required to support kotlin-reflect
 -keep,allowshrinking class androidx.window.layout.adapter.extensions.MulticastConsumer {
   void accept(androidx.window.extensions.layout.WindowLayoutInfo);
+}
+-keep interface androidx.window.reflection.Consumer2 {
+  public void accept(***);
+}
+-keep interface androidx.window.reflection.Predicate2 {
+  public boolean test(***);
+}
+-keep interface androidx.window.reflection.JFunction2 {
+  public *** apply(***);
 }
\ No newline at end of file
diff --git a/window/window/src/androidTest/java/androidx/window/embedding/EmbeddingAdapterTest.kt b/window/window/src/androidTest/java/androidx/window/embedding/EmbeddingAdapterTest.kt
index 024a50e..fc53f9e 100644
--- a/window/window/src/androidTest/java/androidx/window/embedding/EmbeddingAdapterTest.kt
+++ b/window/window/src/androidTest/java/androidx/window/embedding/EmbeddingAdapterTest.kt
@@ -186,6 +186,7 @@
         assertEquals(listOf(expectedSplitInfo), adapter.translate(listOf(oemSplitInfo)))
     }
 
+    @Suppress("DEPRECATION")
     private fun createTestOEMSplitInfo(
         testPrimaryActivityStack: OEMActivityStack,
         testSecondaryActivityStack: OEMActivityStack,
@@ -204,6 +205,7 @@
         }
     }
 
+    @Suppress("DEPRECATION")
     private fun createTestOEMActivityStack(
         testActivities: List<Activity>,
         testIsEmpty: Boolean,
diff --git a/window/window/src/main/java/androidx/window/area/WindowAreaControllerImpl.kt b/window/window/src/main/java/androidx/window/area/WindowAreaControllerImpl.kt
index f2ab7b2..c8396a0 100644
--- a/window/window/src/main/java/androidx/window/area/WindowAreaControllerImpl.kt
+++ b/window/window/src/main/java/androidx/window/area/WindowAreaControllerImpl.kt
@@ -36,9 +36,9 @@
 import androidx.window.extensions.area.WindowAreaComponent.SESSION_STATE_CONTENT_VISIBLE
 import androidx.window.extensions.area.WindowAreaComponent.SESSION_STATE_INACTIVE
 import androidx.window.extensions.area.WindowAreaComponent.WindowAreaSessionState
-import androidx.window.extensions.core.util.function.Consumer
 import androidx.window.layout.WindowMetrics
 import androidx.window.layout.WindowMetricsCalculator
+import androidx.window.reflection.Consumer2
 import java.util.concurrent.Executor
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.asCoroutineDispatcher
@@ -63,7 +63,7 @@
     private val vendorApiLevel: Int
 ) : WindowAreaController {
 
-    private lateinit var rearDisplaySessionConsumer: Consumer<Int>
+    private lateinit var rearDisplaySessionConsumer: Consumer2<Int>
     private var currentRearDisplayModeStatus: WindowAreaCapability.Status =
         WINDOW_AREA_STATUS_UNKNOWN
     private var currentRearDisplayPresentationStatus: WindowAreaCapability.Status =
@@ -78,12 +78,12 @@
         get() {
             return callbackFlow {
                 val rearDisplayListener =
-                    Consumer<Int> { status ->
+                    Consumer2<Int> { status ->
                         updateRearDisplayAvailability(status)
                         channel.trySend(currentWindowAreaInfoMap.values.toList())
                     }
                 val rearDisplayPresentationListener =
-                    Consumer<ExtensionWindowAreaStatus> { extensionWindowAreaStatus ->
+                    Consumer2<ExtensionWindowAreaStatus> { extensionWindowAreaStatus ->
                         updateRearDisplayPresentationAvailability(extensionWindowAreaStatus)
                         channel.trySend(currentWindowAreaInfoMap.values.toList())
                     }
@@ -338,17 +338,17 @@
         private val executor: Executor,
         private val appCallback: WindowAreaSessionCallback,
         private val extensionsComponent: WindowAreaComponent
-    ) : Consumer<Int> {
+    ) : Consumer2<Int> {
 
         private var session: WindowAreaSession? = null
 
-        override fun accept(t: Int) {
-            when (t) {
+        override fun accept(value: Int) {
+            when (value) {
                 SESSION_STATE_ACTIVE -> onSessionStarted()
                 SESSION_STATE_INACTIVE -> onSessionFinished()
                 else -> {
                     if (BuildConfig.verificationMode == VerificationMode.STRICT) {
-                        Log.d(TAG, "Received an unknown session status value: $t")
+                        Log.d(TAG, "Received an unknown session status value: $value")
                     }
                     onSessionFinished()
                 }
@@ -371,16 +371,16 @@
         private val executor: Executor,
         private val windowAreaPresentationSessionCallback: WindowAreaPresentationSessionCallback,
         private val windowAreaComponent: WindowAreaComponent
-    ) : Consumer<@WindowAreaSessionState Int> {
+    ) : Consumer2<@WindowAreaSessionState Int> {
 
         private var lastReportedSessionStatus: @WindowAreaSessionState Int = SESSION_STATE_INACTIVE
 
-        override fun accept(t: @WindowAreaSessionState Int) {
+        override fun accept(value: @WindowAreaSessionState Int) {
             val previousStatus: @WindowAreaSessionState Int = lastReportedSessionStatus
-            lastReportedSessionStatus = t
+            lastReportedSessionStatus = value
 
             executor.execute {
-                when (t) {
+                when (value) {
                     SESSION_STATE_ACTIVE -> {
                         // If the last status was visible, then ACTIVE infers the content is no
                         // longer visible.
@@ -405,7 +405,7 @@
                         windowAreaPresentationSessionCallback.onSessionEnded(null)
                     }
                     else -> {
-                        Log.e(TAG, "Invalid session state value received: $t")
+                        Log.e(TAG, "Invalid session state value received: $value")
                     }
                 }
             }
diff --git a/window/window/src/main/java/androidx/window/area/utils/DeviceUtils.kt b/window/window/src/main/java/androidx/window/area/utils/DeviceUtils.kt
index b5fd522..33f241d 100644
--- a/window/window/src/main/java/androidx/window/area/utils/DeviceUtils.kt
+++ b/window/window/src/main/java/androidx/window/area/utils/DeviceUtils.kt
@@ -34,7 +34,7 @@
                     widthPixels = 1080
                     heightPixels = 2092
                     density = 2.625f
-                    densityDpi = 420
+                    densityDpi = DisplayMetrics.DENSITY_420
                 }
             )
         )
diff --git a/window/window/src/main/java/androidx/window/embedding/EmbeddingAdapter.kt b/window/window/src/main/java/androidx/window/embedding/EmbeddingAdapter.kt
index a917c31..0191f1f 100644
--- a/window/window/src/main/java/androidx/window/embedding/EmbeddingAdapter.kt
+++ b/window/window/src/main/java/androidx/window/embedding/EmbeddingAdapter.kt
@@ -36,8 +36,6 @@
 import androidx.window.embedding.SplitAttributes.SplitType.Companion.SPLIT_TYPE_EXPAND
 import androidx.window.embedding.SplitAttributes.SplitType.Companion.SPLIT_TYPE_HINGE
 import androidx.window.embedding.SplitAttributes.SplitType.Companion.ratio
-import androidx.window.extensions.core.util.function.Function
-import androidx.window.extensions.core.util.function.Predicate
 import androidx.window.extensions.embedding.ActivityRule as OEMActivityRule
 import androidx.window.extensions.embedding.ActivityRule.Builder as ActivityRuleBuilder
 import androidx.window.extensions.embedding.EmbeddingRule as OEMEmbeddingRule
@@ -55,6 +53,8 @@
 import androidx.window.extensions.embedding.SplitPlaceholderRule.Builder as SplitPlaceholderRuleBuilder
 import androidx.window.layout.WindowMetricsCalculator
 import androidx.window.layout.adapter.extensions.ExtensionsWindowLayoutInfoAdapter
+import androidx.window.reflection.JFunction2
+import androidx.window.reflection.Predicate2
 
 /** Adapter class that translates data classes between Extension and Jetpack interfaces. */
 internal class EmbeddingAdapter(private val predicateAdapter: PredicateAdapter) {
@@ -68,6 +68,7 @@
         return splitInfoList.map(this::translate)
     }
 
+    @Suppress("DEPRECATION")
     private fun translate(splitInfo: OEMSplitInfo): SplitInfo {
         return when (vendorApiLevel) {
             1 -> api1Impl.translateCompat(splitInfo)
@@ -116,9 +117,10 @@
 
     fun translateSplitAttributesCalculator(
         calculator: (SplitAttributesCalculatorParams) -> SplitAttributes
-    ): Function<OEMSplitAttributesCalculatorParams, OEMSplitAttributes> = Function { oemParams ->
-        translateSplitAttributes(calculator.invoke(translate(oemParams)))
-    }
+    ): JFunction2<OEMSplitAttributesCalculatorParams, OEMSplitAttributes> =
+        JFunction2 { oemParams ->
+            translateSplitAttributes(calculator.invoke(translate(oemParams)))
+        }
 
     @SuppressLint("NewApi")
     fun translate(params: OEMSplitAttributesCalculatorParams): SplitAttributesCalculatorParams =
@@ -150,13 +152,13 @@
             return api1Impl.translateSplitPairRuleCompat(context, rule, predicateClass)
         } else {
             val activitiesPairPredicate =
-                Predicate<AndroidPair<Activity, Activity>> { activitiesPair ->
+                Predicate2<AndroidPair<Activity, Activity>> { activitiesPair ->
                     rule.filters.any { filter ->
                         filter.matchesActivityPair(activitiesPair.first, activitiesPair.second)
                     }
                 }
             val activityIntentPredicate =
-                Predicate<AndroidPair<Activity, Intent>> { activityIntentPair ->
+                Predicate2<AndroidPair<Activity, Intent>> { activityIntentPair ->
                     rule.filters.any { filter ->
                         filter.matchesActivityIntentPair(
                             activityIntentPair.first,
@@ -165,7 +167,7 @@
                     }
                 }
             val windowMetricsPredicate =
-                Predicate<WindowMetrics> { windowMetrics ->
+                Predicate2<WindowMetrics> { windowMetrics ->
                     rule.checkParentMetrics(context, windowMetrics)
                 }
             val tag = rule.tag
@@ -242,15 +244,15 @@
             return api1Impl.translateSplitPlaceholderRuleCompat(context, rule, predicateClass)
         } else {
             val activityPredicate =
-                Predicate<Activity> { activity ->
+                Predicate2<Activity> { activity ->
                     rule.filters.any { filter -> filter.matchesActivity(activity) }
                 }
             val intentPredicate =
-                Predicate<Intent> { intent ->
+                Predicate2<Intent> { intent ->
                     rule.filters.any { filter -> filter.matchesIntent(intent) }
                 }
             val windowMetricsPredicate =
-                Predicate<WindowMetrics> { windowMetrics ->
+                Predicate2<WindowMetrics> { windowMetrics ->
                     rule.checkParentMetrics(context, windowMetrics)
                 }
             val tag = rule.tag
@@ -291,11 +293,11 @@
             return api1Impl.translateActivityRuleCompat(rule, predicateClass)
         } else {
             val activityPredicate =
-                Predicate<Activity> { activity ->
+                Predicate2<Activity> { activity ->
                     rule.filters.any { filter -> filter.matchesActivity(activity) }
                 }
             val intentPredicate =
-                Predicate<Intent> { intent ->
+                Predicate2<Intent> { intent ->
                     rule.filters.any { filter -> filter.matchesIntent(intent) }
                 }
             val builder =
diff --git a/window/window/src/main/java/androidx/window/embedding/EmbeddingCompat.kt b/window/window/src/main/java/androidx/window/embedding/EmbeddingCompat.kt
index cd3aba5..fd35178 100644
--- a/window/window/src/main/java/androidx/window/embedding/EmbeddingCompat.kt
+++ b/window/window/src/main/java/androidx/window/embedding/EmbeddingCompat.kt
@@ -30,9 +30,9 @@
 import androidx.window.embedding.EmbeddingInterfaceCompat.EmbeddingCallbackInterface
 import androidx.window.embedding.SplitController.SplitSupportStatus.Companion.SPLIT_AVAILABLE
 import androidx.window.extensions.WindowExtensionsProvider
-import androidx.window.extensions.core.util.function.Consumer
 import androidx.window.extensions.embedding.ActivityEmbeddingComponent
 import androidx.window.extensions.embedding.SplitInfo as OEMSplitInfo
+import androidx.window.reflection.Consumer2
 import java.lang.reflect.Proxy
 
 /**
@@ -82,7 +82,7 @@
             }
         } else {
             val callback =
-                Consumer<List<OEMSplitInfo>> { splitInfoList ->
+                Consumer2<List<OEMSplitInfo>> { splitInfoList ->
                     embeddingCallback.onSplitInfoChanged(adapter.translate(splitInfoList))
                 }
             embeddingExtension.setSplitInfoCallback(callback)
@@ -118,6 +118,7 @@
         embeddingExtension.invalidateTopVisibleSplitAttributes()
     }
 
+    @Suppress("DEPRECATION")
     @RequiresWindowSdkExtension(3)
     override fun updateSplitAttributes(splitInfo: SplitInfo, splitAttributes: SplitAttributes) {
         WindowSdkExtensions.getInstance().requireExtensionVersion(3)
@@ -128,6 +129,7 @@
         )
     }
 
+    @Suppress("DEPRECATION")
     @RequiresWindowSdkExtension(3)
     override fun setLaunchingActivityStack(
         options: ActivityOptions,
diff --git a/window/window/src/main/java/androidx/window/layout/adapter/extensions/MulticastConsumerApi2.kt b/window/window/src/main/java/androidx/window/layout/adapter/extensions/MulticastConsumerApi2.kt
index 1c2938c6..2262c58 100644
--- a/window/window/src/main/java/androidx/window/layout/adapter/extensions/MulticastConsumerApi2.kt
+++ b/window/window/src/main/java/androidx/window/layout/adapter/extensions/MulticastConsumerApi2.kt
@@ -20,20 +20,16 @@
 import androidx.annotation.GuardedBy
 import androidx.core.util.Consumer
 import androidx.window.RequiresWindowSdkExtension
-import androidx.window.extensions.core.util.function.Consumer as OEMConsumer
 import androidx.window.extensions.layout.WindowLayoutInfo as OEMWindowLayoutInfo
 import androidx.window.layout.WindowLayoutInfo
+import androidx.window.reflection.Consumer2
 import java.util.concurrent.locks.ReentrantLock
 import kotlin.concurrent.withLock
 
-/**
- * A [Consumer] that handles multicasting to multiple [Consumer]s downstream. Implements the
- * [androidx.window.extensions.core.util.function.Consumer] interface for compatibility with
- * extensions.
- */
+/** A [Consumer] that handles multicasting to multiple [Consumer]s downstream. */
 @RequiresWindowSdkExtension(2)
 internal class MulticastConsumerApi2(private val context: Context) :
-    Consumer<OEMWindowLayoutInfo>, OEMConsumer<OEMWindowLayoutInfo> {
+    Consumer<OEMWindowLayoutInfo>, Consumer2<OEMWindowLayoutInfo> {
     private val globalLock = ReentrantLock()
 
     @GuardedBy("globalLock") private var lastKnownValue: WindowLayoutInfo? = null
diff --git a/window/window/src/main/java/androidx/window/reflection/Consumer2.kt b/window/window/src/main/java/androidx/window/reflection/Consumer2.kt
new file mode 100644
index 0000000..d0e9d12
--- /dev/null
+++ b/window/window/src/main/java/androidx/window/reflection/Consumer2.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window.reflection
+
+import androidx.window.extensions.core.util.function.Consumer
+
+/** A duplicate of [Consumer] so that we don't crash on [AbstractMethodError]. */
+internal fun interface Consumer2<T> : Consumer<T> {
+    override fun accept(value: T)
+}
diff --git a/window/window/src/main/java/androidx/window/reflection/JFunction2.kt b/window/window/src/main/java/androidx/window/reflection/JFunction2.kt
new file mode 100644
index 0000000..d129d56
--- /dev/null
+++ b/window/window/src/main/java/androidx/window/reflection/JFunction2.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window.reflection
+
+import androidx.window.extensions.core.util.function.Function as JFunction
+
+/**
+ * A duplicate of [androidx.window.extensions.core.util.function.Function] so that we don't crash on
+ * [AbstractMethodError].
+ */
+internal fun interface JFunction2<T, U> : JFunction<T, U> {
+    override fun apply(t: T): U
+}
diff --git a/window/window/src/main/java/androidx/window/reflection/Predicate2.kt b/window/window/src/main/java/androidx/window/reflection/Predicate2.kt
new file mode 100644
index 0000000..25096b9
--- /dev/null
+++ b/window/window/src/main/java/androidx/window/reflection/Predicate2.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window.reflection
+
+import androidx.window.extensions.core.util.function.Predicate
+
+/** A dulplicate of [Predicate] so that we don't crash on [AbstractMethodError]. */
+internal fun interface Predicate2<T> : Predicate<T> {
+    override fun test(t: T): Boolean
+}
diff --git a/window/window/src/test/java/androidx/window/embedding/RequiresWindowSdkExtensionTests.kt b/window/window/src/test/java/androidx/window/embedding/RequiresWindowSdkExtensionTests.kt
index 5ad6a4e..3cd660b 100644
--- a/window/window/src/test/java/androidx/window/embedding/RequiresWindowSdkExtensionTests.kt
+++ b/window/window/src/test/java/androidx/window/embedding/RequiresWindowSdkExtensionTests.kt
@@ -20,6 +20,7 @@
 import android.content.Context
 import android.os.Binder
 import android.os.Build
+import android.os.IBinder
 import androidx.annotation.RequiresApi
 import androidx.window.RequiresWindowSdkExtension
 import androidx.window.WindowSdkExtensions
@@ -65,6 +66,7 @@
     private lateinit var mockAnnotations: AutoCloseable
     private lateinit var embeddingCompat: EmbeddingCompat
 
+    @Suppress("DEPRECATION")
     @Before
     fun setUp() {
         mockAnnotations = MockitoAnnotations.openMocks(this)
@@ -86,6 +88,7 @@
         mockAnnotations.close()
     }
 
+    @Suppress("DEPRECATION")
     @Test
     fun testVendorApiLevel1() {
         testRule.overrideExtensionVersion(1)
@@ -108,7 +111,8 @@
         assertThrows(UnsupportedOperationException::class.java) {
             embeddingCompat.updateSplitAttributes(TEST_SPLIT_INFO, TEST_SPLIT_ATTRIBUTES)
         }
-        verify(embeddingExtension, never()).updateSplitAttributes(any(), any())
+        verify(embeddingExtension, never())
+            .updateSplitAttributes(any<IBinder>(), any<OemSplitAttributes>())
 
         assertThrows(UnsupportedOperationException::class.java) {
             embeddingCompat.invalidateTopVisibleSplitAttributes()
@@ -116,6 +120,7 @@
         verify(embeddingExtension, never()).invalidateTopVisibleSplitAttributes()
     }
 
+    @Suppress("DEPRECATION")
     @Test
     fun testVendorApiLevel2() {
         testRule.overrideExtensionVersion(2)
@@ -137,7 +142,8 @@
         assertThrows(UnsupportedOperationException::class.java) {
             embeddingCompat.updateSplitAttributes(TEST_SPLIT_INFO, TEST_SPLIT_ATTRIBUTES)
         }
-        verify(embeddingExtension, never()).updateSplitAttributes(any(), any())
+        verify(embeddingExtension, never())
+            .updateSplitAttributes(any<IBinder>(), any<OemSplitAttributes>())
 
         assertThrows(UnsupportedOperationException::class.java) {
             embeddingCompat.invalidateTopVisibleSplitAttributes()
@@ -145,6 +151,7 @@
         verify(embeddingExtension, never()).invalidateTopVisibleSplitAttributes()
     }
 
+    @Suppress("DEPRECATION")
     @Test
     fun testVendorApiLevel3() {
         testRule.overrideExtensionVersion(3)
diff --git a/work/work-multiprocess/src/androidTest/java/androidx/work/multiprocess/RemoteWorkManagerClientTest.kt b/work/work-multiprocess/src/androidTest/java/androidx/work/multiprocess/RemoteWorkManagerClientTest.kt
index 112f8a6..2831ee8 100644
--- a/work/work-multiprocess/src/androidTest/java/androidx/work/multiprocess/RemoteWorkManagerClientTest.kt
+++ b/work/work-multiprocess/src/androidTest/java/androidx/work/multiprocess/RemoteWorkManagerClientTest.kt
@@ -136,7 +136,7 @@
     @Test
     @MediumTest
     @Suppress("UNCHECKED_CAST")
-    public fun executeWhenSessionIsInvalid() {
+    public fun cleanUpWhenSessionIsInvalid() {
         if (Build.VERSION.SDK_INT <= 27) {
             // Exclude <= API 27, from tests because it causes a SIGSEGV.
             return
@@ -155,7 +155,7 @@
             exception = throwable
         }
         assertNotNull(exception)
-        assertTrue(exception!!.message!!.contains("Something bad happened"))
+        verify(mClient).cleanUp()
         verify(mRunnableScheduler, atLeastOnce())
             .scheduleWithDelay(anyLong(), any(Runnable::class.java))
     }
diff --git a/work/work-multiprocess/src/main/java/androidx/work/multiprocess/ListenableWorkerImplClient.java b/work/work-multiprocess/src/main/java/androidx/work/multiprocess/ListenableWorkerImplClient.java
index 170c1b2..9884c9f 100644
--- a/work/work-multiprocess/src/main/java/androidx/work/multiprocess/ListenableWorkerImplClient.java
+++ b/work/work-multiprocess/src/main/java/androidx/work/multiprocess/ListenableWorkerImplClient.java
@@ -16,18 +16,21 @@
 
 package androidx.work.multiprocess;
 
+import static android.content.Context.BIND_AUTO_CREATE;
+
 import android.annotation.SuppressLint;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.os.IBinder;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
 import androidx.annotation.VisibleForTesting;
 import androidx.work.Logger;
-import androidx.work.multiprocess.ServiceBinding.Session;
+import androidx.work.impl.utils.futures.SettableFuture;
 
 import com.google.common.util.concurrent.ListenableFuture;
 
@@ -49,7 +52,7 @@
     final Executor mExecutor;
 
     private final Object mLock;
-    private Session<IListenableWorkerImpl> mConnection;
+    private Connection mConnection;
 
     public ListenableWorkerImplClient(
             @NonNull Context context,
@@ -69,15 +72,23 @@
 
         synchronized (mLock) {
             if (mConnection == null) {
-                Logger.get().debug(TAG,
-                        "Binding to " + component.getPackageName() + ", "
-                                + component.getClassName());
-                Intent intent = new Intent();
-                intent.setComponent(component);
-                mConnection = ServiceBinding.bindToService(mContext, intent,
-                        IListenableWorkerImpl.Stub::asInterface, TAG);
+                Logger.get().debug(TAG, "Binding to " + component.getPackageName() + ", "
+                        + component.getClassName());
+
+                mConnection = new Connection();
+                try {
+                    Intent intent = new Intent();
+                    intent.setComponent(component);
+                    boolean bound = mContext.bindService(intent, mConnection, BIND_AUTO_CREATE);
+                    if (!bound) {
+                        unableToBind(mConnection,
+                                new RuntimeException("Unable to bind to service"));
+                    }
+                } catch (Throwable throwable) {
+                    unableToBind(mConnection, throwable);
+                }
             }
-            return mConnection.mConnectedFuture;
+            return mConnection.mFuture;
         }
     }
 
@@ -123,7 +134,56 @@
      */
     @Nullable
     @VisibleForTesting
-    Session<IListenableWorkerImpl> getConnection() {
+    public Connection getConnection() {
         return mConnection;
     }
+
+    /**
+     * The implementation of {@link ServiceConnection} that handles changes in the connection.
+     *
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public static class Connection implements ServiceConnection {
+        private static final String TAG = Logger.tagWithPrefix("ListenableWorkerImplSession");
+
+        final SettableFuture<IListenableWorkerImpl> mFuture;
+
+        public Connection() {
+            mFuture = SettableFuture.create();
+        }
+
+        @Override
+        public void onServiceConnected(
+                @NonNull ComponentName componentName,
+                @NonNull IBinder iBinder) {
+            Logger.get().debug(TAG, "Service connected");
+            IListenableWorkerImpl iListenableWorkerImpl =
+                    IListenableWorkerImpl.Stub.asInterface(iBinder);
+            mFuture.set(iListenableWorkerImpl);
+        }
+
+        @Override
+        public void onServiceDisconnected(@NonNull ComponentName componentName) {
+            Logger.get().warning(TAG, "Service disconnected");
+            mFuture.setException(new RuntimeException("Service disconnected"));
+        }
+
+        @Override
+        public void onBindingDied(@NonNull ComponentName name) {
+            Logger.get().warning(TAG, "Binding died");
+            mFuture.setException(new RuntimeException("Binding died"));
+        }
+
+        @Override
+        public void onNullBinding(@NonNull ComponentName name) {
+            Logger.get().error(TAG, "Unable to bind to service");
+            mFuture.setException(
+                    new RuntimeException("Cannot bind to service " + name));
+        }
+    }
+
+    private static void unableToBind(@NonNull Connection session, @NonNull Throwable throwable) {
+        Logger.get().error(TAG, "Unable to bind to service", throwable);
+        session.mFuture.setException(throwable);
+    }
 }
diff --git a/work/work-multiprocess/src/main/java/androidx/work/multiprocess/RemoteWorkManagerClient.java b/work/work-multiprocess/src/main/java/androidx/work/multiprocess/RemoteWorkManagerClient.java
index d6e4801..2c329fa 100644
--- a/work/work-multiprocess/src/main/java/androidx/work/multiprocess/RemoteWorkManagerClient.java
+++ b/work/work-multiprocess/src/main/java/androidx/work/multiprocess/RemoteWorkManagerClient.java
@@ -16,11 +16,16 @@
 
 package androidx.work.multiprocess;
 
+import static android.content.Context.BIND_AUTO_CREATE;
+
 import static androidx.work.multiprocess.RemoteClientUtilsKt.map;
 
 import android.annotation.SuppressLint;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
 import android.os.RemoteException;
 
 import androidx.annotation.NonNull;
@@ -29,7 +34,6 @@
 import androidx.annotation.VisibleForTesting;
 import androidx.arch.core.util.Function;
 import androidx.work.Data;
-import androidx.work.DirectExecutor;
 import androidx.work.ExistingPeriodicWorkPolicy;
 import androidx.work.ExistingWorkPolicy;
 import androidx.work.ForegroundInfo;
@@ -43,7 +47,7 @@
 import androidx.work.WorkRequest;
 import androidx.work.impl.WorkContinuationImpl;
 import androidx.work.impl.WorkManagerImpl;
-import androidx.work.multiprocess.ServiceBinding.Session;
+import androidx.work.impl.utils.futures.SettableFuture;
 import androidx.work.multiprocess.parcelable.ParcelConverters;
 import androidx.work.multiprocess.parcelable.ParcelableForegroundRequestInfo;
 import androidx.work.multiprocess.parcelable.ParcelableUpdateRequest;
@@ -58,6 +62,7 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.UUID;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
 
 /**
@@ -80,7 +85,7 @@
     public static final Function<byte[], Void> sVoidMapper = input -> null;
 
     // Synthetic access
-    ServiceBinding.Session<IWorkManagerImpl> mSession;
+    Session mSession;
 
     final Context mContext;
     final WorkManagerImpl mWorkManager;
@@ -340,7 +345,7 @@
      * @return The current {@link Session} in use by {@link RemoteWorkManagerClient}.
      */
     @Nullable
-    ServiceBinding.Session<IWorkManagerImpl> getCurrentSession() {
+    public Session getCurrentSession() {
         return mSession;
     }
 
@@ -380,6 +385,13 @@
     ListenableFuture<byte[]> execute(
             @NonNull final ListenableFuture<IWorkManagerImpl> session,
             @NonNull final RemoteDispatcher<IWorkManagerImpl> dispatcher) {
+        session.addListener(() -> {
+            try {
+                session.get();
+            } catch (ExecutionException | InterruptedException exception) {
+                cleanUp();
+            }
+        }, mExecutor);
         ListenableFuture<byte[]> future = RemoteExecuteKt.execute(mExecutor, session,
                 dispatcher);
         future.addListener(() -> {
@@ -397,20 +409,21 @@
     ListenableFuture<IWorkManagerImpl> getSession(@NonNull Intent intent) {
         synchronized (mLock) {
             mSessionIndex += 1;
-            ListenableFuture<IWorkManagerImpl> resultFuture;
             if (mSession == null) {
-                mSession = ServiceBinding.bindToService(mContext, intent,
-                        IWorkManagerImpl.Stub::asInterface, TAG);
-                // reading future right away, because `this::cleanUp` will synchronously
-                // set mSession to null.
-                resultFuture = mSession.mConnectedFuture;
-                mSession.mDisconnectedFuture.addListener(this::cleanUp, DirectExecutor.INSTANCE);
-            } else {
-                resultFuture = mSession.mConnectedFuture;
+                Logger.get().debug(TAG, "Creating a new session");
+                mSession = new Session(this);
+                try {
+                    boolean bound = mContext.bindService(intent, mSession, BIND_AUTO_CREATE);
+                    if (!bound) {
+                        unableToBind(mSession, new RuntimeException("Unable to bind to service"));
+                    }
+                } catch (Throwable throwable) {
+                    unableToBind(mSession, throwable);
+                }
             }
             // Reset session tracker.
             mRunnableScheduler.cancel(mSessionTracker);
-            return resultFuture;
+            return mSession.mFuture;
         }
     }
 
@@ -425,6 +438,11 @@
         }
     }
 
+    private void unableToBind(@NonNull Session session, @NonNull Throwable throwable) {
+        Logger.get().error(TAG, "Unable to bind to service", throwable);
+        session.mFuture.setException(throwable);
+    }
+
     /**
      * @return the intent that is used to bind to the instance of {@link IWorkManagerImpl}.
      */
@@ -433,6 +451,59 @@
     }
 
     /**
+     * The implementation of {@link ServiceConnection} that handles changes in the connection.
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public static class Session implements ServiceConnection {
+        private static final String TAG = Logger.tagWithPrefix("RemoteWMgr.Connection");
+
+        final SettableFuture<IWorkManagerImpl> mFuture;
+        final RemoteWorkManagerClient mClient;
+
+        public Session(@NonNull RemoteWorkManagerClient client) {
+            mClient = client;
+            mFuture = SettableFuture.create();
+        }
+
+        @Override
+        public void onServiceConnected(
+                @NonNull ComponentName componentName,
+                @NonNull IBinder iBinder) {
+            Logger.get().debug(TAG, "Service connected");
+            IWorkManagerImpl iWorkManagerImpl = IWorkManagerImpl.Stub.asInterface(iBinder);
+            mFuture.set(iWorkManagerImpl);
+        }
+
+        @Override
+        public void onServiceDisconnected(@NonNull ComponentName componentName) {
+            Logger.get().debug(TAG, "Service disconnected");
+            mFuture.setException(new RuntimeException("Service disconnected"));
+            mClient.cleanUp();
+        }
+
+        @Override
+        public void onBindingDied(@NonNull ComponentName name) {
+            onBindingDied();
+        }
+
+        /**
+         * Clean-up client when a binding dies.
+         */
+        public void onBindingDied() {
+            Logger.get().debug(TAG, "Binding died");
+            mFuture.setException(new RuntimeException("Binding died"));
+            mClient.cleanUp();
+        }
+
+        @Override
+        public void onNullBinding(@NonNull ComponentName name) {
+            Logger.get().error(TAG, "Unable to bind to service");
+            mFuture.setException(
+                    new RuntimeException("Cannot bind to service " + name));
+        }
+    }
+
+    /**
      * A {@link Runnable} that enforces a TTL for a {@link RemoteWorkManagerClient} session.
      */
     public static class SessionTracker implements Runnable {
@@ -448,7 +519,7 @@
             final long preLockIndex = mClient.getSessionIndex();
             synchronized (mClient.getSessionLock()) {
                 final long sessionIndex = mClient.getSessionIndex();
-                final Session<IWorkManagerImpl> currentSession = mClient.getCurrentSession();
+                final Session currentSession = mClient.getCurrentSession();
                 // We check for a session index here. This is because if the index changes
                 // while we acquire a lock, that would mean that a new session request came through.
                 if (currentSession != null) {
diff --git a/work/work-multiprocess/src/main/java/androidx/work/multiprocess/ServiceBinding.java b/work/work-multiprocess/src/main/java/androidx/work/multiprocess/ServiceBinding.java
deleted file mode 100644
index cad2faf..0000000
--- a/work/work-multiprocess/src/main/java/androidx/work/multiprocess/ServiceBinding.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.work.multiprocess;
-
-import static android.content.Context.BIND_AUTO_CREATE;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.IBinder;
-import android.os.IInterface;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.RestrictTo;
-import androidx.core.util.Function;
-import androidx.work.Logger;
-import androidx.work.impl.utils.futures.SettableFuture;
-
-class ServiceBinding {
-
-    private ServiceBinding() {
-    }
-
-    static <T extends IInterface> Session<T> bindToService(@NonNull Context context,
-            @NonNull Intent intent,
-            @NonNull Function<IBinder, T> asInterface,
-            @NonNull String loggingTag) {
-        Logger.get().debug(loggingTag, "Binding via " + intent);
-        Session<T> session = new Session<>(loggingTag, asInterface);
-        try {
-            boolean bound = context.bindService(intent, session, BIND_AUTO_CREATE);
-            if (!bound) {
-                session.resolveClosedConnection(new RuntimeException("Unable to bind to service"));
-            }
-        } catch (Throwable throwable) {
-            session.resolveClosedConnection(throwable);
-        }
-        return session;
-    }
-
-    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-    static class Session<T extends IInterface> implements ServiceConnection {
-        private final String mLogTag;
-        final SettableFuture<T> mConnectedFuture;
-        final SettableFuture<T> mDisconnectedFuture;
-        final Function<IBinder, T> mAsInterface;
-
-        public Session(String loggingTag, @NonNull Function<IBinder, T> asInterface) {
-            mAsInterface = asInterface;
-            mConnectedFuture = SettableFuture.create();
-            mDisconnectedFuture = SettableFuture.create();
-            mLogTag = loggingTag;
-        }
-
-        @Override
-        public void onServiceConnected(
-                @NonNull ComponentName componentName,
-                @NonNull IBinder iBinder) {
-            mConnectedFuture.set(mAsInterface.apply(iBinder));
-        }
-
-        @Override
-        public void onServiceDisconnected(@NonNull ComponentName componentName) {
-            Logger.get().debug(mLogTag, "Service disconnected");
-            resolveClosedConnection(new RuntimeException("Service disconnected"));
-        }
-
-        @Override
-        public void onBindingDied(@NonNull ComponentName name) {
-            onBindingDied();
-        }
-
-        /**
-         * Clean-up client when a binding dies.
-         */
-        public void onBindingDied() {
-            Logger.get().debug(mLogTag, "Binding died");
-            resolveClosedConnection(new RuntimeException("Binding died"));
-        }
-
-        @Override
-        public void onNullBinding(@NonNull ComponentName name) {
-            Logger.get().error(mLogTag, "Unable to bind to service");
-            resolveClosedConnection(new RuntimeException("Cannot bind to service " + name));
-        }
-
-        private void resolveClosedConnection(Throwable throwable) {
-            // finishing connected future, in case onServiceDisconnected hasn't been
-            // called.
-            mConnectedFuture.setException(throwable);
-            mDisconnectedFuture.set(null);
-        }
-    }
-}
diff --git a/work/work-runtime/proguard-rules.pro b/work/work-runtime/proguard-rules.pro
index fb15989..97e2bba 100644
--- a/work/work-runtime/proguard-rules.pro
+++ b/work/work-runtime/proguard-rules.pro
@@ -1,5 +1,5 @@
 -keep class * extends androidx.work.Worker
--keep class * extends androidx.work.InputMerger
+-keep class * extends androidx.work.InputMerger { void <init>(); }
 # Keep all constructors on ListenableWorker, Worker
 -keep public class * extends androidx.work.ListenableWorker {
     public <init>(...);
diff --git a/work/work-testing/src/main/java/androidx/work/testing/TestListenableWorkerBuilder.kt b/work/work-testing/src/main/java/androidx/work/testing/TestListenableWorkerBuilder.kt
index 24fe616..1f2636d 100644
--- a/work/work-testing/src/main/java/androidx/work/testing/TestListenableWorkerBuilder.kt
+++ b/work/work-testing/src/main/java/androidx/work/testing/TestListenableWorkerBuilder.kt
@@ -28,6 +28,7 @@
  * @param W The subtype of [ListenableWorker]
  * @param context The application [Context]
  * @param inputData The input data for the [ListenableWorker]
+ * @param tags The tags associated with this [ListenableWorker]
  * @param runAttemptCount The run attempt count of the [ListenableWorker]
  * @param triggeredContentUris The list of triggered content [Uri]s
  * @param triggeredContentAuthorities The list of triggered content authorities
diff --git a/work/work-testing/src/main/java/androidx/work/testing/TestWorkerBuilder.kt b/work/work-testing/src/main/java/androidx/work/testing/TestWorkerBuilder.kt
index 4af121f..30e93bc 100644
--- a/work/work-testing/src/main/java/androidx/work/testing/TestWorkerBuilder.kt
+++ b/work/work-testing/src/main/java/androidx/work/testing/TestWorkerBuilder.kt
@@ -30,6 +30,7 @@
  * @param context The application [Context]
  * @param executor The [Executor] that the [Worker] runs on
  * @param inputData The input data for the [Worker]
+ * @param tags The tags associated with this [Worker]
  * @param runAttemptCount The run attempt count of the [Worker]
  * @param triggeredContentUris The list of triggered content [Uri]s
  * @param triggeredContentAuthorities The list of triggered content authorities